SecurityContext & ServiceAccounts (CKAD)
A pod has two identities: a Linux user on the node and a ServiceAccount to the API server. Shrink both.
An interactive Kubernetes lesson: 22 steps, about 35 minutes, on a live simulation in your browser.
The shop's payments pod handles card charges, and an audit is coming. The auditor asks two questions that sound alike and are not: what could this process do to the node it runs on, and what could it do to the cluster?
On the node, the pod is a Linux process with a user ID and a set of kernel privileges. That identity is shaped by securityContext. To the API server, the pod is a ServiceAccount, and what it may do is decided by RBAC.
What you will learn
Two identities
- One pod, two identities: A pod has two identities: a Linux user on the node, set by securityContext, and a ServiceAccount to the API server, governed by RBAC.
On the node: who the process is
- Root unless told otherwise: With no securityContext a container runs as the image's user. For most images that is UID 0: root.
- runAsUser: choose the user: runAsUser sets the UID the process starts with. Once it is not root, ordinary file permissions protect the rest of the container.
- Break it: runAsNonRoot on a root image: runAsNonRoot is a check, not a setting: refuse to start the container if it would run as UID 0.
- Pod level and container level: Pod-level securityContext is the default for every container. A container-level value overrides it for that container alone.
On the node: what the process may do
- A read-only root filesystem: Read-only root freezes the program. Whatever must be written goes to a volume you mounted on purpose.
- Root is not one power: Root's power is split into capabilities. A container gets a short default list, and even UID 0 cannot do what is not on it.
- Drop ALL, add back by name: capabilities: drop ALL, then add back by name only what the program needs.
- The hardened container: Non-root, no escalation, no capabilities, read-only root, default seccomp. That set is the starting point for every container you ship.
- Break it: privileged: true
To the API: ServiceAccounts
- The identity it never asked for: A ServiceAccount is the pod's identity to the API server. Its token is a short-lived, auto-rotated file mounted into every container.
- What the default account may do: Authenticated is not authorized. The default ServiceAccount proves who the pod is, and is allowed to do nothing.
- No token for pods that never call the API: A pod that never calls the API should not carry a token. automountServiceAccountToken: false takes it away.
- A dedicated account with one job: One ServiceAccount per application, bound to a Role with exactly the verbs it needs. Permissions belong to the account, never to the pod.
- Break it: an account that does not exist
The request pipeline
- Three gates in front of etcd: Authentication: who are you. Authorization: may you do this. Admission: is this object acceptable. In that order, and all three must pass.
- Allowed by RBAC, refused anyway: RBAC decides whether you may create pods. Admission decides whether this pod may exist. Being cluster-admin does not get a bad pod past admission.
- restricted: the hardened spec, enforced
Exam speed
- Drill: bind a Role to a ServiceAccount
- Drill: test an identity
Recap & playground
- Cheat sheet
- Playground