skip to content

Security

How a request is authenticated, then authorised by RBAC, then admitted — plus the workload side: ServiceAccount tokens, securityContext and Pod Security Standards, and how Secrets are really protected. Most compromises start with one over-broad binding.

part ofKubernetesoverview, primer and where to startread it →
on this pageshow

questions

page 1 of 2

Walk through what happens to a request such as 'kubectl apply -f pod.yaml' inside the Kubernetes API server, from the TLS connection to the object being stored in etcd.

level: juniorimportance: must knowfreq 62%

answer

  1. authn → authz → admission → persist
  2. authn yields username + groups only; no User object
  3. authz sees verb/resource, never object fields
  4. mutating first, then schema validation, then validating
  5. 401 = authn, 403 = authz, named-policy error = admission

basics

~20 s

The API server terminates TLS, then runs three gates in order: authentication (who are you — cert, service-account token, or OIDC token), authorization (may this identity do this verb on this resource — usually RBAC), and admission (mutating plugins/webhooks may edit the object, then validating ones may reject it). Only then is the object schema-validated and written to etcd.

solid answer

~60 s

1. **Transport** — the client connects over TLS to kube-apiserver; the request is an HTTP call like `POST /api/v1/namespaces/default/pods`. 2. **Authentication** — a chain of authenticators tries to establish an identity: client certificate, service-account bearer token, OIDC ID token, or an authentication webhook. First success wins and yields a username plus groups. All fail ⇒ the request becomes `system:anonymous` or gets 401. 3. **Authorization** — the identity plus the request attributes (verb, resource, namespace, name) go to the authorization modules, normally RBAC and Node. Any module returning allow short-circuits to allow; if none allows, the answer is 403. 4. **Admission** — **mutating** admission plugins and webhooks run first and may patch the object (defaults, sidecar injection); then the object is schema-validated; then **validating** plugins and webhooks run and may only accept or reject. ResourceQuota is evaluated here too. 5. **Persistence** — the accepted object is serialised and written to etcd; watchers (schedulers, controllers) see it and act. Mnemonic: **authn → authz → admission → persist**, and admission is the only stage that can change the object.

code

bash · 12 lines
bash
# Stage 1 — what identity does the API server see for my credentials?
kubectl auth whoami

# Stage 2 — would authorization allow this verb on this resource?
kubectl auth can-i create pods --namespace default
kubectl auth can-i list secrets --namespace kube-system --as [email protected]

# Stage 3 — run mutating + validating admission without persisting
kubectl apply -f pod.yaml --dry-run=server

# Stage 4 — the write happened only if the object is now readable
kubectl get pod -n default my-pod -o yaml

go deeper

for a junior

Recite the four stages in order and what each decides, and map 401 to authentication and 403 to authorization.

for a middle

Add the mechanics: authenticator chain with first-success-wins, RBAC being additive and field-blind, mutating-then-validating with schema validation in between.

for a senior

Explain why the ordering forces field-level policy into admission, how ResourceQuota and dry-run behave, and how you use the stage boundaries to triage a failing request quickly.

for a principal

Use the pipeline as the frame for cluster security architecture: which control belongs at which stage, the cost each stage adds to every write, and what a compromise of each layer would mean.

## One door into the cluster Everything in Kubernetes goes through kube-apiserver: `kubectl`, controllers, the scheduler, kubelets, and every operator. There is no side channel that writes to etcd directly. That is why the API-server request pipeline is *the* security model of Kubernetes — understanding its four stages tells you where every control lives. ## Stage 0 — transport The API server serves HTTPS only. If the client presents a certificate during the TLS handshake, it is available to the certificate authenticator later; otherwise the connection is still established and identity must come from a header. The REST path itself encodes the target: `POST /api/v1/namespaces/default/pods` (core group) or `/apis/apps/v1/namespaces/default/deployments` (named group). The HTTP method maps to a verb — POST→create, GET→get/list, PUT→update, PATCH→patch, DELETE→delete, plus watch for streaming reads. ## Stage 1 — authentication (who are you?) The API server runs an ordered chain of **authenticators**; each either returns an identity or abstains, and the first success wins: - **X.509 client certificate** signed by a CA the API server trusts: the certificate's Common Name becomes the username, its Organization values become groups. - **Service-account bearer token**: a signed JWT in `Authorization: Bearer …`, yielding `system:serviceaccount:<namespace>:<name>`. - **OIDC ID token** from an external identity provider, mapping configured claims to username and groups — the usual mechanism for humans. - **Authentication webhook**, used by managed clouds to validate their own token formats. An authenticated request carries only a **username, UID, and a list of groups** — Kubernetes stores no User object. If every authenticator abstains, the request is either rejected with 401 or, when anonymous access is enabled, continues as `system:anonymous` in the group `system:unauthenticated`. ## Stage 2 — authorization (may you do it?) The request is reduced to attributes: user, groups, verb, API group, resource, subresource, namespace, and object name (or, for non-resource endpoints such as `/healthz`, just the path). These go to the configured authorization modules, typically **Node** (restricting each kubelet to objects relevant to its own node) and **RBAC** (Roles/ClusterRoles bound to subjects), sometimes a **Webhook** for an external decision service. The modules form a chain: a module may answer allow, deny, or no-opinion; the first explicit answer decides, and if every module abstains the request is denied with 403. RBAC is purely additive — it grants, it never denies — so a 403 usually means "nothing granted it", not "something forbade it". Note the ordering consequence: **authorization runs before the object body matters**. You cannot express "may create pods, but only non-privileged ones" in RBAC, because RBAC sees the verb and resource, not the fields. That gap is exactly what the next stage exists for. ## Stage 3 — admission (should this specific object exist?) Admission controllers see the whole object and run in two sub-phases: 1. **Mutating** — built-in plugins (e.g. `DefaultStorageClass`, `ServiceAccount`) and registered mutating webhooks, which may patch the object: fill defaults, inject a sidecar or environment variables, rewrite an image to a digest. 2. **Object schema validation** — the mutated object is checked against the API schema, so a webhook cannot produce an invalid object. 3. **Validating** — built-in plugins, ValidatingAdmissionPolicies (CEL, in-process), and validating webhooks. These may only accept or reject; they cannot modify. `ResourceQuota` is evaluated late here, since it must count what will actually be stored. A rejection at this stage produces a 4xx with the controller's message — which is why admission errors read very differently from RBAC's terse "forbidden". ## Stage 4 — persistence The accepted object is versioned, optionally encrypted at rest, and written to etcd through the storage layer. Only now does the object exist. Everything after that is asynchronous: the scheduler watches for unscheduled pods and binds one to a node, the kubelet on that node watches for pods bound to it and starts containers. None of that is part of the request; `kubectl apply` returns as soon as the object is persisted, which is why a successful apply says nothing about whether the workload actually runs. ## Why the order is the whole point Each stage answers a strictly different question and can only be reached by passing the previous one: *who are you* (identity), *are you allowed to perform this operation on this kind of thing* (coarse, field-blind), *is this particular object acceptable* (fine-grained, field-aware). Security reviews follow the same order, and so does debugging: a 401 is authentication, a 403 is authorization/RBAC, and a verbose message naming a webhook or policy is admission.

  • You get 'Error from server (Forbidden)'. Which stage failed, and how do you confirm it?
    Forbidden is HTTP 403, which is the authorization stage — you were authenticated successfully but no authorization module granted the verb/resource combination. Confirm with kubectl auth whoami to see the identity the API server assigned, then kubectl auth can-i <verb> <resource> to reproduce the decision. If instead the message names a webhook or policy and describes the object's contents, the request passed authorization and was rejected at admission.
  • Why can't RBAC express 'this user may create pods, but not privileged ones'?
    Authorization runs before the object's fields are considered: the decision inputs are user, groups, verb, API group, resource, subresource, namespace and name — the request body is not among them. Field-level conditions therefore have to be enforced at admission, by Pod Security Standards, a ValidatingAdmissionPolicy, or a policy engine. This split is deliberate; it keeps the authorization layer cheap and cacheable.

