What is Kubernetes RBAC and how do Roles and bindings work?

Kubernetes RBAC (role-based access control) is the authorization system that decides which API requests a user, group or service account may make. A Role or ClusterRole lists allowed verbs on resources, and a RoleBinding or ClusterRoleBinding grants that role to subjects, either in one namespace or across the cluster. Permissions are purely additive: RBAC has no deny rules, so anything not granted is refused.

The four objects

ObjectScopeWhat it does
RoleOne namespaceLists permissions on resources in that namespace
ClusterRoleClusterLists permissions on cluster-scoped resources (such as nodes), non-resource URLs (such as /healthz) or namespaced resources in any namespace
RoleBindingOne namespaceGrants a Role or a ClusterRole to subjects, within the binding’s namespace
ClusterRoleBindingClusterGrants a ClusterRole to subjects in every namespace and for cluster-scoped resources

The combination that confuses people is a RoleBinding that references a ClusterRole. The RBAC reference is clear that the permissions then apply only inside the RoleBinding’s namespace. This is the normal way to reuse one role definition across namespaces: define app-deployer once as a ClusterRole, then bind it per namespace.

A binding’s roleRef cannot change after creation. To point a binding at a different role, delete it and create a new one.

Rules: API groups, resources and verbs

A rule names API groups, resources and verbs:

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: shop
  name: deployer
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]

The core API group is the empty string "". Subresources are written as resource/subresource, and they are granted separately from the parent: pods/log reads logs, pods/exec opens a shell, pods/portforward tunnels traffic. A role that allows get on pods does not allow exec.

resourceNames narrows a rule to named objects, such as one ConfigMap. It cannot restrict create or deletecollection, because those requests do not name an existing object.

Subjects: users, groups and service accounts

Kubernetes has no user objects. A user or group is whatever name the authenticator reports: the common name and organization of a client certificate, or the username and groups claims of an OIDC token from your identity provider. Bind roles to groups, such as platform-admins from your identity provider, rather than to individual users, so that joining or leaving a team is an identity provider change rather than a cluster change. Service accounts are the in-cluster identity for workloads, written as system:serviceaccount:<namespace>:<name>.

The built-in ClusterRoles are a sensible starting point:

  • cluster-admin: every action on every resource.
  • admin: full access within a namespace, including Roles and RoleBindings, when bound with a RoleBinding.
  • edit: read and write most namespaced objects, without access to Roles and RoleBindings.
  • view: read most namespaced objects. It excludes Secrets on purpose, because reading Secrets would expose service account credentials.

The group system:masters is bound to cluster-admin and bypasses RBAC authorization entirely, so nobody’s everyday credential should carry it.

Privilege escalation paths

Many permissions look narrow and are not. The RBAC good-practices guide lists these:

PermissionWhy it is dangerous
list or watch on secretsReturns the contents of every Secret, not only their names
create on Pods or workload resourcesThe Pod can mount any Secret and run as any service account in the namespace; without Pod Security it can be privileged and reach the node
create on PersistentVolumesA hostPath volume gives access to the node’s filesystem
get on nodes/proxyGrants the kubelet API, which allows running commands in every Pod on the node
escalate on rolesLets a user write roles with permissions they do not hold
bind on rolesLets a user bind roles with permissions they do not hold
impersonateLets a user act as another user, group or service account
create on serviceaccounts/tokenLets a user request tokens for existing service accounts
CSR create plus approvalLets a user issue client certificates that authenticate to the cluster

Without escalate or bind, RBAC stops a user from creating a role or binding that grants more than they already hold. Treat those two verbs, impersonate and wildcard rules ("*") as admin-only.

How to audit RBAC

kubectl auth can-i answers “can this subject do this?”:

bash
kubectl auth can-i list secrets -n shop --as=[email protected]
kubectl auth can-i create pods/exec -n shop --as=system:serviceaccount:shop:ci
kubectl auth can-i --list -n shop --as-group=developers --as=test-user

The --list form prints everything a subject may do in a namespace. Run it for each tenant group and each workload service account, and look for the entries in the table above. Pair this with API audit logs, which record who actually used a permission.

Good defaults

  • Give workloads their own service account instead of default, and set automountServiceAccountToken: false where the workload never calls the API.
  • Grant humans view or edit per namespace through group bindings. Keep cluster-admin for a small number of break-glass identities.
  • Prefer namespaced RoleBindings to ClusterRoleBindings.
  • Review RBAC whenever you install a Helm chart or operator, because many ship broad ClusterRoles.

RBAC decides what an authenticated caller may do. Who can authenticate, and from where, is covered in how to secure the Kubernetes API. RBAC is also the first layer of Kubernetes multi-tenancy, and the main control over who can read Kubernetes Secrets.

RBAC on Cloudfleet

Cloudfleet Kubernetes Engine (CFKE) uses standard Kubernetes RBAC, and with single sign-on you can bind roles to the groups from your identity provider. User management explains how Cloudfleet roles map to Kubernetes roles.

On this page