RBAC controls what identities can do in Kubernetes. ServiceAccounts give pods an identity. Misconfigured RBAC -- especially wildcard permissions and cluster-admin bindings -- is the most common privilege escalation path in production clusters.
Understand the Subject-RoleBinding-Role model. Know the difference between Role (namespace) and ClusterRole (cluster-wide). Never use cluster-admin for application ServiceAccounts.
Design least-privilege ServiceAccount roles. Use kubectl auth can-i to verify permissions. Understand aggregated ClusterRoles and how they compose.
Audit existing RBAC with rbac-audit tools. Implement RBAC policies that prevent privilege escalation (no binding of higher roles than you have). Restrict ServiceAccount token auto-mounting.
Design RBAC for multi-tenant clusters: namespace-scoped admin roles, shared cluster roles, OPA/Gatekeeper policies enforcing RBAC hygiene, and continuous RBAC drift detection.
RBAC controls what identities can do in Kubernetes. ServiceAccounts give pods an identity. Misconfigured RBAC -- especially wildcard permissions and cluster-admin bindings -- is the most common privilege escalation path in production clusters.
CI/CD ServiceAccount granted wildcard ClusterRole for "pipeline to work"
Security audit discovers wildcard ClusterRoleBinding; escalation path demonstrated
Researcher creates Job via pipeline SA that grants new SA cluster-admin in 3 API calls
All Secrets in cluster accessible; signing keys potentially compromised
All credentials rotated; RBAC audit tooling (kubectl-who-can) deployed; wildcard roles prohibited
The question this raises
What is the minimum RBAC privilege a ServiceAccount needs to escalate to cluster-admin, and how do you prevent wildcard roles from persisting undetected?
A pod has a ServiceAccount with a Role that allows: resources: ["pods"], verbs: ["get", "list"]. The pod is compromised. What can the attacker do?
Lesson outline
The Authorization Problem
Authentication (who are you?) and authorization (what can you do?) are separate in Kubernetes. RBAC is the authorization layer. It answers: can this identity (user, group, ServiceAccount) perform this action (verb) on this resource type in this namespace?
Least-privilege ServiceAccount
Use for: Create a dedicated ServiceAccount per workload. Grant only the specific resources and verbs needed. No auto-mounted token if the workload does not call the K8s API. This limits blast radius if the pod is compromised.
Aggregated ClusterRole
Use for: A ClusterRole with aggregationRule collects rules from other ClusterRoles matching a label. Used to build composable roles (view, edit, admin) without duplication. Adding a new CRD resource requires only labeling a new ClusterRole.
RBAC audit
Use for: Tools like rbac-lookup and kubectl-who-can enumerate who has what permissions. Run regularly to detect wildcard roles, unexpected cluster-admin bindings, and ServiceAccounts with over-broad permissions.
Creating least-privilege ServiceAccount for a deployment controller
01
1. Create ServiceAccount: kubectl create serviceaccount myapp -n production
02
2. Define Role with minimum required verbs/resources for the specific namespace
03
3. Create RoleBinding linking the ServiceAccount to the Role
04
4. Set automountServiceAccountToken: false if the pod does not call K8s API
05
5. Verify with: kubectl auth can-i list pods --as=system:serviceaccount:production:myapp
06
6. Test a forbidden action: kubectl auth can-i delete secrets --as=system:serviceaccount:production:myapp (should say "no")
1. Create ServiceAccount: kubectl create serviceaccount myapp -n production
2. Define Role with minimum required verbs/resources for the specific namespace
3. Create RoleBinding linking the ServiceAccount to the Role
4. Set automountServiceAccountToken: false if the pod does not call K8s API
5. Verify with: kubectl auth can-i list pods --as=system:serviceaccount:production:myapp
6. Test a forbidden action: kubectl auth can-i delete secrets --as=system:serviceaccount:production:myapp (should say "no")
1apiVersion: v12kind: ServiceAccount3metadata:4name: myapp5namespace: productionautomountServiceAccountToken: false -- no token in pod unless explicitly mounted6automountServiceAccountToken: false # no token unless needed78---9apiVersion: rbac.authorization.k8s.io/v110kind: Role11metadata:12name: myapp-role13namespace: production14rules:15- apiGroups: [""]resourceNames: restrict to specific objects -- prevents reading all ConfigMaps16resources: ["configmaps"]17resourceNames: ["myapp-config"] # specific CM only18verbs: ["get"]19- apiGroups: ["apps"]20resources: ["deployments"]21verbs: ["get", "list"] # read-only on deployments2223---24apiVersion: rbac.authorization.k8s.io/v125kind: RoleBinding26metadata:27name: myapp-binding28namespace: production29subjects:30- kind: ServiceAccount31name: myapp32namespace: production33roleRef:34kind: Role35name: myapp-role36apiGroup: rbac.authorization.k8s.io
RBAC misconfiguration failure modes
Wildcard ClusterRole enables full cluster compromise from single SA
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pipeline-role
rules:
- apiGroups: ["*"] # every API group
resources: ["*"] # every resource type
verbs: ["*"] # every action
# This is equivalent to cluster-admin
# Can read all Secrets, create ClusterRoleBindings, delete nodesapiVersion: rbac.authorization.k8s.io/v1
kind: Role # namespace-scoped, not ClusterRole
metadata:
name: pipeline-deployer
namespace: production # only this namespace
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "create", "update", "patch"]
- apiGroups: [""]
resources: ["services", "configmaps"]
verbs: ["get", "list", "create", "update"]Wildcard ClusterRoles grant full cluster access. Replace with namespace-scoped Role with only the verbs and resources the pipeline actually needs. Most CI/CD pipelines only need to apply Deployments and Services in specific namespaces.
| Pattern | Blast radius | Operational cost | Auditability | Recommended for |
|---|---|---|---|---|
| cluster-admin binding | Full cluster | None (just works) | Hard to audit | Never for apps or CI/CD |
| Wildcard ClusterRole | Full cluster (effectively) | Low | Hard to audit | Never in production |
| Namespace Role + RoleBinding | Namespace-scoped | Medium | Easy to audit | All application SAs |
| Specific resourceNames | Single object | High (enumerate objects) | Very easy | Sensitive ConfigMaps/Secrets |
| No SA (automount: false) | None | None | N/A | Pods that do not use K8s API |
Role vs ClusterRole
📖 What the exam expects
Role: grants permissions within one namespace. ClusterRole: grants permissions cluster-wide or can be used as a template bound in specific namespaces via RoleBinding.
Toggle between what certifications teach and what production actually requires
Security architecture questions about multi-tenant cluster design and debugging questions about "forbidden" API errors.
Common questions:
Strong answer: Mentions RBAC audit tools (rbac-audit, kubectl-who-can), OPA/Gatekeeper to enforce RBAC policies, and WorkloadIdentity / IRSA for cloud provider access instead of Secrets in pods.
Red flags: Granting cluster-admin to CI/CD pipelines, using wildcard resources/verbs, or not knowing that auto-mounted tokens are an attack surface.
Related concepts
Explore topics that connect to this one.
Suggested next
Often learned after this topic.
Pod Security Standards: Hardening Workload ConfigurationsReady to see how this works in the cloud?
Switch to Career Paths for structured paths (e.g. Developer, DevOps) and provider-specific lessons.
View role-based pathsSign in to track your progress and mark lessons complete.
Questions? Discuss in the community or start a thread below.
Join DiscordSign in to start or join a thread.