An airport: passport control proves who you are, the boarding pass check says whether you may take this flight, and security screening inspects what you are actually carrying — and only screening can make you repack your bag.

saying these in an interview costs you the question

  • Putting admission before authorization, or claiming admission decides who you are.
  • Believing Kubernetes stores user accounts as objects in etcd.
  • Saying validating webhooks can modify the object — only mutating ones can.
  • Thinking a successful kubectl apply means the pod is running; it only means the object was persisted.
  • Confusing 401 (authentication failed) with 403 (authenticated but not authorized).

context

open as a page

In a Kubernetes Pod spec, what do the securityContext fields runAsNonRoot and runAsUser do, and why does it matter whether a container process runs as UID 0?

level: juniorimportance: must knowfreq 62%

basics

~20 s

runAsUser sets the numeric UID the container process runs as. runAsNonRoot: true makes the kubelet refuse to start the container if it would run as UID 0. Root inside the container is real root on the host kernel, so any container escape starts privileged.

open as a page

In Kubernetes RBAC, what are the three parts of a policy rule — apiGroups, resources and verbs — and how would you write a Role that grants read-only access to Pods in a single namespace?

level: juniorimportance: must knowfreq 66%

basics

~20 s

A rule says which API groups, which resource types, and which verbs are allowed. Read-only pods is apiGroups: [""] (core group), resources: ["pods"], verbs: ["get","list","watch"]. A Role holds the rules; a RoleBinding attaches it to a user, group or ServiceAccount. RBAC is purely additive — there is no deny.

open as a page

A teammate argues that Kubernetes Secret objects are safe to share and commit to git because their values are base64-encoded. What is wrong with that reasoning, and what actually protects Secret data in a cluster?

level: juniorimportance: must knowfreq 65%

basics

~20 s

Base64 is an encoding, not encryption: anyone decodes it in one command, no key needed. By default a Secret sits unencrypted in etcd and is readable by anyone whose RBAC allows reading Secrets. Real protection is least-privilege RBAC, encryption at rest, and keeping plaintext manifests out of git.

open as a page

When a process running inside a Pod calls the Kubernetes API, what identity does it present and where does that credential come from? Why do security reviews object to leaving every workload on the namespace's default ServiceAccount?

level: juniorimportance: must knowfreq 60%

basics

~20 s

It presents a ServiceAccount: a namespaced identity named by spec.serviceAccountName. The kubelet projects a signed JWT for it into the container at /var/run/secrets/kubernetes.io/serviceaccount/token. Leaving everything on default means all workloads share one identity, so any permission granted to it is granted to all of them and nothing is attributable.

open as a page

What are the clusters, users and contexts sections of a Kubernetes kubeconfig file, and how does kubectl decide which ones to use?

level: juniorimportance: must knowfreq 76%

basics

~10 s

A kubeconfig lists clusters (API server URL and CA), users (credentials) and contexts that pair one cluster with one user and a default namespace. kubectl uses current-context unless the --context flag names another.

open as a page

How does a Kubernetes audit Policy choose what to record for an API request, and what does each audit level capture?

level: middleimportance: must knowfreq 55%

basics

~20 s

kube-apiserver checks the audit Policy's rules in order; the first rule matching the request's user, verb, resource and namespace sets its level, and unmatched requests are not logged. Metadata records who did what; Request adds the request body; RequestResponse adds the response.

open as a page

Kubernetes stores no User object in etcd, yet API requests are attributed to usernames and groups. What mechanisms can the API server use to authenticate a client, and what identity does each one produce?

level: middleimportance: must knowfreq 52%

