Skip to main content
RunBook Academy

KubernetesLVIII · RBACRBAC

Verbs and resources — the RBAC decision matrix

Advanced⏱ ~16 minkubectl

What you'll learn

  • Map common operational tasks to the minimum RBAC verbs and resources
  • Distinguish read-only verbs from write verbs and the danger of each
  • Identify the dangerous combinations (`update` on Pods, `patch` on Deployments, `create` on ClusterRoleBindings)
  • Build a Role for a real workload with concrete verbs and resources

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

A Role is a matrix of verbs × resources. The matrix is what determines what the subject can do. This lesson maps common production tasks to the minimum RBAC verbs, identifies the dangerous combinations, and shows how to build a Role for a real workload.

The verb × resource matrix

For a typical workload in a typical namespace, the matrix is:

ResourceRead (get, list, watch)Write (create, update, patch, delete)Notes
podsOKDANGEROUSupdate swaps the image; delete kills the Pod
pods/logOKRead-only subresource
pods/execDANGEROUSRequires pods/exec + verb create
servicesOKOKcreate/delete are common for operators
configmapsOKOKOften read-only at runtime; written at deploy
secretsOKDANGEROUSRead is dangerous if the Secret holds credentials
deploymentsOKOKupdate/patch triggers a rollout
statefulsetsOKOKSame as Deployments
daemonsetsOKOKSame as Deployments
jobsOKOKOperators create Jobs
cronjobsOKOKOperators create CronJobs
eventsOKRead-only; usually granted to monitoring
nodesOKDANGEROUSCluster-scoped; update allows node cordoning
rbac.rolebindingsESCALATIONPrivilege escalation primitive
rbac.clusterrolebindingsCRITICALcluster-admin if bound to the right role

Read-only roles

A read-only role for a workload is:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: readonly
  namespace: prod
rules:
- apiGroups: [""]
  resources: ["pods", "services", "configmaps", "endpoints"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get"]
- apiGroups: ["apps"]
  resources: ["deployments", "statefulsets", "daemonsets"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
  resources: ["jobs", "cronjobs"]
  verbs: ["get", "list", "watch"]

This role can read every workload-related object in the namespace but cannot write. The verbs are explicit; no wildcards.

# Verify the role
kubectl auth can-i --list --as=system:serviceaccount:prod:readonly-sa -n prod

Operator roles

An operator that creates Deployments and Services needs both read and write:

rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apiextensions.k8s.io"]
  resources: ["customresourcedefinitions"]
  verbs: ["get", "list", "watch"]

This operator can manage Deployments, Services, and ConfigMaps in the namespace but cannot touch Secrets, RBAC objects, or other namespaces. The customresourcedefinitions read is for watching the CRD’s status field — not for modifying the CRD itself.

Privilege escalation

The escalate verb on RBAC objects is the privilege-escalation primitive. The cluster’s built-in protection:

  • A user cannot create a RoleBinding that grants permissions they do not already have. The API server checks at admission time.
  • The escalate verb allows a user to create a RoleBinding to a Role they do not have access to. This is restricted to specific subjects.
# Can alice create a RoleBinding for cluster-admin?
kubectl auth can-i create clusterrolebindings \
  --as=alice
# no

# Can alice escalate to a Role she doesn't have?
kubectl auth can-i escalate role \
  --as=alice
# no

Subresources

Some resources have subresources that require separate permissions:

SubresourceVerb neededWhat it allows
pods/loggetRead container logs
pods/execcreateExecute a command in a container
pods/portforwardcreatePort-forward to a container
pods/evictioncreateEvict a Pod (drain)
pods/proxy*Proxy to a Pod’s HTTP endpoints
deployments/scaleupdateScale a Deployment
nodes/proxy*Proxy to a node’s HTTP endpoints

A role that grants pods with get cannot get pods/log; the subresource must be added explicitly.

rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create"]

Production failure modes

  1. Granting * verbs on Pods — every write verb on Pods. The caller can swap images, kill pods, and exec into containers. Almost never the right pattern.
  2. Granting * resources — every kind. Includes Secrets, RBAC objects, and CRDs. The caller can read every Secret and create RoleBindings.
  3. Granting update on Deployments to a runtime SA — the SA can roll the workload. Operators should never have this; humans and CI/CD should, but carefully.
  4. Granting deletecollection on a workload kind — the caller can delete every Pod, every ConfigMap, every Service in one call. Useful for cleanup, dangerous in steady-state.
  5. Granting create on ClusterRoleBindings — the caller can bind themselves to cluster-admin. Always restricted; never granted to a SA.

Cross-course references

  • The Observability course covers the audit log that records every RBAC decision.
  • The Linux course covers the file permissions on Secret data — Kubernetes RBAC does not enforce these; secrets stored as files are protected by filesystem ACLs only.

Quiz

Knowledge check · 4 questions

  1. Q1. Which subresource and verb combination allows a ServiceAccount to exec into a Pod?

  2. Q2. Any user can create a ClusterRoleBinding that grants `cluster-admin`, because RBAC objects are just API resources.

  3. Q3. Your CI pipeline runs `kubectl set image deployment/api api=myapp:v1.1` to roll a Deployment. The CI SA has a Role with `apps/deployments: [get, list, watch, update]`. The roll succeeds. Six months later, an attacker compromises the CI SA and runs `kubectl set image deployment/api api=attacker/myapp:latest`. The image is pulled. What happened?

    The role grants `update` on Deployments to the CI SA. The CI SA's token was leaked in a CI runner log. The attacker had network reach to the API server and the right token. The cluster has an admission policy that requires image signatures; the `attacker/myapp:latest` image is unsigned and should be rejected — but the policy was disabled two weeks ago for testing.

  4. Q4. Name three Kubernetes subresources and the verb each one requires.

Passing score: 75%. Answers are checked in this browser.

Production discipline

A defensible Role grants the smallest set of verbs on the smallest set of resources at the smallest scope. Read verbs (get, list, watch) are the foundation; write verbs (create, update, patch, delete, deletecollection) are added one at a time with explicit justification. The dangerous combinations (update on Pods, create on ClusterRoleBindings, * on RBAC objects) are restricted to the minimum number of subjects. The subresources (pods/exec, pods/log, deployments/scale) are explicit; the parent resource does not imply the subresource. The audit log is the proof: every verb × resource combination should be explainable. A cluster whose roles are not explainable has an RBAC programme that is not defensible.