# Demonstration: Watching RBAC Actually Deny Something ## The setup A ServiceAccount `readonly-bot` has a Role granting only `get`/`list` on `pods` — nothing else. ## What it CAN do ``` $ kubectl auth can-i list pods --as=system:serviceaccount:default:readonly-bot yes $ kubectl get pods --as=system:serviceaccount:default:readonly-bot NAME READY STATUS RESTARTS AGE web-abc123 1/1 Running 0 2h ``` ## What it CANNOT do ``` $ kubectl auth can-i delete pods --as=system:serviceaccount:default:readonly-bot no $ kubectl delete pod web-abc123 --as=system:serviceaccount:default:readonly-bot Error from server (Forbidden): pods "web-abc123" is forbidden: User "system:serviceaccount:default:readonly-bot" cannot delete resource "pods" in API group "" in the namespace "default" ``` This is what least privilege actually looks like in practice — not a policy document, a real, enforced denial with a specific, readable error naming exactly which permission was missing. `kubectl auth can-i` is your fastest way to CHECK a permission before attempting an action that might fail — useful both for debugging "why can't my workload do X" and for verifying a Role is actually as narrow as intended. ## What happens when the ServiceAccount tries something it was never even considered for ``` $ kubectl auth can-i get secrets --as=system:serviceaccount:default:readonly-bot no ``` Notice this returns `no` the same way `delete pods` did — RBAC has no concept of "not yet decided," only "explicitly allowed" or "everything else, denied." This is the practical meaning of default-deny applied to permissions: nothing is grey area. ## Instructor Notes **Demo script:** Run all three `kubectl auth can-i`/action pairs live — the FORBIDDEN error message's exact wording (naming the verb, resource, and namespace) is worth reading aloud, since that's exactly the evidence a student would use to debug a real permissions issue later. **Approximate timing:** 8 minutes live; 5 minutes self-paced. **Common misconception to preempt:** students sometimes think `kubectl auth can-i` REQUIRES the action to actually be attempted to know the answer. It doesn't — it's a dry-run permission check against the same RBAC rules, safe to run repeatedly without side effects. **Optional extension:** ask what the error message would look like if `readonly-bot` tried to act on a DIFFERENT namespace than the one its Role/RoleBinding applies to — a good check that students understand Role scope is namespace-specific unless a ClusterRole+ClusterRoleBinding is used instead.