Kubernetes RBAC
Every request to the Kubernetes API, whether from kubectl, a CI pipeline, or a controller running in a Pod, goes through authentication (who are you?) and then authorization (are you allowed to do this?). Role-Based Access Control (RBAC) is the standard authorizer. It grants permissions by attaching Roles (sets of allowed verbs on resources) to subjects (users, groups, ServiceAccounts) through bindings.
RBAC is purely additive: there are no deny rules. A subject can do exactly the union of everything its bindings grant. That makes it easy to reason about and easy to over-grant, which is why least privilege takes deliberate effort.
TL;DR
- A Role grants verbs (
get,list,watch,create,update,patch,delete) on resources within one namespace. - A ClusterRole does the same cluster-wide, or for cluster-scoped resources such as nodes and namespaces.
- A RoleBinding grants a Role or ClusterRole to subjects in one namespace; a ClusterRoleBinding grants it everywhere.
- Subjects are users and groups (from your identity provider or certificates) and ServiceAccounts (identities for Pods).
- Permissions are additive. There's no "deny", so grant narrowly.
- Check access with
kubectl auth can-i, and never hand outcluster-admincasually.
Quick Example
Let a CI pipeline deploy into the staging namespace, and nothing else:
Core Concepts
Rules: API Groups, Resources, Verbs
Each rule lists apiGroups ("" is the core group for Pods, Services, Secrets, and ConfigMaps; apps for Deployments; batch for Jobs), resources (including subresources like pods/log and pods/exec), optional resourceNames to pin specific objects, and verbs. The read verbs are get, list, and watch; the write verbs are create, update, patch, delete, and deletecollection.
The Four Objects
A useful pattern is to define a ClusterRole once (for example, app-developer) and bind it with a RoleBinding per namespace. The permissions stay consistent while the scope stays limited.
Subjects
- Users and groups aren't Kubernetes objects. They come from whatever authenticated the request: client certificates, OIDC tokens from your SSO provider, or cloud IAM integrations such as EKS access entries, GKE with Google groups, or AKS with Entra ID. Bind to groups so access follows team membership.
- ServiceAccounts are namespaced Kubernetes objects that give Pods an identity. Kubernetes mounts a short-lived, audience-bound token into Pods that use them.
Built-in ClusterRoles
Kubernetes ships cluster-admin (everything), admin (full control within a namespace, including RBAC), edit (read/write most objects, no RBAC), and view (read-only, excludes Secrets). They're a reasonable starting point for humans. Workloads almost always need something narrower.
Workload Identity
Pods often need to call cloud APIs as well as the Kubernetes API. Don't mount long-lived cloud keys as Secrets. Map the Pod's ServiceAccount to a cloud identity instead:
- AWS: EKS Pod Identity or IRSA links a ServiceAccount to an IAM role.
- GCP: GKE Workload Identity Federation links it to a Google service account.
- Azure: Entra Workload ID federates it with a managed identity.
The Pod gets short-lived cloud credentials automatically, and access is revoked by editing a role rather than rotating a key. See secrets management.
Best Practices
Least Privilege, Namespaced by Default
Start from zero and add the verbs a subject needs. Prefer RoleBindings over ClusterRoleBindings. Avoid wildcards (resources: ["*"], verbs: ["*"]), which silently grant access to resources added later, CRDs included.
Treat Some Permissions as Admin-Equivalent
Several permissions let a subject escalate to more power than they appear to grant:
createon Pods, or on anything that creates Pods (Deployments, Jobs), in a namespace means running any ServiceAccount in that namespace.get/liston Secrets exposes every credential in scope.pods/execgives a shell in running containers.bind,escalate, andimpersonatelet a subject grant or assume roles.updateon nodes, webhooks, or CRDs can compromise the cluster.
Disable Token Automounting Where Unused
Most application Pods never talk to the Kubernetes API. Set automountServiceAccountToken: false on their ServiceAccount or Pod spec so a compromised container has no API credentials to steal.
Audit Regularly
Enable API server audit logging, and periodically review who holds powerful bindings. kubectl auth can-i --list --as <subject> shows a subject's effective permissions; tools like rbac-lookup, kubectl-who-can, and cloud security posture scanners help at scale.
Manage RBAC as Code
Keep Roles and bindings in Git alongside the rest of your manifests and apply them through GitOps. Out-of-band kubectl create rolebinding commands become invisible permissions nobody remembers granting.
Common Mistakes
Granting cluster-admin to a CI Pipeline
Scope CI to the namespaces it deploys to, with a Role that covers only the resource kinds in your manifests.
Using the default ServiceAccount for Everything
Every namespace has a default ServiceAccount, and Pods use it unless told otherwise. Binding permissions to default grants them to every Pod in the namespace. Create one ServiceAccount per workload that needs API access.
Forgetting That view Isn't the Same as "Safe"
view excludes Secrets, but a custom read-only role with resources: ["*"] includes them. Read access to Secrets is often more dangerous than write access to Deployments.
FAQ
What's the difference between a Role and a ClusterRole?
A Role is namespaced and can only grant access to resources in its own namespace. A ClusterRole is cluster-scoped: it can grant access to cluster-level resources (nodes, namespaces, PersistentVolumes) or be reused across many namespaces through RoleBindings.
Can RBAC deny a permission?
No. RBAC only allows. If you need deny-style guardrails, such as "nobody may create privileged Pods", use admission control: Pod Security Admission, ValidatingAdmissionPolicy, or policy engines such as Kyverno and OPA Gatekeeper.
How do I give developers access to their team's namespace?
Bind the built-in edit ClusterRole, or a custom one, to the team's IdP group with a RoleBinding in each of their namespaces. Access then follows group membership in your identity provider, with no per-user bindings to maintain.
How do I find out who can delete a resource?
Use kubectl auth can-i delete pods -n prod --as jane@example.com for one subject, or a tool such as kubectl-who-can delete pods -n prod to list every subject with that permission.
Related Topics
- Kubernetes — The platform overview
- Container Security — Hardening images and runtime
- Kubernetes Networking — NetworkPolicies as the network-side counterpart
- Secrets Management — Keeping credentials out of manifests
- Zero Trust — The broader access model
- AWS IAM — Cloud identity for Pods on EKS