AWS EKS Security: Complete Hardening Guide for Production
AWS EKS security requires a multi-layered approach that goes far beyond default configurations. Production EKS clusters face unique security challenges that combine Kubernetes-native risks with AWS-specific attack vectors. This guide covers the essential security controls every EKS engineer needs to implement.
EKS Control Plane Security
API Server Access Control
The EKS API server endpoint represents your cluster's primary attack surface. By default, EKS creates a public endpoint accessible from anywhere on the internet.
Configure private endpoint access:
aws eks modify-cluster \
--region us-west-2 \
--name production-cluster \
--resources-vpc-config endpointPublicAccess=false,endpointPrivateAccess=true
For hybrid access, restrict public endpoint CIDR blocks:
aws eks modify-cluster \
--region us-west-2 \
--name production-cluster \
--resources-vpc-config publicAccessCidrs="203.0.113.0/24,198.51.100.0/24"
Control Plane Logging
Enable comprehensive control plane logging to detect suspicious API activity:
aws eks update-cluster-config \
--region us-west-2 \
--name production-cluster \
--logging '{"enable":["api","audit","authenticator","controllerManager","scheduler"]}'
These logs flow to CloudWatch and should trigger alerts for failed authentication attempts, privilege escalations, and unusual resource access patterns.
IAM and Authentication
EKS Service-Linked Roles
EKS requires specific IAM roles with minimal permissions. The cluster service role needs these managed policies:
AmazonEKSClusterPolicyAmazonEKSVPCResourceController
Node groups require:
AmazonEKSWorkerNodePolicyAmazonEKS_CNI_PolicyAmazonEC2ContainerRegistryReadOnly
AWS IAM Authenticator Configuration
Map IAM users and roles to Kubernetes RBAC through the aws-auth ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789012:role/NodeInstanceRole
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
- rolearn: arn:aws:iam::123456789012:role/EKSAdminRole
username: eks-admin
groups:
- system:masters
mapUsers: |
- userarn: arn:aws:iam::123456789012:user/developer
username: developer
groups:
- developers
IRSA (IAM Roles for Service Accounts)
IRSA eliminates the need to store AWS credentials in pods. Create an OIDC identity provider first:
eksctl utils associate-iam-oidc-provider \
--region us-west-2 \
--cluster production-cluster \
--approve
Then create service accounts with IAM role annotations:
eksctl create iamserviceaccount \
--region us-west-2 \
--name aws-load-balancer-controller \
--namespace kube-system \
--cluster production-cluster \
--attach-policy-arn arn:aws:iam::123456789012:policy/AWSLoadBalancerControllerIAMPolicy \
--approve
Network Security
VPC Configuration
Deploy EKS clusters in private subnets with dedicated security groups. The cluster security group should only allow:
- HTTPS (443) from authorized CIDR blocks
- Internal cluster communication
- Managed node group traffic
Network Policies
Implement Kubernetes Network Policies to control pod-to-pod communication. Install a CNI that supports network policies like Calico:
kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/release-1.12/config/master/calico-operator.yaml
kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/release-1.12/config/master/calico-crs.yaml
Example network policy for database access restriction:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database-access
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: web-backend
ports:
- protocol: TCP
port: 5432
Security Groups for Pods
AWS VPC CNI supports applying EC2 security groups directly to pods, providing an additional network security layer:
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: database-pods-sg
namespace: production
spec:
podSelector:
matchLabels:
app: database
securityGroups:
groupIds:
- sg-0123456789abcdef0
Pod Security Standards
Pod Security Standards Implementation
Configure namespace-level Pod Security Standards to replace deprecated Pod Security Policies:
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Security Context Best Practices
Every production pod should implement these security contexts:
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop:
- ALL
Image Security
ECR Integration and Scanning
Use Amazon ECR with automated vulnerability scanning:
aws ecr put-image-scanning-configuration \
--region us-west-2 \
--repository-name my-application \
--image-scanning-configuration scanOnPush=true
Implement admission controllers to prevent vulnerable images from deploying:
apiVersion: v1
kind: ValidatingAdmissionWebhook
metadata:
name: image-security-webhook
webhooks:
- name: image.security.io
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["apps"]
apiVersions: ["v1"]
resources: ["deployments", "daemonsets", "statefulsets"]
Image Policy Enforcement
Use OPA Gatekeeper to enforce image policies:
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: allowedrepos
spec:
crd:
spec:
names:
kind: AllowedRepos
validation:
properties:
repos:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package allowedrepos
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not starts_with(container.image, input.parameters.repos[_])
msg := sprintf("Image '%v' not from allowed repository", [container.image])
}
Secrets Management
AWS Secrets Manager Integration
Use the AWS Secrets Store CSI Driver to mount secrets from AWS Secrets Manager:
helm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
helm install csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver --namespace kube-system
Create SecretProviderClass for secret mounting:
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: app-secrets
spec:
provider: aws
parameters:
objects: |
- objectName: "prod/myapp/database"
objectType: "secretsmanager"
jmesPath:
- path: "username"
objectAlias: "db-username"
- path: "password"
objectAlias: "db-password"
Monitoring and Compliance
Runtime Security Monitoring
Deploy Falco for runtime threat detection:
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm upgrade --install falco falcosecurity/falco \
--set falco.grpc.enabled=true \
--set falco.grpcOutput.enabled=true
Compliance Scanning
Regular security scanning identifies misconfigurations before they become incidents. Tools like FixMyCloud automatically scan EKS clusters for security issues including:
- Misconfigured RBAC permissions
- Exposed services and ingresses
- Pod security violations
- Network policy gaps
- IAM permission sprawl
Manual CIS Kubernetes Benchmark scanning with kube-bench:
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job-eks.yaml
kubectl logs job/kube-bench
Upgrade and Maintenance Security
Automated Security Patching
Configure managed node groups with automatic AMI updates:
aws eks update-nodegroup-config \
--cluster-name production-cluster \
--nodegroup-name production-nodes \
--update-config maxUnavailablePercentage=25
Cluster Version Management
Maintain supported EKS versions and plan regular upgrades. AWS supports each EKS version for approximately 14 months:
aws eks update-cluster-version \
--region us-west-2 \
--name production-cluster \
--kubernetes-version 1.28
AWS EKS Security Checklist
Use this checklist to validate your EKS security posture:
- Control Plane: Private API endpoint, comprehensive logging enabled
- Authentication: IAM roles properly configured, RBAC implemented
- Network: Private subnets, security groups, network policies active
- Pods: Security contexts, non-root users, read-only filesystems
- Images: Vulnerability scanning, approved registries only
- Secrets: External secret management, no hardcoded credentials
- Monitoring: Runtime security, audit logging, compliance scanning
- Updates: Automated patching, supported versions
AWS EKS security requires ongoing attention and regular auditing. The combination of AWS-native security controls with Kubernetes security primitives creates a robust defense-in-depth strategy. Regular automated scanning helps maintain security posture as your cluster evolves and scales.
Scan your AWS environment automatically
FixMyCloud runs 241 AWS security checks across IAM, S3, EC2, RDS, CloudTrail, VPC and more — mapped to CIS, NIST, PCI DSS, and HIPAA.
Start a free scan →