RBAC

Kubernetes RBAC: Roles, Bindings, Examples and Best Practices

Kubernetes RBAC controls which authenticated users, groups and workloads may perform specific actions through the Kubernetes API. You define permissions in Role or ClusterRole objects, then grant them to subjects with RoleBinding or ClusterRoleBinding objects.

The critical detail is scope. A ClusterRole is a cluster-scoped definition, but its permissions are not automatically cluster-wide: a RoleBinding can reuse that ClusterRole inside one namespace. A ClusterRoleBinding is what grants a ClusterRole across the cluster.

Kubernetes RBAC at a glance

Kubernetes evaluates authorization after authentication. If no configured authorizer permits the request, the API server rejects it. Within the RBAC authorizer, permissions are additive: roles grant permissions, and there are no RBAC deny rules that subtract them.

Every RBAC rule connects four questions:

  • Who? A user, group or ServiceAccount.
  • Can do what? An API verb such as get, list, watch, create, update, patch or delete.
  • To what? A resource or subresource such as pods, deployments.apps or pods/log.
  • Where? One namespace or the whole cluster, determined by the role and binding combination.

Kubernetes defines four RBAC object kinds:

Object What it does Scope effect
Role Defines rules for namespaced resources Rules belong to one namespace
ClusterRole Defines reusable rules for namespaced resources, cluster-scoped resources or non-resource URLs Reach depends on how it is bound
RoleBinding Grants a Role, or reuses a ClusterRole, for subjects Grant applies only in the binding’s namespace
ClusterRoleBinding Grants a ClusterRole to subjects Grant applies across the cluster

This distinction comes directly from the Kubernetes RBAC API model. It prevents a common mistake: selecting ClusterRole because a permission definition should be reusable, then assuming the resulting access must be cluster-wide.

Role vs ClusterRole: where permissions are defined

A Role is namespaced. It can define permissions for namespaced resources in that namespace. Use one when the rule itself is specific to a single namespace.

A ClusterRole is not namespaced. It can define permissions for:

  • namespaced resources such as Pods, whether later granted in one namespace or all namespaces;
  • cluster-scoped resources such as Nodes;
  • non-resource API paths such as /healthz.

Choose a ClusterRole when the permission definition must be reused across namespaces or when the target itself is cluster-scoped. Do not infer the final reach of the grant from kind: ClusterRole alone; inspect the binding.

RoleBinding vs ClusterRoleBinding: where permissions are granted

A RoleBinding exists in one namespace. It can reference a Role in that same namespace or a ClusterRole. In both cases, the resulting grant applies only within the RoleBinding’s namespace.

A ClusterRoleBinding can reference only a ClusterRole. It grants those permissions cluster-wide.

Required outcome Define with Grant with
One namespace, one-off rule Role RoleBinding in that namespace
One reusable rule, granted separately per namespace ClusterRole A RoleBinding in each allowed namespace
Access to a cluster-scoped resource such as Nodes ClusterRole ClusterRoleBinding
Access to namespaced resources in every namespace ClusterRole ClusterRoleBinding

The reusable ClusterRole + namespace RoleBinding pattern is often the safest operational choice for a standard team or workload role: maintain the permission set once, but opt namespaces into it explicitly.

How to configure Kubernetes RBAC: a namespace-scoped example

Assume a reporting workload runs in the analytics namespace. It needs to list and watch Pods and read Pod logs there, but it must not access Secrets or Pods in production.

The following manifest creates a dedicated ServiceAccount, a reusable ClusterRole and a RoleBinding that limits the grant to analytics:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: report-reader
  namespace: analytics
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: report-reader
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: report-reader
  namespace: analytics
subjects:
  - kind: ServiceAccount
    name: report-reader
    namespace: analytics
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: report-reader

Apply the manifest only after the analytics namespace exists:

kubectl apply -f report-reader-rbac.yaml

The empty string in apiGroups: [""] means the core API group. A Deployment, by contrast, belongs to the apps API group and would be written as resources: ["deployments"] with apiGroups: ["apps"]. Subresources are separate permissions: get on pods does not automatically grant get on pods/log.

