Kubernetes Security Architecture: RBAC, Service Accounts, and Admission Control
Every administrative and automated request directed at a Kubernetes cluster must traverse a strict three-tier security pipeline inside the kube-apiserver: Authentication (AuthN), Authorization (AuthZ), and Admission Control. Mastering this pipeline alongside Role-Based Access Control (RBAC), Service Accounts, projected tokens, and policy webhooks is fundamental for cluster hardening and real-world certification exams (CKA, CKAD, CKS).
1. The Kubernetes Request Lifecycle: The "Triple A" Framework
When a request arrives at the Kubernetes API server (whether initiated by kubectl, a human engineer, an internal Pod, or a CI/CD pipeline), it passes through three sequential validation gates before persisting state changes into etcd.
The Three Pillars (Triple A)
Note: If a request fails Authentication, the server immediately returns an
HTTP 401 Unauthorized. If it fails Authorization, it returns anHTTP 403 Forbidden. If an Admission Controller rejects it, the server returns anHTTP 400 Bad Requestor anHTTP 403 Forbiddenwith a policy failure description.
2. Authentication (AuthN): Users, Service Accounts, and Token Evolution
Kubernetes distinguishes strictly between Human Users and Machine/Workload Identities (Service Accounts).
Real-Life Analogy
Think of an enterprise office building.
- Human Users are employees wearing external company ID badges issued by HR. Security checks the badge at the front door, but the building itself does not maintain the HR database.
- Service Accounts are internal keycards assigned specifically to automated maintenance robots (Pods) programmed to access only the service elevators and utility closets in a particular wing (Namespace).
Evolution of Service Account Tokens (Kubernetes 1.24+ Transition)
Prior to Kubernetes version 1.24, creating a ServiceAccount automatically created an indefinite, non-expiring Secret containing a long-lived bearer token. This presented a severe security risk.
From Kubernetes 1.24 onward, service account tokens are generated dynamically as short-lived, projected JSON Web Tokens (JWTs).
Inspecting the Decoded JWT Token Payload
A Service Account JWT holds structured claims regarding identity, namespace, and validity:
{
"iss": "https://kubernetes.default.svc.cluster.local",
"sub": "system:serviceaccount:default:deployment-manager",
"kubernetes.io": {
"namespace": "default",
"serviceaccount": {
"name": "deployment-manager",
"uid": "a4d3f101-7c98-4db8-9993-41bb819bdf01"
}
},
"exp": 1715533200
}
Manually Generating Service Account Tokens
# Generate a short-lived token (default 1 hour TTL)
kubectl create token deployment-manager
# Generate a custom token with a prolonged duration (e.g., 1000 hours)
kubectl create token deployment-manager --duration=1000h
3. Kubernetes RBAC Fundamentals: Roles, ClusterRoles, and Bindings
Role-Based Access Control (RBAC) relies on four primary API resources to determine what operations an identity can perform against specific resources.
RBAC Components Breakdown
- Subjects: The target entity (
User,Group, orServiceAccount). - API Groups: The logical API path (e.g.,
""for core resources like Pods/Services,appsfor Deployments/DaemonSets,batchfor Jobs/CronJobs). - Resources: The Kubernetes object type (
pods,deployments,secrets,services,nodes). - Verbs: The authorized actions (
get,list,watch,create,update,patch,delete).
Valid vs. Invalid Scope Combinations
4. Declarative vs. Imperative RBAC Workflows and Verification
Declarative Definitions
1. Creating a Role (role.yaml)
Grants permissions to manage Deployments inside the default namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: deployment-creator
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
2. Creating a RoleBinding (rolebinding.yaml)
Binds the deployment-creator Role to the deployment-manager Service Account:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: bind-deployment-creator
namespace: default
subjects:
- kind: ServiceAccount
name: deployment-manager
namespace: default
roleRef:
kind: Role
name: deployment-creator
apiGroup: rbac.authorization.k8s.io
Fast Imperative Workflow (CKA/CKAD Essential)
In high-speed exam or debugging scenarios, imperative CLI commands generate objects rapidly:
# 1. Create a namespace
kubectl create namespace dev-team
# 2. Create a service account
kubectl create serviceaccount dev-sa -n dev-team
# 3. Create a Role with specific verbs and resources
kubectl create role dev-deployment-manager \
--namespace=dev-team \
--verb=create,get,list,watch \
--resource=deployments.apps
# 4. Bind the Role to the ServiceAccount
kubectl create rolebinding dev-deployment-binding \
--namespace=dev-team \
--role=dev-deployment-manager \
--serviceaccount=dev-team:dev-sa
Permission Verification with kubectl auth can-i
Always verify RBAC rules before deploying workloads:
# Check if the service account can create deployments (Expected: yes)
kubectl auth can-i create deployments \
--as=system:serviceaccount:dev-team:dev-sa \
-n dev-team
# Check if the service account can create services (Expected: no)
kubectl auth can-i create services \
--as=system:serviceaccount:dev-team:dev-sa \
-n dev-team
# Check if the service account can create pods (Expected: no)
kubectl auth can-i create pods \
--as=system:serviceaccount:dev-team:dev-sa \
-n dev-team
5. Attaching Service Accounts to Pods and Deployments
Workloads assume permissions by specifying the serviceAccountName field within their Pod template specification.
Deployment Manifest with Custom Service Account
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
serviceAccountName: deployment-manager
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Automatic Mutation Note: If
serviceAccountNameis omitted from a Pod manifest, Kubernetes defaults it to thedefaultservice account of that namespace via an internal mutating admission controller.
6. Admission Controllers: Mutating vs. Validating Webhooks
Admission Controllers intercept API requests after authentication and authorization succeed, but before the resource is persisted in etcd.
Mutating vs. Validating Comparison
7. Next-Generation Policy Enforcement: ValidatingAdmissionPolicy (CEL)
Starting in Kubernetes 1.26 (alpha) and reaching GA in Kubernetes 1.30, ValidatingAdmissionPolicy provides in-tree, declarative admission control using the Common Expression Language (CEL) without requiring external webhook servers.
Declarative Policy Definition (vap-policy.yaml)
This policy rejects any Deployment configured with more than 5 replicas:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: "max-deployment-replicas.example.com"
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments"]
validations:
- expression: "object.spec.replicas <= 5"
message: "Deployments cannot exceed 5 replicas in this cluster environment."
Policy Binding Definition (vap-binding.yaml)
Binds the policy specifically to namespaces labeled with environment: test:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: "max-replicas-test-binding"
spec:
policyName: "max-deployment-replicas.example.com"
validationActions: [Deny]
matchResources:
namespaceSelector:
matchLabels:
environment: test
8. Deep-Dive: Hardening Clusters with ImagePolicyWebhook
The ImagePolicyWebhook is an admission plugin used to evaluate container images prior to Pod creation (e.g., verifying image signatures, ensuring images originate only from trusted private registries, or checking vulnerability scan statuses).
Cluster Configuration Setup
1. Admission Control Configuration File (admission-config.json)
Placed inside /etc/kubernetes/admission/:
{
"apiVersion": "apiserver.config.k8s.io/v1",
"kind": "AdmissionConfiguration",
"plugins": [
{
"name": "ImagePolicyWebhook",
"configuration": {
"imagePolicy": {
"kubeConfigFile": "/etc/kubernetes/admission/image-policy-kubeconfig.yaml",
"allowTTL": 50,
"denyTTL": 50,
"retryBackoff": 500,
"defaultAllow": false
}
}
}
]
}
2. Kubeconfig for Image Policy Server (image-policy-kubeconfig.yaml)
apiVersion: v1
kind: Config
clusters:
- name: image-checker
cluster:
certificate-authority: /etc/kubernetes/admission/ca.crt
server: https://image-validator.internal.net:8443/image-policy
contexts:
- name: image-checker-context
context:
cluster: image-checker
user: apiserver
current-context: image-checker-context
users:
- name: apiserver
user:
client-certificate: /etc/kubernetes/admission/client.crt
client-key: /etc/kubernetes/admission/client.key
3. Enabling Plugin in kube-apiserver.yaml
Add flags and mount paths to /etc/kubernetes/manifests/kube-apiserver.yaml:
spec:
containers:
- name: kube-apiserver
command:
- kube-apiserver
- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook
- --admission-control-config-file=/etc/kubernetes/admission/admission-config.json
volumeMounts:
- mountPath: /etc/kubernetes/admission
name: admission-config
readOnly: true
volumes:
- hostPath:
path: /etc/kubernetes/admission
type: DirectoryOrCreate
name: admission-config
9. Production Debugging & Best Practices: API Server & RBAC
When configuring API server flags, static pods, and security policies in production environments, misconfigurations can bring down control plane access.
Critical Troubleshooting Checklist
-
API Server Fails to Start:
- Check container runtime logs using
crictl logs $(crictl ps -a --name kube-apiserver -q | head -n 1). - Verify that paths referenced in
--admission-control-config-filematch the container's internalvolumeMounts, not just the host paths.
- Check container runtime logs using
-
Diagnosing RBAC 403 Forbidden Errors:
- Trace the exact failure identity using:
BASH
kubectl auth can-i <verb> <resource> --as=system:serviceaccount:<namespace>:<sa-name> -n <namespace> - Ensure the API Group is explicitly defined (e.g.,
appsfor deployments,""for core resources like configmaps or pods).
- Trace the exact failure identity using:
-
ServiceAccount Token Lifetime Management:
- Do not rely on persistent static tokens inside Pods. Design applications to leverage auto-rotated projected tokens provided at
/var/run/secrets/kubernetes.io/serviceaccount/token.
- Do not rely on persistent static tokens inside Pods. Design applications to leverage auto-rotated projected tokens provided at
Summary and Key Takeaways
- The Request Pipeline: Every request to the
kube-apiserverstrictly traverses Authentication, Authorization (RBAC), and Admission Control before reachingetcd. - User vs. Service Account: Kubernetes delegates human authentication to external systems (X.509/OIDC), whereas
ServiceAccountsare managed internally for workload identity. - Service Account Token Modernization: Kubernetes 1.24+ deprecated automatic static secret generation in favor of short-lived, rotatable JWT projected tokens with a default 1-hour expiration.
- RBAC Building Blocks:
RolesandRoleBindingsgovern namespace-scoped permissions, whileClusterRolesandClusterRoleBindingsenforce permissions across all namespaces or cluster-scoped resources. - ClusterRole Reuse: A
ClusterRolebound via aRoleBindingrestricts the defined cluster permissions exclusively to the namespace of thatRoleBinding. - Validation Testing: The
kubectl auth can-i <verb> <resource> --as=<user/SA>command allows deterministic dry-run verification of RBAC rules. - Two-Stage Admission: Mutating Webhooks execute first to inject defaults or modify requests; Validating Webhooks execute second to accept or reject compliant configurations.
- Declarative Governance with CEL:
ValidatingAdmissionPolicyenables fast, in-tree policy enforcement directly inside the API server without external webhook infrastructure. - Control Plane Safety: Always create a physical backup of
/etc/kubernetes/manifests/kube-apiserver.yamlbefore enabling admission plugins or modifying static control-plane manifests.