Amazon EKS — IAM & Security — Practice Exercises
Chapter 9 — Practice Exercises
Exercise 1: IRSA Setup
Question: Your application pod needs to read from S3 bucket data-bucket and write to DynamoDB table sessions. Create the IAM policy, IRSA setup commands, and pod spec.
Show Solution
IAM Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::data-bucket",
"arn:aws:s3:::data-bucket/*"
]
},
{
"Effect": "Allow",
"Action": ["dynamodb:PutItem", "dynamodb:GetItem", "dynamodb:UpdateItem"],
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/sessions"
}
]
}
Create IRSA:
$ aws iam create-policy --policy-name app-policy --policy-document file://policy.json
$ eksctl create iamserviceaccount \
--cluster demo \
--name app-sa \
--namespace production \
--attach-policy-arn arn:aws:iam::123456789012:policy/app-policy \
--approve
Pod spec:
apiVersion: v1
kind: Pod
metadata:
name: app
namespace: production
spec:
serviceAccountName: app-sa
containers:
- name: app
image: my-app:latest
Exercise 2: RBAC Design
Question: Create RBAC rules for: (a) Developers can view pods and logs in staging, (b) Ops team can manage deployments in all namespaces, (c) CI/CD service account can create/update deployments in production.
Show Solution
(a) Developer pod viewer — namespace-scoped:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-viewer
namespace: staging
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-pod-viewer
namespace: staging
subjects:
- kind: Group
name: developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-viewer
apiGroup: rbac.authorization.k8s.io
(b) Ops deployment manager — cluster-scoped:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: deployment-manager
rules:
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: ops-deployment-manager
subjects:
- kind: Group
name: operations
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: deployment-manager
apiGroup: rbac.authorization.k8s.io
(c) CI/CD deployer — namespace-scoped:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployer
namespace: production
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["create", "update", "patch"]
- apiGroups: [""]
resources: ["services", "configmaps"]
verbs: ["create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cicd-deployer
namespace: production
subjects:
- kind: ServiceAccount
name: cicd-sa
namespace: production
roleRef:
kind: Role
name: deployer
apiGroup: rbac.authorization.k8s.io
Exercise 3: Pod Security
Question: Write a pod spec that passes the restricted Pod Security Standard. Include all required security contexts.
Show Solution
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: my-app:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {} # Writable /tmp since root FS is read-only
Exercise 4: Security Audit
Question: You’ve inherited an EKS cluster. List 10 things you would check in a security audit and the commands to check them.
Show Solution
# 1. API endpoint access
$ aws eks describe-cluster --name cluster --query 'cluster.resourcesVpcConfig'
# 2. Control plane logging
$ aws eks describe-cluster --name cluster --query 'cluster.logging'
# 3. Envelope encryption
$ aws eks describe-cluster --name cluster --query 'cluster.encryptionConfig'
# 4. Kubernetes version
$ aws eks describe-cluster --name cluster --query 'cluster.version'
# 5. RBAC — who has cluster-admin?
$ kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects'
# 6. Pods running as root
$ kubectl get pods -A -o json | jq '.items[] | select(.spec.securityContext.runAsNonRoot != true) | .metadata.name'
# 7. Pods with privileged containers
$ kubectl get pods -A -o json | jq '.items[] | select(.spec.containers[].securityContext.privileged == true) | .metadata.name'
# 8. Network policies
$ kubectl get networkpolicies -A
# 9. IRSA usage (vs node IAM)
$ kubectl get sa -A -o json | jq '.items[] | select(.metadata.annotations."eks.amazonaws.com/role-arn") | .metadata.name'
# 10. Image sources (ECR vs public)
$ kubectl get pods -A -o jsonpath='{range .items[*]}{.spec.containers[*].image}{"\n"}{end}' | sort -u
Exercise 5: Secrets Security
Question: Your cluster stores database passwords as Kubernetes Secrets. What are 3 security risks and how would you mitigate each?
Show Solution
Risk 1: Secrets stored as base64 in etcd (not encrypted)
Mitigation: Enable KMS envelope encryption
$ aws eks create-cluster ... --encryption-config '[{"resources":["secrets"],"provider":{"keyArn":"arn:aws:kms:..."}}]'
Risk 2: Anyone with namespace access can read Secrets
Mitigation: RBAC — restrict secrets access
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: [] # No access to secrets
Risk 3: Secrets visible in pod spec (env vars)
Mitigation: Use AWS Secrets Manager with CSI driver
- Secrets stored in AWS Secrets Manager
- Mounted as files (not env vars)
- Rotation supported
- Audit trail via CloudTrail
What’s Next?
Expose your apps: Chapter 10 — Load Balancing & Ingress.