Test the allowed and denied cases

Do not stop after kubectl apply succeeds. Test the exact identity, verb, resource and namespace. These checks use ServiceAccount impersonation, so the operator running them must itself be allowed to impersonate that subject.

# Expected: yes
kubectl auth can-i list pods \
  --as=system:serviceaccount:analytics:report-reader \
  --namespace=analytics

# Expected: yes
kubectl auth can-i get pods \
  --subresource=log \
  --as=system:serviceaccount:analytics:report-reader \
  --namespace=analytics

# Expected: no
kubectl auth can-i list pods \
  --as=system:serviceaccount:analytics:report-reader \
  --namespace=production

# Expected: no
kubectl auth can-i get secrets \
  --as=system:serviceaccount:analytics:report-reader \
  --namespace=analytics

The two negative checks are part of the acceptance test. A positive test proves the workload can function; a negative test proves the boundary was not accidentally widened.

To list everything Kubernetes currently allows for that ServiceAccount inside analytics:

kubectl auth can-i --list \
  --as=system:serviceaccount:analytics:report-reader \
  --namespace=analytics

kubectl auth can-i is a point-in-time authorization query. It does not replace reviewing every binding that can affect the subject or collecting audit records of actual requests.

Users, groups and ServiceAccounts are different subjects

Kubernetes does not store normal human users as API objects. An external authentication method establishes a username and group membership; RBAC binds those strings to permissions. Provisioning or disabling the human identity therefore belongs to that external identity system, not to a Kubernetes User object.

A ServiceAccount is a Kubernetes API object intended to provide an identity to a workload. Give each workload a dedicated ServiceAccount when it needs Kubernetes API access, then bind only the required permissions.

Modern Kubernetes workloads normally receive short-lived, automatically rotating ServiceAccount tokens through the TokenRequest API and projected volumes. Avoid static, long-lived ServiceAccount token Secrets. If a Pod does not need to call the Kubernetes API, disable automatic token mounting in the Pod specification:

spec:
  automountServiceAccountToken: false

The Kubernetes ServiceAccount documentation describes the current token and cross-namespace patterns.

Kubernetes RBAC best practices

1. Prefer namespace-scoped grants

Use a RoleBinding instead of a ClusterRoleBinding when the subject only needs access in selected namespaces. A reusable ClusterRole does not require a cluster-wide grant.

2. Avoid wildcard resources and verbs

Rules such as resources: ["*"] or verbs: ["*"] cover more than today’s objects and operations. Kubernetes is extensible; a wildcard can also grant access to future resource types.

3. Treat Secrets and workload creation as high risk

get, list and watch on Secrets can reveal Secret contents. Permission to create Pods or workload controllers can also permit mounting Secrets, ConfigMaps, volumes or a more privileged ServiceAccount in that namespace. Review effective capability, not just the visible verb name.

4. Protect RBAC administration and escalation paths

Creating or updating roles and bindings is sensitive. Pay particular attention to the bind, escalate and impersonate verbs, as well as permissions to modify roles, clusterroles, rolebindings and clusterrolebindings. Kubernetes normally prevents a user from creating a role or binding that contains permissions the user does not already hold, unless those special privileges were granted.

5. Use dedicated ServiceAccounts

Do not grant application permissions to the namespace’s default ServiceAccount. Any Pod without an explicit serviceAccountName would inherit them. Use one ServiceAccount per workload or trust boundary, and disable token mounting when it is unnecessary.

6. Manage RBAC as reviewed configuration

Keep manifests in version control, require review for privileged changes and compare intended policy with the live cluster. If a binding must point to a different role, create a replacement: Kubernetes makes roleRef immutable. kubectl auth reconcile can help reconcile RBAC manifests, including binding replacement.

7. Test negative cases in CI

For each privileged identity, specify what must be allowed and what must remain denied. Repeat the tests when a role, binding, chart, operator or CRD changes. A new CRD or aggregated role can alter effective permissions without changing the workload’s original manifest.

The official Kubernetes RBAC good-practices guide documents the privilege-escalation risks behind these controls.

Aggregated ClusterRoles and custom resources

