Grant least privilege with Kubernetes RBAC
# A Role scoped to one namespace and specific verbs — not ClusterRole, not *apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: namespace: orders name: orders-apprules: - apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list", "watch"]Why it matters
Section titled “Why it matters”cluster-admin is unrestricted control of the entire cluster: every namespace,
every secret, every workload, and the ability to grant others the same. It is the
Kubernetes equivalent of root, and it is bound far more widely than it should be —
to CI pipelines, to every engineer’s kubeconfig, to operators and controllers that
need a fraction of it.
Every over-broad binding is a blast radius. A leaked CI token bound to
cluster-admin is the whole cluster. A compromised pod whose service account can
get secrets cluster-wide reads every credential you have. RBAC is where you
decide that a leak is bounded to one namespace and one verb instead of everything.
The escalation verbs
Section titled “The escalation verbs”Three RBAC privileges are special because they let a subject grant themselves more — they’re how limited access becomes cluster-admin:
escalateon roles — create a role with more permissions than you have.bindon rolebindings — bind yourself to a more powerful role.impersonate— act as another user or service account, including admins.
A role that grants create/update on roles and rolebindings, or any of the
verbs above, is effectively cluster-admin even if it looks scoped. Also watch:
create pods is close to node-level power, because a pod can mount host paths
and service account tokens (see
privileged containers), and
access to secrets is access to whatever those secrets protect.
Role, not ClusterRole; verbs, not wildcards
Section titled “Role, not ClusterRole; verbs, not wildcards”Two habits do most of the work:
Role(namespaced), notClusterRole, unless the thing genuinely operates cluster-wide. AClusterRolebound with aClusterRoleBindingapplies in every namespace — the most common way “just for this app” becomes cluster-wide.- Named verbs and resources, never
*.verbs: ["*"]orresources: ["*"]grants everything including future resources you’ve never heard of. List what the workload calls.
Applications almost never need to write cluster-scoped objects. If a manifest asks for a ClusterRole with wildcards, that’s the finding.
Related
Section titled “Related”- Disable service account automount — the token RBAC governs.
- Secure the API server — RBAC is only enforced if the authorizer is on.
- Encrypt secrets at rest — what
get secretsexposes.