Blog

Kubernetes RBAC: Role-Based Access Control Explained

Kubernetes RBAC explained: how Roles, bindings, and ServiceAccounts work, how access is evaluated, and least-privilege best practices for your cluster.

Bruno Baldo·Sep 14, 2026·11 min read·Reviewed by Rainforest Technologies

If you run anything on Kubernetes, Kubernetes RBAC is the control that decides who can read your Secrets, delete your pods, or quietly grant themselves the keys to the whole cluster. Role-Based Access Control is the Kubernetes authorization system that maps subjects — users, groups, and ServiceAccounts — to the specific actions they are allowed to perform on specific resources. Get it right and a compromised workload stays boxed into its namespace. Get it wrong and a single leaked token becomes a cluster-wide breach. This deep dive walks through how RBAC actually works, where teams get burned, and how to apply role-based access control in Kubernetes with least privilege as the default. It's part of our broader guide to Kubernetes security.

What RBAC is and why it matters in Kubernetes

Every request that hits the Kubernetes API server — whether it comes from a human running kubectl, a controller, or a pod talking to the API — passes through three gates: authentication (who are you?), authorization (are you allowed to do this?), and admission control (should this specific object be accepted?). RBAC is the most widely used authorization mechanism for the middle gate.

What makes RBAC matter so much is the blast radius behind it. The Kubernetes API is the control plane for everything: workloads, Secrets, network policy, node configuration. A subject with enough API power can read every credential in the cluster, launch privileged pods, or reach the underlying nodes. RBAC is the boundary that keeps a narrow job narrow. When it's too permissive, it becomes the shortest path from a foothold to full compromise — which is exactly why attackers enumerate it early.

RBAC has been the default authorization mode in Kubernetes for years, and it is enabled on essentially every managed and self-hosted distribution you'll encounter. The question is almost never whether you use it, but how carefully.

Core objects: Roles, bindings, ServiceAccounts, and subjects

RBAC is built from four API objects, plus the identities they apply to. The mental model is simple once it clicks: two objects say what is allowed, two objects say who gets it.

Roles and ClusterRoles define a set of permissions. They are purely additive — a Role is just a list of things that are permitted, with no concept of denial.

  • A Role is namespaced. Its permissions apply only within the one namespace it lives in.
  • A ClusterRole is cluster-scoped. It can grant access to cluster-wide resources (nodes, PersistentVolumes), to non-resource endpoints (like /healthz), or to namespaced resources across all namespaces.

Here is a minimal Role that allows reading pods in a single namespace:

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

  namespace: team-payments

  name: pod-reader

rules:

- apiGroups: [""] # "" is the core API group

  resources: ["pods"]

  verbs: ["get", "list", "watch"]

RoleBindings and ClusterRoleBindings attach a Role or ClusterRole to a set of subjects.

  • A RoleBinding grants permissions within a specific namespace. It can reference a Role in that namespace, or — usefully — a ClusterRole, in which case the ClusterRole's rules apply only inside the binding's namespace.
  • A ClusterRoleBinding grants permissions across the entire cluster. This is the object to treat with the most suspicion, because it removes namespace boundaries entirely.

apiVersion: rbac.authorization.k8s.io/v1

kind: RoleBinding

metadata:

  name: read-pods

  namespace: team-payments

subjects:

- kind: ServiceAccount

  name: reporting

  namespace: team-payments

roleRef:

  kind: Role

  name: pod-reader

  apiGroup: rbac.authorization.k8s.io

Subjects are the identities on the receiving end. Kubernetes recognizes three kinds:

  • Users and Groups — human or external identities. Kubernetes has no user database of its own; these come from your authentication layer (certificates, OIDC, and so on), and RBAC simply references them by name.
  • ServiceAccounts — in-cluster identities meant for workloads. Every pod runs as a ServiceAccount, and that account is how the pod authenticates to the API server. ServiceAccounts are the identities you'll scope most often, because they represent your running code.

A common and powerful pattern is to define broad, reusable permission sets as ClusterRoles, then hand them out narrowly with per-namespace RoleBindings. That keeps the definition DRY while keeping the grant tight.

Verbs and resources: the grammar of a rule

Each rule in a Role or ClusterRole answers three questions: which API group, which resources, and which verbs.

Resources are the object types — pods, deployments, secrets, configmaps, and so on. You can narrow further to subresources like pods/log or pods/exec, and even to specific object names with resourceNames.

Verbs are the actions. The common ones are get, list, watch, create, update, patch, and delete (plus deletecollection). It's worth internalizing that these are not all equal:

  • list and watch return object contents, not just names. Granting list on Secrets effectively grants read access to every Secret in scope — a frequent surprise.
  • create on pods, combined with the right namespace, can be enough to run arbitrary code in the cluster.
  • pods/exec and pods/attach let a subject open a shell inside running containers.

