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?
answer
- no User object — identity is just username + UID + groups
- cert: CN → user, O → groups; no CRL support
- SA token: system:serviceaccount:ns:name; projected = audience-bound, expiring
- OIDC = humans (short-lived, revocable, SSO groups)
- chain of authenticators, first success wins
basics
~20 sAn 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.
solid answer
~60 sThe API server runs a chain of authenticators; each abstains or returns an identity, and the first success wins: - **X.509 client certificates** signed by a CA in `--client-ca-file`: subject **CN → username**, each **O → group**. Revocation is the weak point — there is no CRL support, so you rotate the CA or keep lifetimes short. - **ServiceAccount tokens**: signed JWTs. Modern projected tokens are audience-scoped, time-limited, and bound to the pod; identity is `system:serviceaccount:<ns>:<name>` with groups `system:serviceaccounts` and `system:serviceaccounts:<ns>`. - **OIDC ID tokens** from an external IdP: the API server validates the signature via JWKS and maps `--oidc-username-claim`/`--oidc-groups-claim` (optionally prefixed). The standard way to authenticate humans, because it gives short-lived, centrally revocable credentials and SSO groups. - **Webhook token authentication**: the API server posts a TokenReview to an external service — how managed clouds accept their own tokens. - **Authenticating proxy headers** and **bootstrap tokens** for narrow cases. Static token/password files are legacy; don't use them. Whatever succeeds, the API server carries forward only username, UID, groups, and optional extras — RBAC then binds to those strings.
code
bash · 12 lines# Identity the API server assigns to your current kubeconfig context
kubectl auth whoami
# Subject line of a client certificate: CN becomes the user, each O a group
openssl x509 -in alice.crt -noout -subject
# subject=CN = alice, O = platform, O = oncall
# Mint a short-lived, audience-scoped token for a ServiceAccount
kubectl create token build-bot -n ci --audience=https://kubernetes.default.svc --duration=10m
# Confirm what a given token authenticates as
kubectl auth whoami --token="$TOKEN"go deeper
Name the three main mechanisms — client certificates, ServiceAccount tokens, OIDC — and know that authentication yields a username and groups, not a stored user record.
Give the exact mappings (CN/O, system:serviceaccount:ns:name, OIDC claims) and explain the first-success-wins chain.
Discuss operational properties: no CRL support, CA rotation as the only revocation, projected bound tokens versus legacy Secrets, and why humans should use OIDC.
Frame it as identity architecture — one authoritative IdP for humans, workload identity for machines, prefixing to prevent claim collisions, and treating CSR approval and token minting as privileged identity-issuance paths.
## The design decision Kubernetes deliberately has **no user database**. There is no `kubectl create user`, no User kind, nothing in etcd representing a human. The API server's job is only to turn incoming credentials into a *claimed identity* — a username, a UID, a set of group strings, and optional extra key/value attributes — and hand that to authorization. Where those credentials come from is delegated to whatever the cluster operator configured. This keeps Kubernetes out of the identity-management business and is why cluster access integrates with corporate SSO rather than duplicating it. ServiceAccounts are the one exception: they *are* real API objects, because in-cluster workloads need an identity the cluster itself can issue and manage. ## The authenticator chain Authenticators run in order. Each one either says "not mine" (abstain) or returns an identity. The first success stops the chain; if all abstain, the request is anonymous or 401. Nothing later can change the identity, and there is no notion of "most privileged wins". ### X.509 client certificates If `--client-ca-file` is set, a client certificate presented during the TLS handshake and signed by that CA authenticates the request. The mapping is fixed and easy to remember: **CN is the username, each O is a group**. So a cert with `CN=alice, O=platform, O=oncall` authenticates as user `alice` in groups `platform` and `oncall`. Certificates are how the control plane's own components authenticate (kubelets present `CN=system:node:<nodename>, O=system:nodes`, which the Node authorizer relies on). For humans they are convenient to bootstrap and painful to operate: Kubernetes does **not** check certificate revocation lists, so a leaked client cert is valid until it expires or you rotate the signing CA — which invalidates everyone. Hence: short lifetimes, and prefer OIDC for people. The `CertificateSigningRequest` API lets clients request certs from the cluster CA, but approval must be controlled — the ability to get a cert signed with `O=system:masters` is cluster-admin. ### ServiceAccount tokens A ServiceAccount is a namespaced object; the API server issues JWTs for it signed with its service-account signing key. The resulting identity is `system:serviceaccount:<namespace>:<name>`, and it is automatically in the groups `system:serviceaccounts` and `system:serviceaccounts:<namespace>` — the latter two are what makes an accidental binding to `system:serviceaccounts` catastrophic. Modern clusters use **projected, bound tokens**: mounted into the pod by the kubelet, valid for a limited period, automatically refreshed, scoped to an **audience**, and bound to the specific pod and ServiceAccount object so they stop working when the pod is deleted. The legacy model — a non-expiring token stored in a Secret — is deprecated precisely because such a token, once exfiltrated, is a permanent credential. ### OIDC ID tokens For humans, the recommended path. The user authenticates against a corporate IdP and receives an ID token (a JWT); `kubectl` sends it as a bearer token. The API server validates the signature against the issuer's JWKS, checks issuer, audience, and expiry, and maps claims to identity via configuration: a username claim (often `email` or `sub`) and a groups claim, each optionally prefixed to avoid collisions with built-in `system:` names. Newer clusters can express this as a structured authentication configuration file with CEL expressions for claim mapping and validation, supporting multiple issuers. The operational advantages are exactly what certificates lack: short-lived tokens, revocation by disabling the account in the IdP, MFA enforced centrally, and group membership sourced from the directory so RBAC binds to real teams. ### Webhook token authentication The API server POSTs a `TokenReview` containing the opaque token to an external service, which replies with the identity or a rejection. This is how managed Kubernetes services accept their cloud provider's own credentials. ### The rest An **authenticating proxy** can assert identity through configured headers, trusted only when the proxy presents a client cert from a dedicated CA — otherwise header spoofing is trivial. **Bootstrap tokens** exist for joining nodes. **Static token and basic-auth files** are legacy and effectively unusable in current versions; naming them as a good option is a red flag. ## What this means downstream Authorization never sees a credential — only strings. So a username from a certificate and the same username from OIDC are indistinguishable to RBAC, which is both convenient and a hazard: if two authenticators can mint the same username, whichever is weaker defines your security. Prefix your OIDC usernames and groups, never issue certs with `O=system:masters` casually, and treat any path that can obtain a signed certificate or a ServiceAccount token as an identity-issuance path deserving the same scrutiny as your IdP.
- Why are client certificates a poor choice for human access to a production cluster?Kubernetes does not consult certificate revocation lists, so a leaked or ex-employee certificate stays valid until it expires; the only true revocation is rotating the signing CA, which invalidates every other certificate at the same time. Certificates also carry group membership baked in at issuance, so a team change requires reissuing. OIDC gives short-lived tokens, central revocation, MFA, and group membership resolved from the directory at login.
- What makes a projected ServiceAccount token safer than the legacy token stored in a Secret?A projected token is issued for a specific audience, has a limited lifetime and is refreshed in place by the kubelet, and is bound to the pod and ServiceAccount objects so it becomes invalid once the pod is gone. The legacy Secret token had no expiry and no audience, so anyone who read that Secret — or exfiltrated the file — held a permanent, universally accepted credential for that ServiceAccount.
The API server is a venue that accepts several kinds of ID — a company badge, a day pass, a government ID from a trusted issuer — but keeps no membership roster of its own; it just reads whichever ID you present and writes your name and affiliations on the wristband.
saying these in an interview costs you the question
- Claiming Kubernetes stores users in etcd or that you can create a User object.
- Getting the certificate mapping backwards (thinking O is the username or that SANs supply groups).
- Treating a ServiceAccount token as safe to hand to a human or to reuse outside the pod.
- Proposing static token files or basic auth as a workable authentication option.
- Assuming a failed authenticator means rejection — the chain continues, and total abstention may yield anonymous access rather than 401.