Skip to content

RBAC

RBAC governs what authenticated identities can do in Kubernetes.

Authentication answers who the caller is. Authorization with RBAC answers what that caller is allowed to do.

Core RBAC objects

graph LR
    SA[ServiceAccount\nor User / Group] --> RB[RoleBinding]
    RB --> R[Role\nnamespace-scoped]
    R --> PERM[verbs on resources\nin namespace]

    SA2[ServiceAccount\nor User / Group] --> CRB[ClusterRoleBinding]
    CRB --> CR[ClusterRole\ncluster-scoped]
    CR --> PERM2[verbs on resources\ncluster-wide]
  • Role: grants permissions within a single namespace.
  • ClusterRole: grants permissions cluster-wide, or defines a reusable permission set applied per-namespace via RoleBinding.
  • RoleBinding: attaches a Role or ClusterRole to subjects within one namespace.
  • ClusterRoleBinding: attaches a ClusterRole to subjects across the entire cluster.

RBAC is allow-only

There are no deny rules in RBAC. Every permission is a grant, and a request is allowed if any role bound to the caller (directly, or via a group) permits it. This has two important consequences:

  • You cannot subtract. There is no way to write "team-a can do everything except read Secrets." You must construct the permission set additively, granting only what's intended.
  • Review means finding the union. A user's effective access is the union of every binding that matches them or their groups. kubectl auth can-i --list --as=<user> -n <ns> shows the computed result.

RBAC is also only one authorizer in a chain. The API server consults its configured authorization modes in order (typically Node, then RBAC, and in some clusters a webhook); the first authorizer that allows wins, and denial just means "ask the next one." This is why external policy systems can grant access RBAC knows nothing about.

Scope and reuse model

A common pattern is to define reusable ClusterRoles and bind them per namespace with RoleBindings.

This gives consistency without giving global access. Note the asymmetry rule: the binding's location decides the scope. A RoleBinding referencing a ClusterRole grants those permissions only inside the binding's namespace -- the ClusterRole is just a reusable template. A roleRef is immutable once created; changing what a binding points to requires recreating it.

Role example

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-reader
  namespace: team-a
rules:
  - apiGroups: [""]
    resources: ["pods", "services", "configmaps"]
    verbs: ["get", "list", "watch"]

RoleBinding example

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-reader-binding
  namespace: team-a
subjects:
  - kind: Group
    name: team-a-developers
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: app-reader
  apiGroup: rbac.authorization.k8s.io

Service account access

Workloads should use dedicated service accounts, not the namespace default account.

Pair each service account with only the minimal verbs and resources it needs.

Disable automatic token mounting for service accounts that don't need API access:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app
automountServiceAccountToken: false

Or per-pod:

spec:
  automountServiceAccountToken: false

By default, every pod gets a token for the namespace's default service account, even if it never uses the Kubernetes API. Disabling this reduces the blast radius if a pod is compromised.

Validation and troubleshooting

kubectl auth can-i list pods -n team-a
kubectl auth can-i create deployments --as=system:serviceaccount:team-a:deployer -n team-a
kubectl get role,rolebinding -n team-a
kubectl get clusterrole,clusterrolebinding

Hardening guidance

  • avoid broad wildcard rules unless explicitly justified
  • tightly control secrets, pods/exec, and impersonate permissions
  • minimize use of cluster-admin
  • review bindings on a fixed cadence and remove stale access

Watch for privilege escalation paths, not just direct grants. Permissions that are effectively cluster-admin in disguise: create on pods in kube-system (mount any secret), escalate/bind on roles, create on clusterrolebindings, write access to mutating webhook configurations, and pods/exec into privileged pods. RBAC prevents you granting permissions you don't hold -- unless the caller has the escalate verb, which is why that verb deserves special scrutiny.

Certification notes

  • CKA and CKS both test RBAC directly. Practice the imperative forms: kubectl create role, create rolebinding, create clusterrole, create clusterrolebinding with --verb and --resource flags.
  • Service account subjects are written system:serviceaccount:<namespace>:<name> -- the exact spelling matters.
  • kubectl auth can-i <verb> <resource> --as=system:serviceaccount:ns:sa is the fastest way to verify your answer before moving on.

Summary

RBAC is a primary control plane security boundary. It is allow-only and additive -- keep permissions explicit, minimal, and auditable, and treat escalation-capable verbs as crown jewels.