Wildcards (*) are accepted for apiGroups, resources, and verbs, and they are the single biggest source of accidental over-permissioning. verbs: ["*"] on resources: ["*"] is cluster-admin in all but name.

How authorization is evaluated: additive and deny-by-default

Two rules govern how Kubernetes turns your bindings into a yes-or-no decision, and both matter for reasoning about security.

First, RBAC is deny-by-default. If no rule explicitly allows a request, it is denied. A brand-new ServiceAccount can do essentially nothing until you bind a role to it.

Second, RBAC is purely additive — there are no deny rules. When a request comes in, the authorizer checks whether any Role or ClusterRole bound to the subject permits it. If one does, the request is allowed; the others are irrelevant. You cannot write a rule that says "allow everything except deleting Secrets." The only way to withhold a permission is to never grant it in the first place.

The practical consequence: you can't patch over an over-broad grant with a narrow denial. If a subject ends up with too much power, you have to find and fix the binding that gave it. This is why sprawling, overlapping bindings are dangerous — the effective permissions of a subject are the union of everything bound to it, and that union is easy to lose track of.

Least privilege in practice

Least privilege is the whole point of RBAC, and in Kubernetes it comes down to a few concrete habits.

Scope to namespaces by default. Prefer Roles and RoleBindings over their cluster-scoped cousins. Most workloads and most teams operate inside one namespace; there's rarely a reason to grant cluster-wide reach. Reserve ClusterRoleBindings for genuinely cluster-wide concerns (a monitoring agent that must read all nodes, for example) and review each one deliberately.

Avoid wildcards. Name the specific resources and verbs you need. ["get", "list", "watch"] on ["configmaps"] tells a reviewer — and a scanner — exactly what a role does. ["*"] tells them nothing and hides future scope creep.

Never hand out `cluster-admin` casually. The built-in cluster-admin ClusterRole is unrestricted access to everything. Binding it to a human "to unblock them," or to a workload "to make the error go away," is the most common way clusters end up wide open. If someone genuinely needs it, grant it narrowly and temporarily rather than through a standing ClusterRoleBinding.

Right-size, don't reuse blindly. The built-in admin, edit, and view ClusterRoles are convenient, but edit and admin are broader than many teams assume — they include access to Secrets in their namespace. Read what you're binding before you bind it.

For the workload side of least privilege — dropping capabilities, running as non-root, and enforcing Pod Security Standards — see our companion guide to Kubernetes pod security.

ServiceAccount hygiene

ServiceAccounts are where RBAC meets your running workloads, and a few defaults deserve attention.

Don't rely on the `default` ServiceAccount. Every namespace ships with one named default, and any pod that doesn't specify a ServiceAccount runs as it. Because it's shared, any permission you grant default leaks to every unlabeled workload in that namespace. Leave it with no bindings and give each workload its own account.

Give each workload its own ServiceAccount. Per-workload accounts let you scope permissions to exactly what that one service needs, and they make audit trails meaningful — you can tell which workload made which API call.

apiVersion: v1

kind: ServiceAccount

metadata:

  name: reporting

  namespace: team-payments

automountServiceAccountToken: false

Turn off token automounting where it isn't needed. By default, Kubernetes mounts a ServiceAccount token into every pod at a well-known path. If the workload never talks to the API server, that token is pure attack surface — anyone who compromises the container gets a valid cluster credential for free. Set automountServiceAccountToken: false on the ServiceAccount or the pod spec unless the workload genuinely needs API access. Managing the tokens and other credentials those workloads do need is a topic in itself — see Kubernetes secrets management.

Common misconfigurations and escalation paths

Attackers don't need a wide-open cluster; they need one over-permissioned subject they can reach. These are the patterns worth hunting for.

Bindings to `cluster-admin` or other broad ClusterRoles. Any ClusterRoleBinding to cluster-admin is a single point of total compromise. Enumerate them and justify every one.

The `escalate` and `bind` verbs. Normally Kubernetes stops you from creating a role with more permissions than you already hold — otherwise RBAC would be trivial to bypass. The escalate verb removes that guardrail for Roles/ClusterRoles, and bind removes it for bindings. A subject that can bind and reference cluster-admin can promote itself to admin, even if it started with almost nothing. Treat any grant of these verbs as equivalent to granting what they unlock.

The `impersonate` verb. This lets a subject act as another user, group, or ServiceAccount. A subject that can impersonate system:masters or a cluster-admin is a cluster-admin. Impersonation has legitimate uses, but it should be rare and tightly scoped.

Broad Secret access. get, list, or watch on Secrets is read access to credentials, tokens, and TLS keys. Combined with a mounted ServiceAccount token, it's often the pivot from one workload to many. Scope Secret access to named Secrets with resourceNames wherever you can.

`create` on pods plus a privileged ServiceAccount. If a subject can create pods in a namespace and set the pod's ServiceAccount, it can launch a pod that runs as a more privileged account — turning a modest permission into that account's full power.