basics

~20 s

An ordered chain of authenticators, first success wins. X.509 client certificates map Common Name to username and Organization values to groups. ServiceAccount JWTs map to system:serviceaccount:<ns>:<name>. OIDC ID tokens map configured claims to username and groups. Authentication webhooks and proxy headers exist too. The result is only a username, UID, and group list.

open as a page

When asked to harden a self-managed Kubernetes kube-apiserver, which flags would you set, and what does each one close?

level: middleimportance: must knowfreq 60%

basics

~10 s

Set --anonymous-auth=false, --authorization-mode=Node,RBAC (the built-in default is AlwaysAllow), --enable-admission-plugins including NodeRestriction, --encryption-provider-config for Secrets at rest, and TLS client flags toward etcd and the kubelets.

open as a page

Beyond choosing a non-root UID, which Kubernetes container securityContext fields would you set to harden a workload — specifically capabilities.drop, readOnlyRootFilesystem, allowPrivilegeEscalation and seccompProfile — and what does each one actually prevent?

level: middleimportance: must knowfreq 58%

basics

~20 s

Drop all Linux capabilities (add back only what you need), set readOnlyRootFilesystem so the image cannot be modified at runtime, set allowPrivilegeEscalation: false so setuid binaries cannot gain rights, and set seccompProfile RuntimeDefault to block rarely-used syscalls. Together they shrink the kernel attack surface.

open as a page

Kubernetes defines three Pod Security Standards — privileged, baseline and restricted — enforced by the built-in Pod Security Admission controller through namespace labels. Explain what each level allows and how the enforce, audit and warn modes differ.

level: middleimportance: must knowfreq 55%

basics

~20 s

privileged allows everything; baseline blocks known escalations (privileged mode, host namespaces, hostPath, extra capabilities); restricted additionally requires non-root, drop ALL capabilities, no privilege escalation and a seccomp profile. You opt a namespace in with labels: enforce rejects violating pods, audit records them in the audit log, warn returns a client warning.

open as a page

Kubernetes RBAC has Role, ClusterRole, RoleBinding and ClusterRoleBinding. Explain the scoping matrix — which combinations are legal and what each one actually grants — and what aggregated ClusterRoles are for.

level: middleimportance: must knowfreq 68%

basics

~20 s

Role + RoleBinding = permissions in one namespace. ClusterRole + ClusterRoleBinding = cluster-wide, including cluster-scoped resources. ClusterRole + RoleBinding = the ClusterRole's rules applied only inside the binding's namespace — the reuse pattern. Role + ClusterRoleBinding is illegal. Aggregated ClusterRoles merge in other ClusterRoles by label selector.

open as a page

Compare the old long-lived ServiceAccount token that Kubernetes stored in a Secret with the token a modern cluster projects into a Pod through the TokenRequest API. What changed regarding expiry, audience, and object binding, and why did those changes matter?

level: middleimportance: must knowfreq 50%

basics

~20 s

The old token was a non-expiring JWT sitting in a Secret, valid for any audience and any holder forever. The projected token from the TokenRequest API expires (about an hour, refreshed in place by the kubelet), is scoped to a named audience, and is bound to the Pod and ServiceAccount, so it dies when the Pod does.

open as a page

When you register an admission webhook with Kubernetes, the configuration has a failurePolicy field set to either Fail or Ignore. What does each value do when the webhook is unreachable, and how do you decide which one a security policy webhook should use?

level: seniorimportance: must knowfreq 50%

basics

~20 s

failurePolicy: Fail rejects any matching API write when the webhook errors or times out — policy holds, but an outage of your webhook blocks writes cluster-wide. failurePolicy: Ignore admits the request unchecked — the cluster keeps working, but policy silently stops being enforced. Security policies want Fail plus a highly available webhook and careful scoping.

open as a page

How would you make Kubernetes Secret data unreadable to someone who obtains a raw copy of the etcd data files or a cluster backup, and what does a KMS provider add over an encryption key configured locally on the control plane?

level: seniorimportance: must knowfreq 50%

basics

~20 s

Configure encryption at rest: pass an EncryptionConfiguration to kube-apiserver naming secrets as a resource. A local aescbc or secretbox key sits in a file on the control-plane node; a KMS provider does envelope encryption so the root key lives in an external KMS/HSM instead. Existing Secrets must be rewritten to become encrypted.

open as a page

How do you scope Kubernetes RBAC so that a workload or a human can read only the Secrets it actually needs, and why is granting the list verb on Secrets almost as dangerous as granting read access to every one of them?

level: seniorimportance: must knowfreq 55%

basics

~20 s

Bind a namespaced Role that grants get on named Secrets via resourceNames, never a ClusterRole with list or watch. list and watch return the full objects including data, and resourceNames cannot restrict them, so list on secrets equals read-everything in scope. Also close the Pod-create and exec escalation paths.

open as a page

How can a Pod obtain short-lived cloud IAM credentials, for example to read an object-storage bucket, without any static cloud access key being stored in the cluster? Describe the trust chain that makes it work.

level: seniorimportance: must knowfreq 50%

basics

~20 s

Workload identity federation: the cluster publishes an OIDC discovery document and JWKS, the cloud IAM provider is configured to trust that issuer, the Pod gets a projected ServiceAccount token minted for the cloud's audience, and the cloud STS exchanges that token for short-lived credentials scoped to a role mapped from the ServiceAccount.

open as a page

A contractor leaving the fraud-rules engine team still holds a Kubernetes client certificate valid for 290 more days. How do you actually cut off their cluster access?

level: seniorimportance: must knowfreq 58%

basics

~20 s

Kubernetes checks no CRL for client certificates, so the certificate keeps authenticating. Remove every RBAC binding matching its CN, re-key any group in its O field, rotate the CA if it holds system:masters, and hunt for credentials they minted.

open as a page

OPA Gatekeeper and Kyverno are the two common policy engines for Kubernetes clusters. How does each one express a policy, and what practical differences would drive you to pick one over the other?

level: middleimportance: should knowfreq 38%

basics

~20 s

Both install as admission webhooks with CRDs. Gatekeeper wraps Open Policy Agent: you write rules in the Rego language inside a ConstraintTemplate, then instantiate Constraint objects. Kyverno uses plain Kubernetes YAML policies with validate, mutate, generate and verifyImages rules — no new language, and it can also create and clone resources.

open as a page

Kubernetes ships a built-in ValidatingAdmissionPolicy resource whose rules are written in CEL (Common Expression Language) and evaluated inside the API server. How does it work, and when would you pick it over an external validating admission webhook?

level: middleimportance: should knowfreq 45%

basics

~20 s

ValidatingAdmissionPolicy holds CEL expressions the API server evaluates in-process on incoming objects. A ValidatingAdmissionPolicyBinding scopes it to namespaces or resources and picks the action: Deny, Warn, or Audit. No external service means no serving certificates, no network hop, no availability risk. But CEL cannot mutate or call out.

open as a page

In Kubernetes, what are the user system:anonymous and the group system:unauthenticated, when does a request end up with them, and why is binding a ClusterRole to system:unauthenticated dangerous?

level: middleimportance: should knowfreq 32%

basics

~20 s

When every authenticator abstains and anonymous access is enabled, the API server treats the request as user system:anonymous in group system:unauthenticated instead of returning 401. Any RBAC binding to that group applies to anybody who can reach the API server with no credentials at all — so binding a powerful ClusterRole to it exposes the cluster to unauthenticated callers.

open as a page

Why is an open Kubernetes kubelet API on port 10250 a node-takeover risk, and which kubelet settings lock it down?

level: middleimportance: should knowfreq 48%

basics

~20 s

