RBAC: give exactly the verbs asked for
The four objects, and when each is right
| object | scope | use when |
|---|---|---|
| Role | namespace | permissions inside one namespace |
| ClusterRole | cluster | cluster-scoped resources, or a reusable permission set |
| RoleBinding | namespace | grants a Role or a ClusterRole inside one namespace |
| ClusterRoleBinding | cluster | grants cluster-wide — the dangerous one |
A ClusterRole bound with a RoleBinding is the trick question: the rules are
cluster-shaped, the effect is namespaced.
Task: a user who can only read Pods and logs in one namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: {name: pod-reader, namespace: prod}
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata: {name: pod-reader-binding, namespace: prod}
subjects:
- kind: User
name: jane # exact string from the CSR / certificate CN
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
roleRef is immutable — to change what a binding grants you delete and
recreate it. kubectl auth reconcile does that for you:
kubectl auth reconcile -f /tmp/rbac.yaml --remove-extra-permissions
Prove it — always
kubectl auth can-i list pods -n prod --as jane
kubectl auth can-i delete pods -n prod --as jane # must be "no"
kubectl auth can-i --list -n prod --as jane # the whole effective set
kubectl auth can-i list pods --as=system:serviceaccount:prod:api
--as requires your own account to be allowed to impersonate; as cluster-admin
it is fine, and it is the only honest way to check.
Cleaning up an over-permissive role
The task usually gives you a role with * verbs or secrets access and asks you
to reduce it to what a workload needs:
kubectl get clusterrole over-permissive -o yaml > /tmp/cr.yaml
# keep only the apiGroups/resources/verbs the task lists, delete the rest
kubectl apply -f /tmp/cr.yaml
kubectl auth can-i --list --as=system:serviceaccount:prod:api
Watch for resources: ["*"], verbs: ["*"], apiGroups: ["*"], and forsecrets in a role that only ever reads configmaps. Deleting a rule is safe;
deleting the whole role breaks the workload and the marker checks the workload.
Default roles you should recognise
cluster-admin—*on everything. Bind it to a named user for a task, never to a workload.admin— full control inside a namespace, not of the namespace object.edit— read/write most objects, no RBAC, no Secrets read in some versions.view— read-only on most, never Secrets.system:aggregate-to-*— the aggregation labels that buildadmin/edit/view.
Aggregated ClusterRoles
kind: ClusterRole
metadata:
name: monitoring-read
labels: {rbac.example.com/aggregate-to-view: "true"}
rules:
- apiGroups: [""]
resources: ["pods", "nodes"]
verbs: ["get", "list", "watch"]
If the label matches the view aggregator, the rules land inside view
automatically. The exam rarely asks for this, but it explains why some rules seem
to come from nowhere when you read kubectl get clusterrole view -o yaml.