KCSA — Role-Based Access Control (RBAC)
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.