RBAC (Role-Based Access Control)
Secure your cluster with Roles, ClusterRoles, and ServiceAccounts β granting only the permissions each workload actually needs.
kubectl command run by a cluster administrator? How are permissions bound to a ServiceAccount under the hood? Think about this security handshake before reading.Kubernetes Has No Built-In User Accounts
Unlike database systems or operating systems, Kubernetes has no built-in user database. There is no kubectl create user command, and human user objects do not exist in etcd. Human identity is decoupled and comes from:
- x509 client certificates: The API server authenticates requests by validating a client certificate signed by the cluster root Certificate Authority (CA). The Certificate's Common Name (CN) is parsed as the username, and the Organization (O) fields are mapped to groups (e.g.,
system:masters). - OIDC tokens: The API server authenticates JWTs from an external identity provider (like Dex, Okta, Keycloak, Google, or Azure AD) configured via api-server flags (
--oidc-issuer-url, etc.). - Static token files / Webhooks: The API server delegates authentication to an external HTTPS webhook or reads from a local CSV token file.
Kubernetes does, however, have a first-class, etcd-persisted object for workload identity: the ServiceAccount.
ServiceAccount
A ServiceAccount is a namespaced identity for Pods (not humans). Every namespace has a default ServiceAccount that all Pods use unless you specify otherwise.
spec: serviceAccountName: app-reader
Starting in Kubernetes 1.24+, tokens are no longer statically stored as Secret objects in etcd. Instead, they are dynamic, short-lived (audience-bound and time-bound) JWTs generated on-demand by the TokenRequest API. The kubelet automatically projects this token into the Pod container at /var/run/secrets/kubernetes.io/serviceaccount/token using a projected volume mounted on a tmpfs (RAM disk) to prevent local disk exposure.
Visualizing RBAC Authorization Flow
HTTP/gRPC Request (kubectl or Pod)
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β KUBERNETES API SERVER β
β β
β [Phase 1: Authentication (Authn)] β
β - X.509 client certificates (signed by Cluster CA) β
β - OIDC / Webhook tokens (e.g., Dex, Okta, Azure AD) β
β - ServiceAccount JWT (TokenRequest API projected volume) β
β β β
β βΌ (Identity Resolved) β
β β
β [Phase 2: Authorization (Authz)] β
β - RBAC Engine: Evaluates Rules & Bindings β
β - Subjects (User / Group / ServiceAccount) β
β - API Group & Resource mapping (e.g., apiGroups: [""]) β
β - Verbs validation (get, list, watch, create, update...) β
β β β
β βΌ (Access Granted) β
β β
β [Phase 3: Admission Control] β
β - Mutating & Validating Webhooks β
β β β
ββββββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββββ
βΌ
[etcd Storage]
(Raft consensus commit)
Roles and ClusterRoles
Permissions are strictly additive (whitelist-only); there are no deny rules.
| Object | Scope | Use case |
|---|---|---|
| Role | Namespace-scoped | Grant access to resources inside a single namespace |
| ClusterRole | Cluster-scoped | Access across all namespaces, or cluster-scoped resources (Nodes, PVs, namespaces) |
A Role defines what is allowed β resources, API groups, and verbs:
rules: - apiGroups: [""] # "" indicates the core API group resources: ["pods", "pods/status", "pods/log"] # resources and subresources verbs: ["get", "list", "watch"]
Available verbs: get (fetch specific resource), list (list resources), watch (stream real-time changes), create (POST new), update (PUT replace), patch (PATCH modify), delete (DELETE single), deletecollection (DELETE bulk).
API request paths map to resources:
- Core group:
/api/v1/namespaces/default/pods - Named group:
/apis/apps/v1/namespaces/default/deployments
RoleBindings and ClusterRoleBindings
A RoleBinding attaches a Role (or ClusterRole) to a subject β a User, Group, or ServiceAccount β within one namespace.
A ClusterRoleBinding attaches a ClusterRole to a subject cluster-wide.
Role ββββββββββββββββββββββββ RoleBinding ββββ Subject (ServiceAccount / User) ClusterRole ββββ ClusterRoleBinding ββββ Subject (cluster-wide) ClusterRole ββββ RoleBinding ββββ Subject (restricted to RoleBinding's namespace)
view or edit) while restricting the subject's access strictly to the namespace of the RoleBinding.Principle of Least Privilege & SubjectAccessReview
Grant only the minimum permissions required. Common security risks include:
- Using
ClusterRoleBindingwhen a namespacedRoleBindingis sufficient. - Granting
*wildcard verbs on*wildcard resources. - Granting update permissions on security-sensitive resources like
secretsorpods/exec.
Under the hood, authorization checks are evaluated by the API server using a SubjectAccessReview API call. You can run this check locally using:
kubectl auth can-i list pods --as=system:serviceaccount:default:app-reader