CKA — RBAC, ServiceAccounts, and Certificate-Based Auth — the domain's other half
The exam does not ask you to explain RBAC. It gives you a terminal and six minutes.
§ IWhere This Sits on the Blueprint
Cluster Architecture, Installation & Configuration is the CKA's largest domain at 25%, and it holds two different bodies of work. One is machinery: control-plane components, etcd backup and restore, kubeadm install and upgrade, high availability. The 07-23 lesson took that half.
The other is access control, on the curriculum as manage role based access control (RBAC). That single line is worth several questions on a scored attempt, and every one of them is answered by typing rather than by reasoning.
Today's Ops lesson carried the concepts at depth. This lesson assumes them and drills the exam surface: four objects cold, imperative creation, the verification commands the grader effectively runs, kubeconfig context surgery, and the CSR flow that mints a human credential. Poulton's chapter summary is the frame to carry into the terminal (ch. 13, p. 186).
§ IIThe Four Objects, Cold
| Enumerates permissions | Attaches to subjects | |
|---|---|---|
| Namespaced | Role | RoleBinding |
| Cluster-wide | ClusterRole | ClusterRoleBinding |
Three combinations are valid and one is not. Role plus RoleBinding is the everyday grant. ClusterRole plus ClusterRoleBinding is the cluster-wide grant. ClusterRole plus RoleBinding is the reuse case: the ClusterRole defines the permission set once, the RoleBinding scopes it into one namespace. A Role can never be bound by a ClusterRoleBinding, because its rules mean nothing outside its own namespace.
Commit that asymmetry. Questions phrase it as grant the built-in view permissions to user dev in namespace apps only, and the answer is ClusterRole view plus a namespaced RoleBinding. Reaching for a ClusterRoleBinding grants view cluster-wide and fails the check.
Subject kinds
A binding names subjects with three kinds: User, Group, ServiceAccount. Users and Groups are strings the authenticator produced, with no object behind them (Poulton, p. 177). ServiceAccounts are real objects and require a namespace field in the subject entry, which is the single most common YAML mistake in this domain.
The built-in gradient
view reads most things but not Secrets. edit writes workloads but cannot touch RBAC objects. admin adds RBAC management within a namespace. cluster-admin is * on * in *. If a question asks for read-only across a namespace, the answer is view, not a hand-written Role.
§ IIIImperative Creation, Because the Clock Is Real
Nobody passes this domain writing YAML by hand. The imperative forms are the answer, and --dry-run=client -o yaml is how you get an editable manifest when the question wants a field the flags do not expose.
kubectl create role ledger-writer \
--verb=get,list,watch --resource=configmaps -n trading
kubectl create rolebinding ledger-writer-binding \
--role=ledger-writer \
--serviceaccount=trading:ledger-writer -n trading
kubectl create clusterrole node-reader \
--verb=get,list,watch --resource=nodes
kubectl create clusterrolebinding dev-view \
--clusterrole=view --user=dev
kubectl create rolebinding dev-view-apps \
--clusterrole=view --user=dev -n apps
Read the flag grammar closely, because it is where marks are lost. --role names a Role and --clusterrole names a ClusterRole; the last two commands differ only in which flag and which scope. Subject flags are --user, --group, --serviceaccount, and the ServiceAccount form takes namespace:name in one string.
kubectl create serviceaccount ledger-writer -n trading
kubectl create role patcher \
--verb=get,patch --resource=deployments \
--resource-name=ledger -n trading
--resource-name is the narrowing flag. A question saying allow patching only the deployment named ledger is testing whether you know it exists.
§ IVVerification — the Commands That Decide the Mark
The grader checks behavior, not YAML. Check the same way.
kubectl auth can-i list secrets -n trading \
--as system:serviceaccount:trading:ledger-writer
kubectl auth can-i '*' '*' --as dev
kubectl auth can-i create deployments -n apps --as dev --list
The ServiceAccount username format is exact: system:serviceaccount:<namespace>:<name>. Every ServiceAccount also joins the group system:serviceaccounts:<namespace> and the cluster-wide system:serviceaccounts. A binding to either group hits every ServiceAccount in scope, which is how an over-grant question is usually built.
Impersonation needs permission. --as requires the impersonate verb on users, groups, or serviceaccounts. In the exam you are cluster-admin so it works. In a real cluster, impersonate on groups is effectively a path to whatever those groups hold.
Check the negative cases. A grant-read-only question tests both that get returns yes and that create returns no. A cluster-admin binding satisfies the first and fails the task.
kubectl describe rolebinding ledger-writer-binding -n trading
roleRef is immutable after creation. A wrong roleRef is deleted and recreated, never patched. Attempting the patch wastes a minute you do not have.
§ VWorked Scenario — Minting a Human Identity with a CSR
This question separates candidates and runs across both CKA and CKS. The Sovereign-Bootcamp corpus carries it as a scored lab at CKS-PREP-2025/questions/24-user-csr-rbac with its own LabSetUp.bash, Questions.bash, and Verify.bash. Below is the same flow at exam pace.
Task: create a credential for user sasha who may read pods in namespace trading and nothing else. Deliver a kubeconfig context that works.
Kubernetes has no User object, so the identity comes from a certificate the cluster CA signed. The Common Name becomes the username; the Organization becomes the group.
openssl genrsa -out sasha.key 2048
openssl req -new -key sasha.key -out sasha.csr \
-subj "/CN=sasha/O=traders"
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: sasha
spec:
request: <base64 of sasha.csr, no wrapping>
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 86400
usages:
- client auth
signerName must be kubernetes.io/kube-apiserver-client for a human client credential. The other signers exist for kubelet serving and kubelet client certificates; choosing one produces a certificate the API server will not accept for user authentication. Base64-encode the CSR with no line wraps, which is what base64 -w 0 buys.
kubectl apply -f sasha-csr.yaml
kubectl certificate approve sasha
kubectl get csr sasha -o jsonpath='{.status.certificate}' | base64 -d > sasha.crt
The certificate proves who. It grants nothing. Authorize separately:
kubectl create role pod-reader \
--verb=get,list,watch --resource=pods -n trading
kubectl create rolebinding sasha-pod-reader \
--role=pod-reader --user=sasha -n trading
kubectl config set-credentials sasha \
--client-key=sasha.key --client-certificate=sasha.crt --embed-certs=true
kubectl config set-context sasha-trading \
--cluster=kubernetes --user=sasha --namespace=trading
kubectl config use-context sasha-trading
kubectl get pods
kubectl get secrets
The last two lines are the verification. Pods list. Secrets return Forbidden. That pair answers the task as asked. --embed-certs=true is the flag worth remembering: without it the kubeconfig stores file paths, and the config stops working the moment it leaves the directory those files sit in.
§ VIFive Traps, Named
The empty apiGroup. Core resources (pods, services, configmaps, secrets, serviceaccounts) live in apiGroups: [""]. Deployments live in apps. RBAC objects live in rbac.authorization.k8s.io. Writing apiGroups: ["v1"] produces a Role granting nothing, with no error reported.
Missing namespace on a ServiceAccount subject. In a RoleBinding, a subject of kind ServiceAccount requires namespace. Omit it and the binding matches nothing.
get versus list. get needs the object name; list enumerates and returns contents. Granting list on Secrets where get was asked for is a silent over-grant a good question checks with a negative case.
Immutable roleRef. Delete and recreate. Do not patch.
No deny rules. RBAC is additive only. A question saying remove dev's ability to delete pods asks you to find and delete a binding, never to add a restricting one.
§ VIIPractice Drill
Tap a card to reveal its resolution. Score cold first.
dev must have the built-in read-only permissions in namespace apps and in no other namespace. Which two objects, and what is the trap?view plus a namespaced RoleBinding in apps. The trap is reaching for a ClusterRoleBinding, which grants view cluster-wide and fails the scoping requirement. kubectl create rolebinding dev-view --clusterrole=view --user=dev -n apps.ci in namespace build the verbs get, list, create on pods, using an existing Role named ci-runner.kubectl create rolebinding ci-runner-binding --role=ci-runner --serviceaccount=build:ci -n build. Note --role rather than --clusterrole, and the namespace:name form of the ServiceAccount flag.agent in trading gets 403 on list secrets. can-i --as system:serviceaccount:trading:agent returns no. The RoleBinding points at Role agent-reader, which grants ["get","list"] on ["secrets"] in apiGroups: ["v1"]. Name the bug.apiGroups value. Secrets are in the core group, written "", not "v1". The Role parses, applies to nothing, and the authorizer correctly answers no. Change to apiGroups: [""].roleRef. What is the fix?roleRef is immutable, so a patch is rejected.signerName mints a client credential for a human user, and what does the certificate's Organization field become?kubernetes.io/kube-apiserver-client. The Organization (O=) becomes the Kubernetes group; the Common Name (CN=) becomes the username.edit to group system:serviceaccounts:staging. What is the blast radius?staging, present and future, holds edit across the entire cluster. edit cannot modify RBAC objects, so it is not a direct escalation path, but it can write workloads in every namespace. Fix by deleting the binding, not by adding a narrower one.§ VIIIThe Trio Interlock
Ops carried the request path and the GKE cloud-identity bridge, which is where RBAC stops and IAM starts. Dev built the preflight: SelfSubjectAccessReview in Python, checked at controller startup so a missing verb crashes the deploy rather than a reconcile. This lesson is the same material at exam pace, by hand, against a clock.
Coverage note for the next CKA day: Workloads & Scheduling (15%) and Storage (10%) are the two blueprint domains still untouched by this arc.
Set a six-minute timer. Do the CSR scenario in §V start to finish without scrolling back. The minute you lose is always the same minute, and finding out which one is the point of the drill.
Filed 2026-08-04 Fajr · Cert-Prep lesson · CKA-emphasis (k8s_day_counter 4, even) · K8s deep-mastery track day 13