How does authentication work in the Kubernetes API server?

advanced|architecturedevopssrecloud architectCKA
TL;DR

The Kubernetes API server supports multiple authentication methods including client certificates, bearer tokens, OIDC, and service account tokens. Requests pass through all configured authenticators until one succeeds. Once authenticated, the identity is passed to authorization (RBAC) and admission control before the request is processed.

Detailed Answer

The Kubernetes API server implements a pluggable authentication system where multiple authentication methods (called authenticators) run in parallel for each request. The first authenticator to successfully validate the request determines the caller's identity. If all authenticators fail, the request is rejected with a 401 Unauthorized response.

Authentication Methods

X.509 Client Certificates -- The most common method for cluster components and administrators. The API server is configured with a CA certificate, and any client presenting a certificate signed by that CA is authenticated. The Common Name (CN) becomes the username, and Organization (O) fields become group memberships.

# Generate a client certificate for a user
openssl genrsa -out jane.key 2048
openssl req -new -key jane.key -out jane.csr -subj "/CN=jane/O=developers"

# Sign with the cluster CA
openssl x509 -req -in jane.csr \
  -CA /etc/kubernetes/pki/ca.crt \
  -CAkey /etc/kubernetes/pki/ca.key \
  -CAcreateserial \
  -out jane.crt -days 365

# Add to kubeconfig
kubectl config set-credentials jane \
  --client-certificate=jane.crt \
  --client-key=jane.key

kubectl config set-context jane-context \
  --cluster=kubernetes \
  --user=jane \
  --namespace=development

# Test authentication
kubectl --context=jane-context get pods

Service Account Tokens -- Kubernetes automatically provisions service accounts for pods. Since v1.24, pods receive bound service account tokens, which are short-lived, audience-scoped JWTs projected as volumes:

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  serviceAccountName: my-app-sa
  containers:
  - name: app
    image: my-app:latest
    # Token is automatically mounted at:
    # /var/run/secrets/kubernetes.io/serviceaccount/token
    volumeMounts:
    - name: kube-api-access
      mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      readOnly: true
# Create a service account
kubectl create serviceaccount my-app-sa

# Create a token manually (for external use)
kubectl create token my-app-sa --duration=1h

# Inspect the token (it's a JWT)
kubectl create token my-app-sa | cut -d. -f2 | base64 -d | python3 -m json.tool
# Shows: iss, sub, aud, exp, iat, kubernetes.io claims

OpenID Connect (OIDC) -- Integrates with identity providers like Keycloak, Okta, Azure AD, or Google:

# API server flags for OIDC
spec:
  containers:
  - command:
    - kube-apiserver
    - --oidc-issuer-url=https://accounts.google.com
    - --oidc-client-id=kubernetes
    - --oidc-username-claim=email
    - --oidc-groups-claim=groups
    - --oidc-ca-file=/etc/kubernetes/pki/oidc-ca.crt

Webhook Token Authentication -- Delegates token validation to an external service:

# API server flag
--authentication-token-webhook-config-file=/etc/kubernetes/webhook-authn.yaml

# webhook-authn.yaml
apiVersion: v1
kind: Config
clusters:
- name: authn-service
  cluster:
    server: https://authn.example.com/authenticate
    certificate-authority: /etc/kubernetes/pki/authn-ca.crt
users:
- name: api-server
  user:
    client-certificate: /etc/kubernetes/pki/authn-client.crt
    client-key: /etc/kubernetes/pki/authn-client.key

Bootstrap Tokens -- Short-lived tokens used during cluster bootstrapping (kubeadm join):

# Create a bootstrap token
kubeadm token create --ttl 24h --print-join-command

Authentication Flow

Client Request
    |
    v
+----------------------------+
| API Server Auth Chain      |
| 1. Client Certificate?     | -> Check CN/O against CA
| 2. Bearer Token?           | -> Check against token auth file, SA tokens, OIDC
| 3. Webhook?                | -> Delegate to external service
| 4. Anonymous?              | -> system:anonymous (if enabled)
+----------------------------+
    |
    v (identity established)
Authorization (RBAC)
    |
    v
Admission Control

Verifying Authentication

# Check who you are authenticated as
kubectl auth whoami  # Kubernetes 1.27+

# Or use the legacy method
kubectl get --raw='/apis/authentication.k8s.io/v1/selfsubjectreviews' \
  -o jsonpath='{.status.userInfo}'

# Test if a user can perform an action
kubectl auth can-i create deployments --as=jane --namespace=production
kubectl auth can-i '*' '*' --as=system:serviceaccount:default:my-app-sa

# View RBAC bindings for a user
kubectl get clusterrolebindings -o json | \
  python3 -c "import json,sys;[print(b['metadata']['name']) for b in json.load(sys.stdin)['items'] if any(s.get('name')=='jane' for s in b.get('subjects',[]))]"

Security Best Practices

  1. Disable anonymous authentication in production (--anonymous-auth=false)
  2. Use short-lived tokens -- Prefer bound service account tokens and OIDC over static tokens
  3. Rotate certificates -- Use cert-manager or kubeadm certs renew to rotate before expiry
  4. Audit authentication -- Enable API server audit logging to track authentication events
  5. Use RBAC -- Always pair authentication with fine-grained RBAC policies
  6. Minimize service account privileges -- Avoid using the default service account; create dedicated ones with minimal permissions

Why Interviewers Ask This

Authentication is a critical security boundary. Interviewers ask this to evaluate whether a candidate understands how cluster access is secured, how service accounts work, and how to integrate external identity providers. This is essential for securing production clusters.

Common Follow-Up Questions

How do service account tokens work in Kubernetes?
Since v1.24, Kubernetes uses bound service account tokens (short-lived, audience-bound JWTs) projected into pods via a volume. The API server validates them using the service account signing key. Legacy static tokens are deprecated.
How would you integrate OIDC for user authentication?
Configure the API server with --oidc-issuer-url, --oidc-client-id, and --oidc-username-claim flags. Users authenticate with the OIDC provider and present the resulting token to the API server, which validates it directly.
What is the difference between authentication and authorization in Kubernetes?
Authentication determines WHO you are (identity). Authorization determines WHAT you can do (permissions). Authentication runs first; if it passes, RBAC or another authorizer checks if the identity has permission for the requested action.

Key Takeaways

  • Multiple authentication strategies run simultaneously; the first to succeed determines identity
  • Service accounts are for pod-to-API-server communication; user accounts are for human/CI access
  • Bound service account tokens (short-lived, audience-scoped JWTs) replaced static secret-based tokens