An Amazon EKS cluster created with defaults has a public API endpoint, no control plane logs, no network policy and worker nodes you must patch yourself, and AWS's shared responsibility model leaves every one of those with you. AWS runs the control plane, including the API server and etcd, but node security, pod security, network security and logging sit on the customer side for EC2-based clusters. This guide covers the non-identity layers of EKS hardening: choosing between Auto Mode, managed node groups and Fargate, the API endpoint, VPC CNI network policies, Pod Security admission, envelope encryption, logging and GuardDuty, and the CIS Amazon EKS Benchmark. It is written for platform engineers, cloud security architects and auditors working with EKS. Access entries, Pod Identity, IRSA and node role exposure are covered in depth in the EKS identity guide and only summarised here.
Key takeaways
- Pick the compute model first: EKS Auto Mode gives immutable Bottlerocket nodes with SELinux enforcing, a read-only root filesystem, no SSH or SSM access and a 21-day maximum node lifetime; managed node groups leave AMI upgrades to you.
- Make the API endpoint private: the public endpoint is enabled by default; disable it, or at minimum restrict
publicAccessCidrsand enable the private endpoint so node traffic stays in the VPC. - Turn on control plane logs: none of the five log types is sent to CloudWatch Logs by default, and the
auditandauthenticatorlogs are the ones investigations need. - Enforce pod and network policy: Pod Security admission with
enforce,auditandwarnlabels, and VPC CNI network policies, including cluster-wideClusterNetworkPolicydeny rules, contain a compromised pod. - Protect the key that protects the cluster: Kubernetes API data is envelope encrypted by default on 1.28 and later; if you bring a customer managed KMS key, deleting it makes the cluster unrecoverable.
How identity and access work in EKS
A short recap, because every control below assumes it. IAM authenticates requests to the Kubernetes API and Kubernetes RBAC authorises them, with access entries as the AWS-side mapping from IAM principals to cluster permissions. Pods reach AWS APIs through EKS Pod Identity or IAM Roles for Service Accounts (IRSA), and the node IAM role must not be reachable from ordinary pods through the instance metadata service. The non-identity point that matters here is that the network path to the API server and the kubelet is part of access control: the cluster security group governs the private endpoint and the kubelet API used by kubectl exec, attach, cp, logs and port-forward. See the EKS Identity Hardening Guide and the Kubernetes RBAC Guide.
Admin roles and privileged access
Privilege in EKS also comes from settings that let someone bypass the Kubernetes API altogether.
- Node access: in Auto Mode SSH and SSM access to nodes are disallowed. On managed or self-managed node groups, treat SSH keys, SSM Session Manager permissions on node instances and the ability to change launch templates as cluster-admin equivalents, because they reach the kubelet and every pod on the node.
- Key administration: whoever can disable or schedule deletion of the KMS key used for envelope encryption can take the cluster down. Keep that permission with a small key administration role, separate from cluster administrators.
- Endpoint changes:
eks:UpdateClusterConfigcan re-open the public endpoint or change logging. Restrict it and alert on it. - Policy engine administrators: whoever can change Kyverno or OPA Gatekeeper policies, namespace Pod Security labels or
ClusterNetworkPolicyobjects can switch off the guardrails in this guide. - Lock-out risk: AWS warns that before disabling public access you must make sure the IAM principal you use, including bastion or IDE credentials, is mapped in the cluster's access configuration, or you may lock yourself out. Keep a documented break-glass path; see the Break-Glass Emergency Access Guide.
Integrations, API tokens and service accounts
Most EKS credential exposure is not in IAM at all but in Kubernetes objects and pod settings.
| Exposure | Why it matters | Hardened setting |
|---|---|---|
| Service account tokens automounted in every pod | A compromised pod can call the Kubernetes API with whatever its service account allows | automountServiceAccountToken: false on pods or ServiceAccounts that do not call the API |
| Kubernetes Secrets in manifests and Git | Base64 is encoding, not encryption | External secret store, pull-only registry credentials, secret scanning in CI |
| Node role reachable through IMDS | Pods inherit node permissions | Pod Identity or IRSA, and block pod access to node metadata; note that VPC CNI network policies may need an explicit IMDS allow rule for pods that legitimately use it |
| Docker socket mounts and Docker-in-Docker | Effective control of the node | Build with Kaniko, Buildah or CodeBuild; isolate CI/CD clusters from general workloads |
| Service discovery environment variables | Pods learn every service in the namespace | enableServiceLinks: false where not needed |
The exposed Kubernetes Secrets research of 2023 shows the cost: registry credentials stored in Kubernetes Secrets were committed to public GitHub repositories, and one SAP artifact repository key granted access to over 95 million artifacts. See the Kubernetes Secrets Security Guide and the Kubernetes Service Account Token Guide.
Logging and detection
EKS control plane logging is off by default and each log type must be enabled individually. The types are api, audit, authenticator, controllerManager and scheduler, delivered to the CloudWatch Logs group /aws/eks/<cluster-name>/cluster at standard ingestion and storage prices. Set the log group's retention explicitly, because EKS does not. The authenticator log is unique to EKS and records IAM-based authentication to the cluster.
GuardDuty EKS Protection analyses EKS audit logs through its own independent stream, so it works even if control plane logging is off; but you only have the logs for your own investigation if you enable control plane logging. EKS Runtime Monitoring is a separate GuardDuty feature for node and container runtime activity. CloudTrail records EKS API calls such as UpdateClusterConfig, CreateAccessEntry and AssociateAccessPolicy. See the AWS CloudTrail Guide.
| What to detect | Source | ATT&CK v20 |
|---|---|---|
| Anonymous or unexpected identity calling the API | audit, authenticator, GuardDuty EKS Protection | T1552.007 Container API |
pods/exec into production workloads | audit | T1609 Container Administration Command |
| Privileged, hostPath or hostNetwork pod created | audit, admission controller logs | T1610 Deploy Container |
| Container escape behaviour on a node | GuardDuty Runtime Monitoring | T1611 Escape to Host |
| Bulk list and watch across namespaces | audit | T1613 Container and Resource Discovery |
| Public endpoint re-enabled or logging turned off | CloudTrail UpdateClusterConfig | T1685 Disable or Modify Tools (logging) |
| Crypto-mining pods | GuardDuty findings, node CPU metrics | T1496 Resource Hijacking |
Metrics: percentage of clusters with the public endpoint disabled or CIDR restricted; percentage with all five control plane log types enabled; percentage of namespaces with Pod Security enforce at baseline or restricted; node AMI age (days behind the latest EKS-optimised or Bottlerocket release); GuardDuty EKS findings of high severity open more than 7 days; clusters in extended support.
Hardening baseline
Choosing the compute model
| Area | EKS Auto Mode | Managed node groups | Fargate |
|---|---|---|---|
| Node OS | Bottlerocket variants, immutable AMI, SELinux enforcing, read-only root filesystem | EKS-optimised AMI or your own; you choose and harden it | AWS-managed, no node access |
| Node access | SSH and SSM disallowed | Possible; restrict | None |
| Patching | Automatic; nodes replaced within a 21-day maximum lifetime, respecting Pod and NodePool Disruption Budgets | You upgrade node groups to the latest AMI through the EKS API, CLI, CloudFormation or console | AWS secures the underlying instance and runtime |
| Privileged pods, hostNetwork, hostPort | Governed by your Pod Security and policy settings | Governed by your Pod Security and policy settings | Not allowed |
| VPC CNI network policies | Network policy enforcement is part of managed pod networking | Supported on EC2 Linux nodes | Not supported |
| CIS Amazon EKS Benchmark node checks | Largely handled by the managed node design; verify | Fully your responsibility | Not applicable (the benchmark applies to EC2 nodes) |
Decision guidance: Auto Mode suits most new clusters and smaller teams, because node hardening and patching stop being a recurring task and nodes cannot drift. Managed node groups suit teams that need custom AMIs, specific kernel modules or node agents, at the cost of owning node patching and CIS node checks. Fargate removes node access entirely and blocks privileged pods, which suits untrusted or multi-tenant workloads, but it does not support VPC CNI network policies, so isolation must come from other controls. Large estates often standardise on one model per cluster type and enforce the rest with policy as code.
API endpoint and network
- Endpoint mode: set
endpointPrivateAccess=trueandendpointPublicAccess=falsewhere operators can reach the VPC through Transit Gateway, VPN, a bastion or CloudShell's VPC environment. A private endpoint needsenableDnsHostnamesandenableDnsSupporton the VPC andAmazonProvidedDNSin the DHCP options. - If public access must stay: restrict
publicAccessCidrsand enable the private endpoint too, so node-to-control-plane traffic uses the private path. If you restrict CIDRs without the private endpoint, the list must include the addresses nodes and Fargate pods use. AWS advises choosing one endpoint, not both, for clusters with hybrid nodes. - Network policy: VPC CNI 1.21.0 or later supports standard
NetworkPolicyand adminClusterNetworkPolicyobjects on EC2 Linux nodes. Admin-tier Deny rules cannot be overridden by namespace policies, which makes them the right tool for protecting sensitive namespaces; Baseline-tier policies act as overridable defaults. Mind the documented limits: 24 port and protocol combinations per CIDR, enforcement on the primary interface only, and less reliable enforcement for standalone pods without owner references. Do not edit the EKS-managedPolicyEndpointresources. - Egress: run nodes in private subnets with controlled egress through NAT or a proxy, and use VPC endpoints for ECR, S3 and STS. See the Amazon VPC Security Guide.
Pod security
PodSecurityPolicy was removed in Kubernetes 1.25. Use Pod Security Standards through Pod Security admission, or policy-as-code tools such as Kyverno or OPA Gatekeeper where you need custom rules. Label namespaces with pod-security.kubernetes.io/enforce, audit and warn: AWS notes that with enforce alone a violating Deployment is accepted but its pods are never created, and the reason appears only in the Deployment status. A gradual path is enforce: baseline with warn: restricted, then restricted everywhere it fits. In pod specs, set runAsNonRoot: true, allowPrivilegeEscalation: false, capabilities.drop: ["ALL"], seccompProfile.type: RuntimeDefault and readOnlyRootFilesystem: true (not possible on Windows containers), and set requests and limits on every container. See the Kubernetes Admission Control Guide.
Encryption of cluster data
On Kubernetes 1.28 and later, EKS envelope encrypts all Kubernetes API data, including Secrets and ConfigMaps, using KMS v2 with an AWS-owned key encryption key by default; this does not cover data on nodes or EBS volumes. You can bring a customer managed KMS key instead. If that key is disabled, the API server fails on restart with KMS_KEY_DISABLED and you have 30 days to re-enable it before the cluster is automatically upgraded and recovery is not guaranteed; if the key is deleted (KMS_KEY_NOT_FOUND or KMS_GRANT_REVOKED), the cluster cannot be recovered. AWS recommends least-privilege key policies, a CloudWatch alarm on key state and API-level backups with a tool such as Velero. See the Cloud Customer-Managed Keys and BYOK/HYOK Decision Guide.
CIS Amazon EKS Benchmark
The CIS Amazon EKS Benchmark, introduced in July 2020, drops the control plane section of the CIS Kubernetes Benchmark because AWS manages the control plane. Its sections cover control plane logging configuration, worker node configuration files and the kubelet, Kubernetes policies, and managed services recommendations. It applies to EC2 nodes, managed and self-managed, not to Fargate, and node operating system hardening is covered by the relevant CIS OS benchmark. Run kube-bench against worker nodes in a pipeline or as a scheduled job, and check which benchmark version your tool evaluates against the current CIS release.
Phased rollout
- Inventory: list clusters with Kubernetes version, compute model, endpoint mode, logging status, CNI version, network policy status and KMS key ownership.
- Low-risk changes first: enable all five control plane log types with retention, enable GuardDuty EKS Protection, and set
auditandwarnPod Security labels on every namespace. - Measure: run kube-bench on nodes and collect two to four weeks of Pod Security warnings and policy-engine audit results.
- Pilot ring: on a non-production cluster, enable the private endpoint and restrict or disable the public one, apply default-deny NetworkPolicies and an Admin-tier deny for sensitive namespaces, and move to Auto Mode or Bottlerocket nodes.
- Enforce: switch Pod Security to
enforceper namespace, roll out network policies and endpoint changes to production cluster by cluster, and add SCP or Config checks that block public endpoints on new clusters. - Roll back: namespace labels can be returned to
warn, network policies removed per namespace and public endpoint access re-enabled throughUpdateClusterConfig; keep a tested break-glass path before cutting public access.
Framework mapping
| EKS control | NIST SP 800-53 Rev. 5 | NIST CSF 2.0 | CIS Controls v8.1 | ISO/IEC 27001:2022 |
|---|---|---|---|---|
| CIS EKS Benchmark, node baseline | CM-2, CM-6 | PR.PS-01 | 4 | A.8.9 |
| Auto Mode or AMI patching | SI-2 | PR.PS-02 | 7 | A.8.8 |
| Private endpoint, network policies | SC-7, AC-4 | PR.IR-01 | 12, 13 | A.8.20, A.8.22 |
| Pod Security admission | CM-7, AC-6 | PR.PS-01 | 4 | A.8.9 |
| Envelope encryption and key control | SC-12, SC-28 | PR.DS-01 | 3 | A.8.24 |
| Control plane logs, GuardDuty | AU-2, AU-12, SI-4 | DE.CM-09 | 8 | A.8.15, A.8.16 |
Common misconfigurations
- Public endpoint open to 0.0.0.0/0 for years: the default stays because nobody owns the change, leaving the API reachable by anyone holding a valid credential.
- Control plane logs never enabled: GuardDuty raises a finding but there is no
auditlog in the account to investigate it with. - Pod Security in enforce only: deployments appear to succeed while pods never start, so teams remove the label instead of fixing the pod spec.
- Network policy assumed on Fargate or Windows: VPC CNI network policies do not apply there, so isolation that looks configured is not enforced.
- Stale node AMIs: managed node groups are not upgraded after the control plane, leaving kubelet and kernel vulnerabilities on nodes for months.
- Customer managed key without protection: a shared KMS key used for several clusters is disabled or scheduled for deletion during a clean-up, and the clusters fail on the next API server restart.
Practitioner checklist
- Each cluster has a deliberate compute model, with Auto Mode or Bottlerocket preferred where custom nodes are not needed.
- The public API endpoint is disabled, or restricted with
publicAccessCidrsand paired with the private endpoint. - All five control plane log types are enabled with a set retention, and GuardDuty EKS Protection and Runtime Monitoring are on.
- Every namespace carries Pod Security labels, with
enforceat baseline or restricted andauditandwarnalongside. - Default-deny NetworkPolicies exist per namespace and Admin-tier
ClusterNetworkPolicydenies protect sensitive namespaces. - Pods that do not call the Kubernetes API do not mount service account tokens, and no pod mounts the Docker socket.
- Any customer managed KMS key for envelope encryption has restricted key administration, a key state alarm and API-level backups.
- Managed node group AMIs are no more than one release behind, and kube-bench runs against nodes on a schedule.
- CloudTrail alerts fire on
UpdateClusterConfigchanges to endpoint access or logging.
Standards and references
- AWS: Amazon EKS Best Practices Guide, Security
- AWS: Automate cluster infrastructure with EKS Auto Mode
- AWS: Cluster API server endpoint
- AWS: Send control plane logs to CloudWatch Logs
- AWS: Limit pod traffic with Kubernetes network policies
- AWS: Default envelope encryption for all Kubernetes API data
- AWS: EKS Best Practices, Pod Security
- AWS: Introducing the CIS Amazon EKS Benchmark
Related NHI Mgmt Group resources: EKS Identity Hardening Guide · Kubernetes Security Guide · GKE Security Hardening Guide · Kubernetes Cluster Compromise Playbook