Auditing and reviewing RBAC

RBAC drift is inevitable: roles get added under deadline pressure and rarely get removed. Regular review is the counterweight.

Ask the API what a subject can do. kubectl auth can-i answers authorization questions directly, including on behalf of another identity:

kubectl auth can-i list secrets \

  --as=system:serviceaccount:team-payments:reporting \

  -n team-payments

Enable and read audit logs. The API server's audit log records who did what, and is the ground truth for spotting a ServiceAccount using permissions it shouldn't need — a strong signal that a binding is too broad (or that something is wrong).

Use RBAC analysis tooling. Beyond kubectl auth can-i and kubectl describe, the community has open-source tools that flatten and visualize effective permissions, flag risky verbs, and diff bindings over time. Because RBAC's additive model makes effective permissions hard to eyeball, tooling that computes the union for you is worth adopting.

Review on a cadence, and treat every ClusterRoleBinding and every use of escalate, bind, impersonate, or wildcards as a line item that has to earn its place.

RBAC in CI/CD and infrastructure-as-code

Here's the leverage point most teams miss: your RBAC configuration is YAML, and YAML can be checked before it reaches the cluster.

Rather than discovering an over-permissioned ClusterRoleBinding during an incident, you can scan the manifests in your Git repository as part of code review and CI — the same way you'd lint any other infrastructure-as-code. A pipeline check can fail a merge request that introduces a wildcard verb, a cluster-admin binding, or a Role that grants escalate, giving reviewers a chance to push back while the change is still cheap to fix.

This shift-left approach fits naturally with GitOps: if the cluster's RBAC state is defined declaratively in Git, then scanning Git is scanning the cluster's intended state. Catching a dangerous binding at the pull request stage is far less painful than catching it after it's live — and it builds a culture where broad permissions have to be justified in review.

How Rainforest helps

Rainforest's application security platform includes infrastructure-as-code scanning that analyzes Kubernetes manifests and IaC definitions before they're applied, surfacing risky RBAC patterns — wildcard permissions, bindings to overly broad ClusterRoles, dangerous verbs, and exposed ServiceAccount tokens — as part of your existing pipeline. Because it runs where your developers already work, findings land in code review with the context to fix them, not weeks later in a separate report. It's one piece of a broader application security testing approach that spans your code, dependencies, and configuration.

If you'd like to see how that looks against your own manifests, book a demo and we'll walk through it with your setup.

Frequently asked questions

What is Kubernetes RBAC?

Kubernetes RBAC (Role-Based Access Control) is the built-in authorization system that governs what actions an identity — a user, group, or ServiceAccount — is allowed to perform against the Kubernetes API. It works by binding roles, which are lists of permitted actions on specific resources, to subjects. RBAC is deny-by-default, so an identity can do nothing until a role is explicitly bound to it, and it's the primary control that limits the blast radius of a compromised account or workload.

What is the difference between a Role and a ClusterRole?

A Role is namespaced: its permissions apply only within the single namespace it's defined in. A ClusterRole is cluster-scoped and can grant access to cluster-wide resources (like nodes), to non-resource API endpoints, or to namespaced resources across every namespace at once. A useful pattern is to define reusable permission sets as ClusterRoles but grant them narrowly using namespaced RoleBindings, so the same definition can be applied to one namespace at a time.

How do I follow least privilege with RBAC?

Prefer namespaced Roles and RoleBindings over cluster-scoped ones, name specific resources and verbs instead of using wildcards, and never bind humans or workloads to cluster-admin as a shortcut. Give each workload its own ServiceAccount rather than sharing the namespace default, disable ServiceAccount token automounting where API access isn't needed, and scope access to sensitive resources like Secrets down to named objects. Review the built-in edit and admin roles before using them, since both include Secret access.

What are common RBAC misconfigurations?

The most dangerous are standing bindings to cluster-admin, wildcard verbs and resources, and grants of the escalate, bind, or impersonate verbs, each of which can let a subject promote itself to full control. Broad get/list/watch access to Secrets exposes credentials, and create on pods combined with the ability to set a pod's ServiceAccount can be used to run workloads as a more privileged identity. Leaving permissions on the shared default ServiceAccount is another frequent mistake.

How do I audit Kubernetes RBAC?

Start with kubectl auth can-i, which answers whether a given identity can perform a specific action and can query on behalf of another subject with --as. Enable the API server audit log to see which identities are actually exercising which permissions, and adopt open-source RBAC analysis tools that compute and visualize effective permissions — valuable because RBAC's additive model makes a subject's true reach hard to read by hand. You can also scan RBAC manifests as infrastructure-as-code in CI to catch risky bindings before they're applied.

Bruno Baldo

Written by

Bruno Baldo

CMO

Um pouco de marketing e um pouco de curiosidade e temos a receita pra criar um apaixonado por cyber!

Keep reading