KCSA — Role-Based Access Control (RBAC)

7 minute read

RBAC — “What Are You Allowed to Do?”

Role-Based Access Control (RBAC) is the standard authorization mechanism in Kubernetes. After the API server authenticates a request (determines who you are), RBAC determines what you can do.

RBAC is enabled by default in every modern Kubernetes distribution. It uses four API resources to define permissions and bind them to users, groups, or service accounts.

KCSA Relevance: RBAC is one of the most heavily tested topics in the KCSA exam. Expect multiple questions on RBAC resources, their scope, binding mechanics, and best practices.


The Four RBAC Resources

Resource Scope Purpose
Role Namespace Defines permissions within a single namespace
ClusterRole Cluster-wide Defines permissions across all namespaces or for cluster-scoped resources
RoleBinding Namespace Binds a Role or ClusterRole to subjects in a namespace
ClusterRoleBinding Cluster-wide Binds a ClusterRole to subjects across the entire cluster

Think of it this way:

  • Roles define what actions are permitted.
  • Bindings define who gets those permissions.

Role vs ClusterRole

Role (Namespace-Scoped)

A Role defines permissions within a specific namespace.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: development
  name: pod-reader
rules:
  - apiGroups: [""]          # core API group
    resources: ["pods"]
    verbs: ["get", "list", "watch"]

This Role grants read-only access to pods — but only in the development namespace.

ClusterRole (Cluster-Scoped)

A ClusterRole defines permissions that apply across all namespaces or to cluster-scoped resources (like nodes, namespaces, PersistentVolumes).

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-reader
rules:
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["get", "list", "watch"]

Role vs ClusterRole Comparison

Aspect Role ClusterRole
Scope Single namespace Cluster-wide
Can define rules for namespace-scoped resources Yes (within its namespace) Yes (across all namespaces)
Can define rules for cluster-scoped resources No Yes
Can define rules for non-resource URLs No Yes (e.g., /healthz)
Created in a namespace Yes No (cluster-level object)

Exam Tip: A ClusterRole can be bound to a namespace via a RoleBinding. This is a common pattern to reuse a ClusterRole definition across multiple namespaces.


RoleBinding vs ClusterRoleBinding

RoleBinding (Namespace-Scoped)

A RoleBinding grants permissions defined in a Role or ClusterRole to subjects within a specific namespace.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: development
subjects:
  - kind: User
    name: jane
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

This binds the pod-reader Role to user jane in the development namespace.

ClusterRoleBinding (Cluster-Scoped)

A ClusterRoleBinding grants permissions defined in a ClusterRole to subjects across the entire cluster.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: read-nodes-global
subjects:
  - kind: Group
    name: monitoring-team
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: node-reader
  apiGroup: rbac.authorization.k8s.io

RoleBinding vs ClusterRoleBinding Comparison

Aspect RoleBinding ClusterRoleBinding
Scope Single namespace Entire cluster
Can reference a Role Yes No
Can reference a ClusterRole Yes (scoped to namespace) Yes (cluster-wide)
Use case Namespace-level permissions Cluster-wide permissions

The ClusterRole + RoleBinding Pattern

This is a powerful and common pattern:

# A ClusterRole that defines read access to pods
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-reader
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
---
# A RoleBinding that grants this ClusterRole only in the "staging" namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-staging
  namespace: staging
subjects:
  - kind: User
    name: bob
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Bob can read pods in staging only — even though the ClusterRole itself is cluster-scoped. The RoleBinding limits the scope.


RBAC Subjects

Bindings can target three types of subjects:

Subject Kind Description Example
User Human user (external identity) jane
Group Group of users developers, system:masters
ServiceAccount In-cluster service account system:serviceaccount:default:my-app
subjects:
  # A user
  - kind: User
    name: jane
    apiGroup: rbac.authorization.k8s.io
  # A group
  - kind: Group
    name: developers
    apiGroup: rbac.authorization.k8s.io
  # A service account
  - kind: ServiceAccount
    name: my-app
    namespace: default

Common RBAC Verbs

RBAC verbs correspond to API operations:

Verb HTTP Method Description
get GET (single resource) Read a specific resource
list GET (collection) List resources
watch GET (with watch) Stream resource changes
create POST Create a new resource
update PUT Replace an existing resource
patch PATCH Partially modify a resource
delete DELETE Delete a resource
deletecollection DELETE (collection) Delete multiple resources

Read-Only Access

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

Full CRUD Access

verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

The Wildcard Verb

verbs: ["*"]    # All verbs — use with extreme caution

Never use "*" in production Roles unless absolutely necessary. It grants every possible action, including future verbs that may be added.