The kubelet API can run commands in any container on its node and read its logs, so anonymous access there means code execution. Disable anonymous auth, enable webhook authentication and Webhook authorization, and set readOnlyPort to 0.

open as a page

A workload's ServiceAccount is getting HTTP 403 Forbidden from the Kubernetes API server. How do you determine exactly which permission is missing and which binding should grant it?

level: middleimportance: should knowfreq 48%

basics

~20 s

Read the 403 message — it names the user, verb, resource and namespace. Reproduce it with kubectl auth can-i <verb> <resource> -n <ns> --as system:serviceaccount:<ns>:<sa>, and list the whole effective set with kubectl auth can-i --list --as that identity. Then add the narrowest rule, usually a RoleBinding in that namespace.

open as a page

Why do hardened Kubernetes deployments prefer mounting a Secret as a file through a volume rather than injecting it into the container as an environment variable with secretKeyRef, and how does that choice affect what happens when the Secret's value is later rotated?

level: middleimportance: should knowfreq 55%

basics

~20 s

Environment variables leak: they are visible in /proc/<pid>/environ, inherited by every child process, and captured by crash reporters and debug endpoints. They are also frozen at container start, so a rotated Secret needs a Pod restart. Mounted files stay off the process environment and the kubelet refreshes them in place.

open as a page

Most application Pods never call the Kubernetes API, yet by default each one carries a credential for it. How do you stop that credential from being mounted, which two places accept the setting, and which one wins when they disagree?

level: middleimportance: should knowfreq 45%

basics

~20 s

Set automountServiceAccountToken: false. It can go on the ServiceAccount object, which applies to every Pod using it, or in the Pod spec, which applies to that Pod. The Pod spec wins when both are set. Without a mounted token, a compromised container has no API credential to steal.

open as a page

How do you issue a Kubernetes client certificate through the CertificateSigningRequest API, and how does the API server derive the username and groups?

level: middleimportance: should knowfreq 56%

basics

~20 s

Submit their PKCS#10 request as a CertificateSigningRequest with signer kubernetes.io/kube-apiserver-client, approve it with kubectl certificate approve, and read status.certificate. The API server takes the certificate's CN as the username and each O as a group.

open as a page

When a Kubernetes API server trusts an OIDC identity provider, what does the API server verify and what does a kubeconfig exec credential plugin do?

level: middleimportance: should knowfreq 52%

basics

~20 s

The API server only verifies ID tokens from a configured issuer and maps claims to a username and groups. A kubeconfig exec plugin performs the login, caches the token and gives it to kubectl, which sends it as a bearer token.

open as a page

How would you enforce, at Kubernetes admission time, that workloads may only run container images from approved registries, pinned by digest, and carrying a valid signature?

level: seniorimportance: should knowfreq 34%

basics

~20 s

Use an admission policy engine. A simple CEL or YAML rule can require the image reference to start with an approved registry prefix and to contain an @sha256: digest. Signature and provenance checks need an engine that can reach the registry — for example Kyverno's verifyImages with cosign — which verifies the signature and rewrites the tag to the verified digest.

open as a page

You must be able to show from Kubernetes audit records who read a database-credentials Secret, who opened kubectl exec sessions, and who changed RBAC bindings. What audit Policy rules do you write?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Record Secret get, list and watch at Metadata, pods/exec, attach and portforward at Metadata for any verb, and RBAC object writes at RequestResponse, all placed above any exclusion or broad rule. Never exclude service-account traffic wholesale.

open as a page

The Kubernetes API server can run several authorization modules — including RBAC, Node, and Webhook. How do multiple modules combine to reach a decision, and what specific problem does the Node authorizer solve?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Modules are consulted in order; each returns allow, deny, or no-opinion. The first explicit allow or deny ends the chain, and if every module abstains the request is denied with 403. RBAC only grants — it never denies. The Node authorizer restricts each kubelet to the objects tied to pods on its own node, instead of granting all kubelets blanket read access.

open as a page

showing 1–30 of 41