9.1 Kubernetes Security & Access Control (RBAC & ServiceAccounts)
Key Takeaways
- Authentication verifies the caller's identity (who you are) using X.509 client certificates, bearer tokens, or OpenID Connect (OIDC), whereas Authorization determines permissions (what you can do) via Role-Based Access Control (RBAC).
- Kubernetes RBAC rules pair API subjects (Users, Groups, ServiceAccounts) with API resources (Pods, Deployments, Secrets) using explicit action verbs such as get, list, watch, create, update, and delete.
- Namespaced RBAC primitives (Role and RoleBinding) govern permissions within a single namespace, whereas cluster-scoped primitives (ClusterRole and ClusterRoleBinding) govern non-namespaced resources (Nodes, PersistentVolumes) or grant uniform access across all namespaces.
- ServiceAccounts provide API identities for workloads running inside Pods, utilizing Bound ServiceAccount Token Volume Projection to dynamically issue time-limited, audience-bound JWT bearer tokens rotated automatically by the kubelet.
- Admission Controllers intercept API requests after authentication and authorization; Mutating Webhooks modify objects before schema validation (such as injecting sidecar containers), while Validating Webhooks enforce governance policies including Pod Security Standards.
9.1 Kubernetes Security & Access Control (RBAC & ServiceAccounts)
Quick Answer: Kubernetes secures access through a sequential multi-stage security pipeline: Authentication (verifying caller identity via X.509 client certificates, service account tokens, or OIDC) followed by Authorization (enforcing permissions via Role-Based Access Control). ServiceAccounts grant API identity to workloads running inside Pods, while Admission Controllers (including Validating/Mutating Webhooks and Pod Security Standards) enforce structural and runtime security policies before objects are persisted to etcd.
Securing a Kubernetes cluster requires a defense-in-depth approach spanning identity management, fine-grained access control, workload isolation, and admission governance. Because the kube-apiserver acts as the single gateway for all operations within a cluster, every incoming request must successfully pass through multiple security checkpoints before any state modification occurs.
Incoming HTTP Request
│
▼
┌──────────────┐ Failed
│ Authentication├───────────────────► HTTP 401 Unauthorized
└──────┬───────┘
│ Verified Identity
▼
┌──────────────┐ Failed
│ Authorization ├───────────────────► HTTP 403 Forbidden
└──────┬───────┘
│ Authorized
▼
┌──────────────────────────────┐
│ Mutating Admission Webhooks │ ──► Modifies Request (e.g., sidecar injection)
└──────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ Object Schema Validation │ ──► Validates OpenAPI Spec
└──────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ Validating Admission Webhooks│ ──► Rejects Non-compliant Objects (e.g., PSS)
└──────────────┬───────────────┘
│ Approved
▼
┌──────────────────────────────┐
│ Persisted to etcd │
└──────────────────────────────┘
Authentication vs. Authorization in Kubernetes
Understanding the distinction between Authentication (AuthN) and Authorization (AuthZ) is fundamental to Kubernetes security:
- Authentication (AuthN): Confirms who is making the request. Kubernetes distinguishes between human users (administrators, developers) and service accounts (workloads). Notably, Kubernetes does not maintain an API object for human user accounts. Instead, human identities are verified externally through X.509 client certificates, static bearer tokens, or identity providers via OpenID Connect (OIDC).
- Authorization (AuthZ): Determines what an authenticated identity is permitted to do. After identity is confirmed, the API server evaluates the request against authorization modules. While Kubernetes supports multiple authorizers (ABAC, Node, Webhook), Role-Based Access Control (RBAC) is the industry standard and default mechanism.
RBAC Primitives: Roles, ClusterRoles, and Bindings
Kubernetes RBAC is driven by four declarative API objects defined in the rbac.authorization.k8s.io/v1 API group. Permissions are strictly additive (there are no explicit "deny" rules).
The Four Core RBAC Objects
- Role: Defines a set of permission rules within a single specific namespace. A Role specifies API groups, resources (e.g.,
pods,services), and allowed actions called Verbs (e.g.,get,list,watch,create,update,delete). - ClusterRole: Defines permissions at the cluster level. ClusterRoles can govern non-namespaced resources (such as
nodes,persistentvolumes, or/healthz), namespaced resources across all namespaces, or non-resource endpoints (like/metrics). - RoleBinding: Grants the permissions defined in a Role (or ClusterRole) to a list of Subjects (Users, Groups, or ServiceAccounts) within a specific namespace.
- ClusterRoleBinding: Grants the permissions defined in a ClusterRole to subjects across the entire cluster, spanning all namespaces.
RBAC Primitive Comparison Matrix
| RBAC Primitive | Scope | Target Resources | Common Use Case |
|---|---|---|---|
| Role | Namespaced | Namespaced resources (pods, deployments, services) | Granting developers read/write access inside a dev namespace |
| ClusterRole | Cluster-Wide | Non-namespaced resources (nodes, pv) OR all namespaced resources | Defining cluster-wide monitoring, security scanner, or admin privileges |
| RoleBinding | Namespaced | References a Role or ClusterRole | Binding a role to a developer team restricted to namespace finance |
| ClusterRoleBinding | Cluster-Wide | References a ClusterRole | Binding cluster-admin permissions to a CI/CD deployment controller |
Declarative RBAC Manifest Examples
Example 1: Namespaced Role and RoleBinding
The following manifest creates a Role named pod-reader in namespace engineering allowing read-only access to Pods, and binds it to a ServiceAccount named app-scanner.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: engineering
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-binding
namespace: engineering
subjects:
- kind: ServiceAccount
name: app-scanner
namespace: engineering
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Example 2: ClusterRole and ClusterRoleBinding
The following manifest grants a cluster-wide metrics collector read permissions for node infrastructure.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-metrics-reader
rules:
- apiGroups: [""]
resources: ["nodes", "nodes/stats", "nodes/metrics"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: collector-node-binding
subjects:
- kind: ServiceAccount
name: prometheus-node-exporter
namespace: monitoring
roleRef:
kind: ClusterRole
name: node-metrics-reader
apiGroup: rbac.authorization.k8s.io
Workload Identity: ServiceAccounts & Token Projection
While human users access the cluster via credentials managed outside Kubernetes, in-cluster processes running inside Pods require their own identity to authenticate to the kube-apiserver. This identity is provided by the ServiceAccount resource.
Every namespace contains a default ServiceAccount created automatically. When a Pod is created without explicitly nominating a serviceAccountName, it inherits this default account.
Bound ServiceAccount Token Volume Projection
Modern Kubernetes clusters use projected service account tokens (ProjectedVolumeSource). Instead of static secrets mounted permanently, the kubelet dynamically projects a JSON Web Token (JWT) into the Pod container at /var/run/secrets/kubernetes.io/serviceaccount/token with the following security features:
- Time-Limited: Tokens have a configurable expiration lifetime (e.g., 1 hour) and are automatically rotated by the local
kubeletbefore expiration. - Audience-Bound: Tokens contain an
audclaim matching the intended recipient (e.g.,https://kubernetes.default.svc), preventing stolen token reuse against unrelated services. - Pod-Bound: Tokens are tied to the specific lifetime and UID of the Pod instance.
Security Best Practice: If a Pod does not need to communicate with the Kubernetes API server, set
automountServiceAccountToken: falsein the Pod or ServiceAccount specification to enforce the principle of least privilege.
Pod Security Standards (PSS) & Admission Controllers
Admission Controllers are specialized plugins that intercept requests to the API server after authentication and authorization complete, but before the object is stored in etcd.
Mutating vs. Validating Webhook Admission
- Mutating Admission Webhooks: Can modify incoming object specs. For example, a service mesh sidecar injector intercepts a Pod creation request and mutates the spec to append a proxy sidecar container.
- Validating Admission Webhooks: Evaluate object specs against compliance rules and reject requests that violate policy. They cannot alter objects.
Pod Security Standards (PSS)
Replacing legacy PodSecurityPolicies, Pod Security Standards (PSS) define three predefined security profiles to prevent container privilege escalation:
- Privileged: Unrestricted profile providing wide-open permissions. Intended for system-level infrastructure workloads (e.g., CNI plugins, storage drivers) requiring root access, host networking, or device access.
- Baseline: Minimal restriction profile designed for standard application workloads. Prevents known privilege escalations by restricting host port usage, host path mounts, and host namespaces (
hostPID,hostNetwork). - Restricted: Highly hardened profile following current pod hardening best practices. Requires containers to run as non-root users, forces read-only root filesystems, drops all capabilities (
capabilities.drop: ["ALL"]), and enforces strict seccomp profiles.
Pod Security Standards are enforced built-in via Pod Security Admission (PSA) using namespace labels:
metadata:
name: secure-production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/warn: baseline
Which RBAC object combination should be used to grant a ServiceAccount read access to Pods strictly within the 'staging' namespace?
How does Kubernetes handle modern ServiceAccount authentication for workloads executing inside Pods?
Which Pod Security Standards (PSS) profile enforces strict hardening controls such as requiring non-root execution, dropping all capabilities, and enforcing read-only root filesystems?