ClusterRole aggregation lets a controller combine rules from labeled ClusterRoles into another ClusterRole. Kubernetes uses this mechanism for default user-facing roles such as admin, edit and view, and platform teams can use it to extend a role for CRDs.

Treat the aggregated role’s rules as controller-managed. Do not hand-edit or force-apply that field; the aggregation controller overwrites it. Review the selector and every contributing ClusterRole, because a new matching label can add effective permissions.

How to troubleshoot Kubernetes RBAC

Start with the failed request, not with the assumption that the role is wrong. Record the subject, verb, API group, resource or subresource, resource name and namespace.

Symptom What to inspect
403 Forbidden for one namespace The RoleBinding namespace and exact subject name/group
Can read Pods but not logs A separate pods/log rule and the get verb
Can manage core Pods but not Deployments apiGroups: ["apps"] and resources: ["deployments"]
Access works in every namespace unexpectedly ClusterRoleBindings and broad group subjects such as system:authenticated or system:serviceaccounts
Removing one binding does not remove access Other bindings or another configured authorizer; RBAC grants are additive
Binding update fails validation roleRef is immutable; replace the binding or use kubectl auth reconcile
kubectl auth can-i --as is forbidden The operator lacks permission to impersonate that user, group or ServiceAccount

Inspect the live objects behind the decision:

kubectl get rolebindings --all-namespaces -o wide
kubectl get clusterrolebindings -o wide
kubectl get rolebinding report-reader -n analytics -o yaml
kubectl get clusterrole report-reader -o yaml

If a resource rule still does not match, confirm its API group and whether the request targets a subresource:

kubectl api-resources

Audit what actually happened

Authorization checks tell you whether a request should be allowed now. Kubernetes audit events provide a chronological record of requests handled by the API server, including the requesting identity, verb, resource and response stage at the configured audit level.

Audit logging is configured separately from RBAC. An audit policy determines which events and bodies are recorded; the API server can write them to a log or webhook backend. Managed Kubernetes services expose control-plane auditing through provider-specific settings, so confirm the provider’s retention and export behavior rather than assuming a self-managed configuration. See the official Kubernetes auditing guide.

Use audit evidence to investigate denied requests, privileged changes and permissions that are granted but apparently unused. Do not log sensitive request or response bodies indiscriminately; choose audit levels and retention according to the data and investigation need.

Kubernetes RBAC vs application RBAC

Kubernetes RBAC protects the Kubernetes API: who may read Secrets, modify Deployments, view logs or change cluster configuration. It does not decide whether an end user may view Tenant A’s invoice, edit a project or administer another user inside your SaaS application.

If a B2B SaaS product runs on Kubernetes, it normally needs both layers:

Layer Protected resource Example decision
Kubernetes RBAC Cluster and workload resources May this ServiceAccount list Pods in analytics?
Application authorization Customer and product resources May this tenant member export this account’s audit log?

Keep the policy models and enforcement points separate. A Kubernetes namespace is not automatically a customer-tenant authorization boundary, and an application role should not grant cluster privileges. The RBAC guide covers the general model; the authorization architecture guide explains tenant context, policy decisions and application enforcement.

Frontegg’s roles documentation covers application roles and permissions for customer-facing products. Those capabilities complement Kubernetes RBAC; they do not configure or replace the Kubernetes API authorizer.

Kubernetes RBAC implementation checklist

  • The subject is an exact user, group or dedicated ServiceAccount.
  • The API group, resource, subresource and verbs match the real request.
  • The binding grants access only in the required namespace or cluster scope.
  • Wildcards, Secrets, workload creation and RBAC-administration privileges are justified explicitly.
  • Pods without an API requirement do not receive a ServiceAccount token.
  • Both allowed and denied cases pass kubectl auth can-i tests.
  • RBAC manifests are reviewed and reconciled from version control.
  • Aggregated ClusterRole inputs are inventoried when CRDs or operators change.
  • API-server audit events are enabled and retained at an appropriate level.
  • Kubernetes infrastructure access remains separate from application and tenant authorization.
Looking to take your User Management to the next level?
Sign up. It's free