The 4Cs model is a defense-in-depth framework for cloud-native security. Each layer wraps the next — a weakness in an outer layer can expose the inner layers. You must secure all four simultaneously; no single layer is sufficient on its own.
Image security: scanning, least privilege, read-only root FS, non-root user
C
Code
Application code: SAST, dependency scanning, input validation, secrets in env vars
What are the 4Cs of cloud-native security?
Cloud, Cluster, Container, Code — a defense-in-depth model where each C wraps the one inside it. A vulnerability in an outer layer can expose inner layers. All four must be secured independently.
What does the "Cloud" layer of the 4Cs cover?
AWS infrastructure security: VPC configuration, IAM policies, account-level guardrails, physical security of data centers. This is partly shared with AWS (physical/hypervisor) and partly your responsibility (VPC design, IAM).
What does the "Cluster" layer of the 4Cs cover?
Kubernetes cluster security: RBAC (who can call the K8s API), admission controllers (enforce policies at creation time), network policies (pod-to-pod traffic), secrets encryption at rest in etcd, audit logging.
What does the "Container" layer of the 4Cs cover?
Container image security: scanning images for CVEs (ECR image scanning), using minimal base images, running as non-root, setting readOnlyRootFilesystem: true, dropping Linux capabilities, avoiding privileged containers.
What does the "Code" layer of the 4Cs cover?
Application code security: SAST (static analysis), dependency scanning (Dependabot, Snyk), input validation to prevent injection attacks, avoiding hardcoded secrets, secure communication (mTLS between services).
Why is the 4Cs model called "defense in depth"?
Because each layer provides an independent security boundary. An attacker who breaches the Cloud layer still faces Cluster controls. A container escape still faces Code-level protections. No single layer failure should compromise everything. Security comes from multiple overlapping controls.
TOPIC 2 Shared responsibility model
EKS extends the AWS shared responsibility model. The boundary shifts depending on which data plane option you choose. Understanding who owns what for each option is critical for both the exam and real security planning.
Responsibility
Default EKS (self-managed nodes)
Managed Node Groups
Fargate
K8s control plane
✓ AWS
✓ AWS
✓ AWS
Node OS patching
You
✓ AWS
✓ AWS
Node provisioning & replacement
You
✓ AWS
✓ AWS
Container runtime
You
You choose
✓ AWS
Network config, IAM, RBAC
You
You
You
Application workloads
You
You
You
Pod security context
You
You
You
What extra responsibility does AWS take on with managed node groups vs self-managed?
With managed node groups, AWS additionally manages node OS patching, rolling node replacements, and joining/removing nodes from the cluster. With self-managed nodes, all of that is your responsibility.
What does AWS manage for you when using Fargate?
On Fargate, AWS manages the entire node layer: provisioning, OS patching, container runtime, node replacement. You only manage pod security context, app code, RBAC, IAM, and network config. The node is completely abstracted.
What security responsibilities ALWAYS remain yours regardless of data plane option?
Regardless of data plane choice, you always own: RBAC configuration, IAM policies, network config (VPC/security groups), pod security context, application code, secrets management, and logging/monitoring setup. AWS never owns these.
Why does Fargate reduce your attack surface compared to EC2 nodes?
Fargate provides 1 pod per micro-VM isolation, OS patching by AWS, no shared kernel between pods, and no SSH access to worry about. You cannot misconfigure node security groups, patch timing, or container runtime versions — those risks don't exist for you.
TOPIC 3 GuardDuty for EKS
Amazon GuardDuty provides threat detection for EKS clusters. It analyzes EKS audit logs and runtime activity to surface suspicious behavior without requiring you to write detection rules or manage infrastructure.
What GuardDuty monitors
EKS control plane audit logs
Runtime activity on nodes (with Runtime Monitoring add-on)
Container image pulls and process execution
Network connections from pods
Anomalous API calls to K8s API server
Threat types detected
Privilege escalation (e.g., creating a ClusterRoleBinding to system:masters)
Credential theft (service account token misuse)
Container breakouts / host path traversal
Cryptomining (unusual CPU + network patterns)
Unusual Kubernetes API calls from unexpected principals
What data source does GuardDuty use for EKS threat detection?
GuardDuty analyzes EKS audit logs (control plane API server logs) and, with Runtime Monitoring enabled, runtime activity on nodes (process executions, file access, network connections). It does not require you to ship logs to a SIEM first.
Give two examples of EKS threats that GuardDuty can detect.
1. Privilege escalation — an attacker binding themselves to system:masters to gain cluster-admin. 2. Credential theft — a service account token being used from an unexpected IP or region outside normal cluster traffic.
Does GuardDuty require you to configure rules or write detections?
No. GuardDuty is a managed threat detection service. AWS maintains the threat intelligence and detection logic. You enable it and receive findings — you do not write rules. This is the key contrast with a self-managed SIEM or custom audit log analysis.
TOPIC 4 Authentication & authorization overview
EKS uses two separate permission systems that work in tandem. You must understand both, and more importantly, when each one applies. Confusing IAM and RBAC is the single most common EKS security mistake.
Kubernetes API (create Pod, list Services, get Secrets…)
Scope
AWS account & resources
Kubernetes cluster resources
Subject types
IAM user, IAM role, AWS service
User, Group, ServiceAccount
Policy object
IAM Policy
Role / ClusterRole
Binding object
Policy attachment to principal
RoleBinding / ClusterRoleBinding
Used for
Authentication (who you are)
Authorization (what you can do in K8s)
Bridge: The aws-auth ConfigMap (or EKS Access Entries) maps IAM principals to K8s RBAC subjects. IAM handles authentication; RBAC handles authorization inside the cluster.
What are the two separate permission systems in EKS and what does each control?
IAM controls access to AWS APIs — creating clusters, managing node groups, reading ECR, S3, etc. Kubernetes RBAC controls access to the K8s API — creating pods, listing services, reading secrets within the cluster.
How does authentication work when a developer runs kubectl against EKS?
1. kubectl calls aws eks get-token to get a bearer token using IAM credentials. 2. Token sent to K8s API server. 3. API server validates token via AWS IAM Authenticator. 4. Validated identity looked up in aws-auth ConfigMap → K8s username/groups assigned. 5. RBAC evaluates what those groups can do.
What is an EKS OIDC issuer and why does it matter for security?
Each EKS cluster has an OIDC issuer URL. It allows AWS IAM to trust tokens issued by the cluster's K8s API server. This is the cryptographic foundation that enables IRSA — pods can prove their identity to AWS STS without needing static credentials.
Can you have full IAM permissions but still be blocked by RBAC?
Yes. IAM controls AWS API access; RBAC controls K8s API access. Even if your IAM policy allows eks:*, you still need the appropriate RBAC bindings to run kubectl commands. Both systems must grant access — they operate independently.
TOPIC 5 Kubernetes RBAC
Kubernetes Role-Based Access Control (RBAC) is the mechanism that controls who can do what to which Kubernetes resources. It has four object types: two for defining permissions, and two for binding those permissions to subjects.
Animation · RBAC object relationships
Object
Scope
Purpose
Bound by
Role
Namespaced
Defines allowed verbs + resources within one namespace
RoleBinding
ClusterRole
Cluster-wide
Defines allowed verbs + resources across all namespaces
ClusterRoleBinding or RoleBinding
RoleBinding
Namespaced
Binds Role or ClusterRole to subject within one namespace
—
ClusterRoleBinding
Cluster-wide
Binds ClusterRole to subject across all namespaces
—
RBAC subjects are the "who" — they can be a User, Group, or ServiceAccount. Verbs include: get, list, watch, create, update, patch, delete.
# Example: Role in "default" namespace — pod-readerkind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata:
name: pod-readernamespace: defaultrules:
- apiGroups: [""]# "" = core API groupresources: ["pods"]verbs: ["get", "watch", "list"]
---
# Bind the Role to a userkind: RoleBindingmetadata:
name: read-podsnamespace: defaultsubjects:
- kind: Username: janeapiGroup: rbac.authorization.k8s.ioroleRef:
kind: Rolename: pod-readerapiGroup: rbac.authorization.k8s.io
What is the difference between a Role and a ClusterRole?
Role is namespaced — it grants permissions within one namespace only. ClusterRole is cluster-wide — it grants permissions across all namespaces, or to non-namespaced resources like nodes. A ClusterRole can be bound into a namespace using a RoleBinding.
What is the difference between RoleBinding and ClusterRoleBinding?
RoleBinding is namespace-scoped — applies in one namespace. It can bind a Role OR a ClusterRole (which limits the ClusterRole to that namespace). ClusterRoleBinding is cluster-wide — applies across all namespaces. Can only bind a ClusterRole.
Can you use a RoleBinding to bind a ClusterRole?
Yes. A RoleBinding can reference a ClusterRole as its roleRef. The effect is that the ClusterRole's permissions apply only within the RoleBinding's namespace — not cluster-wide. This is useful for reusing a ClusterRole definition with namespace-limited scope.
What is the RBAC analogy to IAM? Map each component.
IAM Policy ≈ RBAC Role/ClusterRole (list of allowed actions + resources)
IAM Principal (user/role) ≈ K8s Subject (User/Group/ServiceAccount)
IAM Policy Attachment ≈ RoleBinding/ClusterRoleBinding
What is the cluster-admin ClusterRole and who should have it?
cluster-admin is the default ClusterRole granting full access to all K8s resources. By default, only the IAM entity that created the EKS cluster has it. It should be tightly controlled — do not routinely grant it. Use least-privilege roles instead.
What are the three default RBAC groups in EKS and what do they map to?
What RBAC verbs exist and what do they map to in HTTP?
get → GET single resource list → GET collection watch → GET with watch stream create → POST update → PUT patch → PATCH delete → DELETE deletecollection → DELETE collection
TOPIC 6 IAM → RBAC: aws-auth ConfigMap
The aws-auth ConfigMap in the kube-system namespace is the bridge between IAM identity and Kubernetes RBAC. It maps IAM roles/users to K8s usernames and groups. Without an entry here, an IAM principal cannot interact with the K8s API even if they have full IAM permissions.
Animation · aws-auth ConfigMap: bridging IAM and RBAC
Critical: The IAM entity that created the EKS cluster is the only principal that automatically gets cluster-admin access. All other IAM principals (including your own admin role in a different session) must be explicitly added to aws-auth.
What is the aws-auth ConfigMap and where does it live?
The aws-auth ConfigMap lives in the kube-system namespace. It maps IAM roles/users (AWS identities) to Kubernetes usernames and groups (K8s RBAC subjects). It is the bridge between IAM authentication and RBAC authorization.
What is the two-step process to grant an IAM role K8s permissions?
Step 1: Add entry to aws-auth ConfigMap: map IAM role ARN → K8s username + groups. Step 2: Create a ClusterRoleBinding (or RoleBinding) that binds the K8s group to a ClusterRole (or Role).
Now: IAM role → K8s group → RBAC permissions.
Why must node IAM roles be in aws-auth?
Worker nodes use an IAM role for AWS API calls, but they also need K8s API access so kubelet can register as a node and report status. The node IAM role must be in aws-auth mapped to system:nodes group so the K8s API server trusts the node's identity.
What happens if you accidentally delete the aws-auth ConfigMap?
Only the cluster creator's IAM entity retains cluster-admin access (it's hardcoded). All other users lose K8s API access — including your admin roles. Nodes will also lose their K8s identity. You must recreate the ConfigMap immediately using the creator's credentials.
How do you grant a new IAM role cluster-admin in aws-auth?
Add to the mapRoles section of aws-auth:
rolearn: <IAM-role-ARN> username: cluster-admin groups: [system:masters]
The system:masters group is pre-bound to the cluster-admin ClusterRole, giving full access.
TOPIC 7 Service accounts & pod permissions
A service account is the Kubernetes identity for pods (not humans). Every pod runs with a service account. By default, all pods in a namespace run with the default service account, which has minimal permissions and no AWS access.
The default SA problem
Every namespace has a "default" service account
All pods use it unless you specify otherwise
Has no special K8s RBAC permissions by default
Has NO AWS credentials by default
If you bind a powerful role to "default" SA — all pods in namespace inherit it
Solution: always create purpose-specific SAs
Custom service account pattern
Create SA with specific name per application
Create a Role with only needed verbs + resources
Bind Role to SA with RoleBinding
Set serviceAccountName in pod spec
Token automatically projected into pod at /var/run/secrets/kubernetes.io/serviceaccount/
Pod can now call K8s API with those permissions
# Create a service accountapiVersion: v1kind: ServiceAccountmetadata:
name: my-app-sanamespace: production
---
# Use it in a podspec:
serviceAccountName: my-app-sacontainers:
- name: my-appimage: my-app:latest
What is a Kubernetes service account?
A Kubernetes identity for pods (not humans). When a pod calls the K8s API, it authenticates using its service account's token. Service accounts are namespace-scoped and their RBAC bindings define what K8s operations the pod can perform.
What is the "default" service account risk?
Every namespace has a default SA. All pods without an explicit SA use it. If you grant the default SA elevated permissions, all pods in that namespace inherit those permissions — including ones that shouldn't have them. Always create purpose-specific service accounts.
Where is the service account token automatically mounted in a pod?
Kubernetes automatically projects the token to: /var/run/secrets/kubernetes.io/serviceaccount/token Also mounted: ca.crt (cluster CA) and namespace. Applications use this token to authenticate to the K8s API. You can also disable auto-mounting with automountServiceAccountToken: false.
Can a service account call AWS APIs directly (without IRSA)?
Not with proper scoping. Without IRSA, a pod would inherit the node's IAM role — meaning all pods on the same node share the same AWS permissions. This is a security anti-pattern. IRSA solves this by letting each service account have its own scoped IAM role.
TOPIC 8 IAM Roles for Service Accounts (IRSA)
IRSA allows pods to call AWS APIs using scoped IAM roles — without static credentials and without sharing the node's IAM role. It is the recommended way to give pods AWS permissions. Built on a three-way trust between IAM, the cluster's OIDC provider, and the K8s service account.
Animation · IRSA three-way trust — how a pod gets AWS credentials
Why IRSA beats node IAM roles: With a node IAM role, every pod on that node shares the same permissions. If one pod is compromised, attackers get node-level AWS access. IRSA scopes credentials per service account — a compromised pod can only access what that specific SA is permitted.
IRSA Setup Steps
Enable OIDC provider: Associate your cluster's OIDC issuer URL with AWS IAM — eksctl utils associate-iam-oidc-provider --cluster <name>
Create IAM role: Write a trust policy that allows sts:AssumeRoleWithWebIdentity for the specific OIDC issuer URL + system:serviceaccount:<namespace>:<sa-name>
Attach permissions policy: Attach the IAM policy defining the AWS permissions the pod needs (e.g., S3 read-only for specific bucket)
Create annotated K8s service account:eks.amazonaws.com/role-arn: <IAM-role-ARN> on the service account
Deploy pod using that SA: Set serviceAccountName in pod spec. Kubelet automatically injects AWS credentials via a projected volume
Without IRSA, pods use the node's IAM role — all pods on a node share the same AWS permissions (over-permissioned). IRSA lets each pod use a scoped IAM role specific to its service account, following the principle of least privilege.
What is the "three-way trust" in IRSA?
1. EKS OIDC issuer — issues signed JWT tokens for service accounts
2. IAM — trusts the OIDC issuer (configured via OIDC identity provider)
3. K8s service account — annotated with the IAM role ARN
These three form the chain that allows AWS STS to issue temporary credentials to the pod.
How does a pod actually receive AWS credentials via IRSA?
The Pod Mutating Admission Webhook automatically injects the OIDC token as a projected volume and sets environment variables AWS_WEB_IDENTITY_TOKEN_FILE and AWS_ROLE_ARN. The AWS SDK reads these automatically and calls sts:AssumeRoleWithWebIdentity to get temporary credentials.
What annotation do you add to a K8s service account to enable IRSA?
This tells EKS which IAM role to assume when pods using this service account call AWS APIs. The IAM role's trust policy must reference this specific namespace and SA name.
What condition must the IAM trust policy have for IRSA to be secure?
The trust policy StringEquals condition must specify the exact OIDC issuer URL + SA subject: "system:serviceaccount:<namespace>:<sa-name>". Without this, any SA in the cluster could assume the role. The specificity of the subject claim is what makes IRSA secure.
What is the first step to enable IRSA on an existing EKS cluster?
Associate the cluster's OIDC issuer URL with IAM: eksctl utils associate-iam-oidc-provider --cluster <name> --approve
Or via Console: EKS cluster → Configuration → Authentication → Add OIDC. This creates the IAM OIDC identity provider that allows IAM to trust the cluster's service account tokens.
TOPIC 9 Knowledge checks (from the course)
Official course knowledge-check questions formatted as flashcards. Try to answer before flipping.
KC 1 — How does the EKS cluster creator get cluster-admin access? (Select 2) A. Auto system:masters B. Default RBAC policy C. Modify aws-auth D. Auto cluster-admin CRB
✓ A & C
A: The IAM entity that creates the cluster is automatically added to system:masters (no aws-auth entry needed for them). C: Additional users get access by modifying the aws-auth ConfigMap to map their IAM role/user to a K8s group, then adding a ClusterRoleBinding.
KC 2 — Which is the MOST restrictive policy allowing a pod to read from S3? A. Admin IAM policy on node B. S3ReadOnly on node C. Admin IAM via IRSA D. Custom S3 role via IRSA
✓ D — Custom IAM role with only required S3 permissions via IRSA
IRSA with a purpose-built, minimally scoped IAM policy is least-privilege. Options A/B use the node role (all pods on node share), Option C uses IRSA but grants excessive admin permissions.
KC 3 — What do you need for a user to deploy pods to an EKS cluster? (Select 3) A. kubectl + kubeconfig B. IAM perms for K8s API C. RBAC Role for pod creation D. Root account access
✓ A, B, C
A: kubectl tool + kubeconfig pointing to the cluster. B: IAM permissions to authenticate (get token for the K8s API). C: RBAC Role/ClusterRole granting create on pods (or deployments), bound via RoleBinding/ClusterRoleBinding. D is wrong — root access is not needed or recommended.
KC 4 — Service account permissions. Which statements are correct? (Select A,B,D,E)
Correct: A — SA is K8s identity for pods. B — SA enables pod→K8s API auth. D — IRSA lets SA assume IAM role for AWS API calls. E — SA token auto-projected into pod. Incorrect: C — Default SA does NOT have cluster-admin. Never grant broad permissions to default SA.
Exam trap: A developer has full AdministratorAccess IAM policy. They run kubectl get pods and get "Forbidden". Why?
IAM controls AWS API access, not K8s API access. The developer's IAM role is not in the aws-auth ConfigMap, so they have no K8s identity. They need to be added to aws-auth (mapped to a K8s group) AND have an appropriate RBAC binding. AdministratorAccess does not grant K8s access.
Exam trap: Can a ClusterRole be used to grant namespace-scoped permissions?
Yes. If you bind a ClusterRole using a RoleBinding (not ClusterRoleBinding) in a specific namespace, the ClusterRole's permissions apply only to that namespace. This is a valid pattern for reusing permission definitions without creating duplicate Role objects in every namespace.
What is the security risk of using the node IAM role for pod AWS access?
Blast radius. All pods on a node share the node's IAM role. If any pod is compromised, the attacker gains access to all AWS resources the node role can reach — not just those needed by that pod. IRSA scopes credentials per SA, containing the blast radius to a single service.
Where in the 4Cs model does RBAC belong?
RBAC belongs in the Cluster layer — the second C. It is a Kubernetes-layer control, not AWS infrastructure (Cloud), not container image security (Container), and not application code (Code). Cluster security includes RBAC, admission controllers, network policies, and audit logging.