RBAC: Role and RoleBinding
Video: Day 23/40 — Kubernetes RBAC Explained (Role Based Access Control) • https://www.youtube.com/watch?v=uGcDt7iNFkE • Duration: ~22 min
Key terms
| Term | Meaning |
|---|---|
| RBAC | Role-based access control |
| Role | A namespaced permission set |
| RoleBinding | Grants a Role to a subject in a namespace |
| Verb | The action (get/list/create/...) |
| Resource | The object type a rule covers |
| apiGroup | The API family a resource belongs to |
| Subject | The user/group/ServiceAccount being granted |
Problem & solution
Once requests are authenticated, you need a precise, auditable way to grant least-privilege permissions within a namespace instead of all-or-nothing access. Roles and RoleBindings define exactly who can do what.
Solution: Grant least-privilege access with a namespaced Role (verbs x resources) bound to a user or group via a RoleBinding.
The analogy
Think of an office worker handed a keycard that opens only a few specific doors, and only inside one building on a large campus. A Role is the list of doors that card is allowed to open, the exact verbs and resources, while a RoleBinding is the moment security links that card to your name. Swipe the same card at another building and nothing happens, because both the card and the doors it opens live inside a single namespace.
Where this fits in the cluster
The same cluster entities appear in every day's notes; the diagram below shows where this day's topic fits.
The idea
RBAC answers "what can this identity do?" with two halves:
ROLE -> a set of PERMISSIONS (verbs on resources) [namespaced]
ROLEBINDING -> ATTACHES a Role to a user / group / SA
A Role grants nothing by itself until a RoleBinding connects it to someone. Both are namespaced (cluster-wide equivalents = Day 24).
Permission = verbs x resources x apiGroups
A single rule is the combination of which verbs are allowed on which resources in which apiGroups.
verbs: get list watch create update patch delete
resources: pods deployments services configmaps ...
apiGroups: "" (core: pods, svc), "apps" (deployments), etc.
First, create a user (cert) — recap of Day 21/23
Before binding permissions you need an identity, so generate the user's cert via the CSR flow from Day 21.
openssl genrsa -out krishna.key 2048
openssl req -new -key krishna.key -out krishna.csr -subj "/CN=krishna"
# submit CSR -> approve -> pull signed cert:
kubectl get csr krishna -o jsonpath='{.status.certificate}' | base64 -d > krishna.crt
Role (the permissions)
The Role defines what may be done. Here an on-call engineer gets read-only
access to pods and their logs in the default namespace — exactly what you
grant a teammate who needs to debug a running app but must not change anything.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" = core API group
resources: ["pods", "pods/log"] # read pods and stream their logs
verbs: ["get", "watch", "list"]
RoleBinding (attach Role to the user)
The RoleBinding is what actually grants the permissions, connecting the Role to a specific subject such as our user.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: krishna # case-sensitive; must match CN
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # Role or ClusterRole
name: pod-reader # must match the Role name above
apiGroup: rbac.authorization.k8s.io
Imperative shortcuts
The same Role and RoleBinding can be created in one command each, without writing YAML.
kubectl create role pod-reader \
--verb=get,list,watch --resource=pods,pods/log -n default
kubectl create rolebinding read-pods \
--role=pod-reader --user=krishna -n default
Verify
Confirm the binding works by impersonating the user and checking both an allowed and a denied action.
kubectl auth whoami
kubectl auth can-i list pods # as yourself (admin -> yes)
kubectl auth can-i list pods --as krishna # -> yes (in default)
kubectl auth can-i delete pods --as krishna # -> no (not granted)
kubectl auth can-i list pods --as krishna -n kube-system # -> no (other ns)
End-to-end example: an on-call engineer reads pods and logs in one namespace
A namespaced Role + RoleBinding lets on-call engineer amy read pods and their
logs in dev (to debug the app) but gives her nothing in prod.
Graph legend — each step maps to a concrete object or decision:
| Graph step | Maps to | What it does |
|---|---|---|
| kubectl logs deploy/app -n dev | a get on the pods/log subresource | Reads container logs to debug the app |
| AuthN user amy group dev-team | the x509 authn plugin | Identifies CN=amy, group dev-team |
| AuthZ RoleBinding in dev | RoleBinding read-pods -> Role pod-reader (ns dev) | Grants get/list/watch on pods and pods/log |
| 200 OK, pod logs streamed | the allow path | Returns the requested logs |
| no RoleBinding for amy in prod | absence of any binding in prod | RBAC default-deny applies outside dev |
| 403 Forbidden | the deny path | Same identity, no permission in another namespace |
End-to-end flow
A namespaced Role plus RoleBinding grants access in one namespace and nowhere else.
Graph legend — each node maps to a concrete object or decision:
| Graph node | Maps to | What it does |
|---|---|---|
| amy: kubectl logs/get pods -n dev | the client request | Reads pods and their logs in dev |
| api-server AuthN: user=amy | the authn layer | Resolves the cert to user amy |
| AuthZ: look for a RoleBinding in dev | the RBAC authorizer | Searches dev for a binding covering amy |
| RoleBinding -> Role pod-reader | RoleBinding read-pods | Links amy to the pod-reader Role |
| Role allows get/list pods and pods/log | the pod-reader Role rules | Permits read access to pods and their logs |
| 403 Forbidden in other namespaces | RBAC default-deny | No binding outside dev means no access |
Key takeaways
- Role = permissions, RoleBinding = who gets them. Both namespaced.
- A rule is verbs x resources x apiGroups; core group is
"". - Subject
namemust match the certCNexactly (case-sensitive). - Test with
kubectl auth can-i <verb> <resource> --as <user>.
Checklist
- [ ] Created the
krishnauser cert via CSR - [ ] Created a
pod-readerRole and aread-podsRoleBinding - [ ] Verified access with
--as krishna(allowed verb + denied verb) - [ ] Confirmed the binding is scoped to its namespace only