RBAC: roles, bindings and service accounts
Roles, ClusterRoles and their bindings, the three kinds of subject, service account tokens, and how to prove access with kubectl auth can-i.
After this lesson
- 01You can create a ServiceAccount, Role and RoleBinding imperatively in under two minutes and choose correctly between Role and ClusterRole, RoleBinding and ClusterRoleBinding.
- 02You can write rules with the right apiGroups, plural resources, subresources and resourceNames.
- 03You can prove what a user, group or service account may and may not do with kubectl auth can-i --as and --as-group.
- 04You can issue a time-limited service account token and remove access that was granted too broadly.
Manage role based access control (RBAC) is the first competency in the architecture domain and one of the most dependable sources of points: a service account, a role and a binding are three short commands. The grader does not read your YAML. It asks the API server whether a subject may perform a verb on a resource, exactly as kubectl auth can-i does, so a rule with the wrong API group fails even when it looks right. RBAC has no deny rules either; a subject's access is the union of every binding that names it, which means taking access away always means removing or narrowing a binding.
Four objects, and where their rules apply
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: config-editor
namespace: arx-rbac-demo
rules:
- apiGroups: [""] # "" is the core group: pods, services, configmaps, secrets
resources: ["configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["app-settings"] # this one object only
verbs: ["update", "patch"]
- apiGroups: ["apps"]
resources: ["deployments", "deployments/scale"]
verbs: ["get", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: config-editor
namespace: arx-rbac-demo
roleRef: # immutable: to point elsewhere, delete and recreate the binding
apiGroup: rbac.authorization.k8s.io
kind: Role
name: config-editor
subjects:
- kind: ServiceAccount # no apiGroup; namespace is required
name: settings-sync
namespace: arx-rbac-demo
- kind: User # the name the authenticator reports (certificate CN, OIDC claim)
apiGroup: rbac.authorization.k8s.io
name: maya
- kind: Group # certificate O field, OIDC groups claim, or a system: group
apiGroup: rbac.authorization.k8s.io
name: platform-oncallapiGroupsis the part ofapiVersionbefore the slash. Core objects use""; Deployments, StatefulSets, DaemonSets and ReplicaSets areapps; Jobs and CronJobs arebatch; Ingresses and NetworkPolicies arenetworking.k8s.io.kubectl api-resources -o wideprints the group and supported verbs of every resource.resourcesare lowercase plurals. Subresources are separate entries:pods/log,pods/exec,deployments/scale,nodes/status. Access topodsgrants nothing onpods/exec.verbs:get,list,watch,create,update,patch,delete,deletecollection, plus special verbs such asimpersonate,bindandescalate."*"matches every verb, including ones added later.resourceNamesnarrows a rule to named objects. It cannot restrictcreateordeletecollection(the name is not known when the request is authorized), and alistorwatchonly matches if it selects that exact name, so pair it with get, update, patch and delete.nonResourceURLssuch as/healthzor/metricsonly work in a ClusterRole bound with a ClusterRoleBinding.
Create it imperatively, prove it with auth can-i
kubectl create namespace arx-rbac-demo
kubectl -n arx-rbac-demo create serviceaccount settings-sync
# Role: comma-separated verbs, any number of resources; non-core resources as <resource>.<group>
kubectl -n arx-rbac-demo create role app-reader \
--verb=get,list,watch --resource=pods,services,deployments.apps
kubectl -n arx-rbac-demo create role settings-writer \
--verb=update,patch --resource=configmaps --resource-name=app-settings
# RoleBinding: --role or --clusterrole, then any mix of subjects (SA is <namespace>:<name>)
kubectl -n arx-rbac-demo create rolebinding app-reader --role=app-reader \
--serviceaccount=arx-rbac-demo:settings-sync --user=maya --group=platform-oncall
kubectl -n arx-rbac-demo create rolebinding settings-writer --role=settings-writer --user=maya
# Cluster-wide rules and binding
kubectl create clusterrole pv-viewer --verb=get,list,watch \
--resource=persistentvolumes,storageclasses.storage.k8s.io
kubectl create clusterrolebinding pv-viewer --clusterrole=pv-viewer --group=platform-oncall
# Ask the API server as the subject. "yes" exits 0, "no" exits 1.
kubectl auth can-i list deployments.apps -n arx-rbac-demo \
--as=system:serviceaccount:arx-rbac-demo:settings-sync
kubectl auth can-i update configmaps/app-settings -n arx-rbac-demo --as=maya # TYPE/NAME form
kubectl auth can-i get pods --subresource=log -n arx-rbac-demo --as=maya # subresources need the flag
kubectl auth can-i list persistentvolumes --as=anyone --as-group=platform-oncall # --as-group needs --as
kubectl auth can-i --list -n arx-rbac-demo --as=system:serviceaccount:arx-rbac-demo:settings-sync
kubectl auth whoami # who you are right now
# Generate YAML instead when you need to add something the flags cannot express
kubectl -n arx-rbac-demo create role app-reader --verb=get --resource=pods --dry-run=client -o yamlService accounts, tokens and the built-in ClusterRoles
A ServiceAccount is a namespaced identity for software. Its username is system:serviceaccount:<namespace>:<name>, and it is a member of system:serviceaccounts and system:serviceaccounts:<namespace>, the group to bind when a rule should cover every account in a namespace. A Pod runs as the account in spec.serviceAccountName (default when unset), and the kubelet mounts a short-lived, automatically rotated token at /var/run/secrets/kubernetes.io/serviceaccount/token. Token Secrets are no longer created for you: kubectl create token asks the TokenRequest API for a token on demand. Set automountServiceAccountToken: false on the Pod or the ServiceAccount when the workload never calls the API.
kubectl -n arx-rbac-demo create serviceaccount report-bot
kubectl -n arx-rbac-demo create token report-bot --duration=2h > /tmp/cka/report-bot.token
# Printed once and never stored. A long-lived token (avoid unless asked) is a Secret the control plane fills in:
kubectl -n arx-rbac-demo apply -f - <<'YAML'
apiVersion: v1
kind: Secret
metadata:
name: report-bot-token
annotations:
kubernetes.io/service-account.name: report-bot
type: kubernetes.io/service-account-token
YAML
# Run as the account: kubectl run has no SA flag, so override the spec (or set it in YAML)
kubectl -n arx-rbac-demo run reporter --image=busybox:1.36 --restart=Never \
--overrides='{"spec":{"serviceAccountName":"report-bot"}}' -- sleep 3600
kubectl -n arx-rbac-demo set serviceaccount deployment/web report-bot # an existing Deployment
# Aggregation: this ClusterRole's rules are merged into the built-in "view" role automatically
kubectl apply -f - <<'YAML'
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: backup-viewer
labels:
rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["ops.example.com"]
resources: ["backuppolicies"]
verbs: ["get", "list", "watch"]
YAMLIn the docs · the tab you get on exam day
- Using RBAC Authorization ↗search: “rbac authorization”
- Configure Service Accounts for Pods ↗search: “configure service accounts”
- kubectl auth can-i ↗search: “kubectl auth can-i”
- Managing Service Accounts ↗search: “managing service accounts”
context · kubectl config use-context kind-cka
A service account that can deploy, and a token for it
arx-rbac, create a ServiceAccount named deployer and a Role named deployer that allows get, list, watch, create, update and patch on Deployments, and get, list, watch on Pods, and nothing else. Bind the Role to the ServiceAccount with a RoleBinding named deployer-binding. Finally, create a token for deployer that is valid for 2 hours and write only the token to /tmp/cka/rbac/deployer.token.- 01
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-1/setup | bash - 02
Solve it in your terminal
Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under
/tmp/cka/. - 03
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-1/verify | bashCounts toward your readiness score. - 04
Clean up
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-1/cleanup | bash
context · kubectl config use-context kind-cka
Read-only node access for a group
arx-ops need to inspect nodes and PersistentVolumes across the cluster without changing anything. Create a ClusterRole named arx-node-reader that allows get, list and watch on nodes and persistentvolumes, and grant it to the group arx-ops with a ClusterRoleBinding named arx-node-reader-ops. The group must not gain any other access.- 01
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-2/setup | bash - 02
Solve it in your terminal
Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under
/tmp/cka/. - 03
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-2/verify | bashCounts toward your readiness score. - 04
Clean up
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-2/cleanup | bash
context · kubectl config use-context kind-cka
Take back cluster-admin from a service account
log-shipper in namespace arx-rbac-fix was given cluster-admin to get a log collector working. It only needs to read Pods and their logs in its own namespace. Remove the excess access, then grant exactly get, list, watch on Pods and get on Pod logs in arx-rbac-fix, using a Role named log-reader and a RoleBinding named log-shipper-read. Do not delete the ServiceAccount.- 01
Set up the scenario
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-3/setup | bash - 02
Solve it in your terminal
Work the way the exam makes you: kubectl, the docs, nothing else. Put any answer files under
/tmp/cka/. - 03
Check your work
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-3/verify | bashCounts toward your readiness score. - 04
Clean up
curl -fsSL https://codewithmuh.com/labs/cka/t/ar-rbac-3/cleanup | bash
Finished reading?
0 of 3 tasks passed. Readiness counts tasks, so run them before you move on.