Default ClusterRoles

Kubernetes ships with several built-in ClusterRoles:

ClusterRole Permissions Intended Use
cluster-admin Full access to everything Emergency admin, cluster setup
admin Full access within a namespace (no resource quotas) Namespace administrator
edit Read/write most resources (no Roles, no RoleBindings) Developer access
view Read-only access (no secrets) Read-only monitoring, auditing

Aggregated ClusterRoles

The admin, edit, and view ClusterRoles use label-based aggregation. Custom ClusterRoles can opt into aggregation by adding labels:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: custom-crd-viewer
  labels:
    rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
  - apiGroups: ["mycompany.io"]
    resources: ["widgets"]
    verbs: ["get", "list", "watch"]

This automatically adds the rules to the built-in view ClusterRole. The same pattern works with aggregate-to-edit and aggregate-to-admin.


Least Privilege Principle with RBAC

The principle of least privilege means granting only the minimum permissions necessary for a subject to perform its function.

How to Apply Least Privilege

Practice Example
Use namespace-scoped Roles instead of ClusterRoles Role in dev namespace, not ClusterRole
Specify exact resources resources: ["pods"] not resources: ["*"]
Specify exact verbs verbs: ["get", "list"] not verbs: ["*"]
Specify resource names when possible resourceNames: ["my-configmap"]
Avoid cluster-admin bindings Use scoped roles instead
Separate read and write roles One role for viewers, another for editors

Resource-Name Scoping

You can restrict a Role to specific named resources:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: configmap-updater
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["app-config", "feature-flags"]
    verbs: ["get", "update", "patch"]

This Role can only read and update two specific ConfigMaps — nothing else.


Common RBAC Mistakes

Mistake Risk Fix
Using * for resources or verbs Excessive permissions Specify exact resources and verbs
Binding cluster-admin to service accounts Full cluster control from a pod Create scoped Roles
Binding to the default service account Every pod in the namespace inherits permissions Create dedicated service accounts
ClusterRoleBinding when RoleBinding suffices Namespace permissions become cluster-wide Use RoleBinding to limit scope
Not reviewing RBAC regularly Permission drift over time Audit with kubectl auth can-i
Copying broad roles from online tutorials Unnecessary privileges Start minimal and add as needed

Auditing RBAC Permissions

Check What a User Can Do

# Can user "jane" get pods in the "development" namespace?
kubectl auth can-i get pods --namespace development --as jane

# Can the "deploy-bot" service account create deployments?
kubectl auth can-i create deployments \
  --namespace production \
  --as system:serviceaccount:production:deploy-bot

# List all actions a user can perform
kubectl auth can-i --list --as jane --namespace development

Check Your Own Permissions

# What can I do in the current namespace?
kubectl auth can-i --list

# Can I delete nodes?
kubectl auth can-i delete nodes

Inspect RBAC Resources

# List all Roles in a namespace
kubectl get roles -n development

# List all ClusterRoleBindings
kubectl get clusterrolebindings

# Describe a specific ClusterRole
kubectl describe clusterrole admin

# Find who has cluster-admin
kubectl get clusterrolebindings -o json | \
  jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects'

Putting It All Together — A Real-World Example

Scenario: A development team needs read/write access to Deployments and Services in the staging namespace, but only read access to Pods and ConfigMaps.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: staging
  name: dev-team-role
rules:
  # Read/write Deployments and Services
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  # Read-only Pods and ConfigMaps
  - apiGroups: [""]
    resources: ["pods", "configmaps"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: staging
  name: dev-team-binding
subjects:
  - kind: Group
    name: dev-team
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: dev-team-role
  apiGroup: rbac.authorization.k8s.io

This follows least privilege: the team gets exactly the permissions they need, scoped to one namespace.


Key Takeaways for the Exam

Concept What to Remember
Four RBAC Resources Role, ClusterRole, RoleBinding, ClusterRoleBinding
Role vs ClusterRole Namespace-scoped vs cluster-scoped
RoleBinding + ClusterRole Limits ClusterRole permissions to a single namespace
Verbs get, list, watch, create, update, patch, delete
Default ClusterRoles cluster-admin, admin, edit, view
Aggregated ClusterRoles Labels like aggregate-to-view extend built-in roles
Least Privilege Specific resources, specific verbs, namespace-scoped
kubectl auth can-i The primary tool for auditing RBAC permissions
Wildcard * Dangerous — avoid in production

What’s Next?

Now that you understand RBAC, the next topic explores Service Accounts — the identity mechanism for pods — and the security implications of token management.

Service Accounts & Token Security

Updated: