Kubernetes RBAC Least Privilege: Roles, Bindings, and Safe Permission Testing

RBAC Has Two Separate Questions

A Role or ClusterRole defines what is permitted. A RoleBinding or ClusterRoleBinding defines who receives it. Keeping those questions separate makes policies easier to review.

Suppose a reporting ServiceAccount needs to list Pods, read individual Pod logs, and read one ConfigMap in the finance namespace. It must not read Secrets, create Pods, or delete anything.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: report-reader
  namespace: finance
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: report-reader
  namespace: finance
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get"]
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["report-settings"]
    verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: report-reader
  namespace: finance
subjects:
  - kind: ServiceAccount
    name: report-reader
    namespace: finance
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: report-reader

The empty API group means core resources. Deployment rules instead use apiGroups: ["apps"]. Subresources are explicit: permission on pods does not automatically grant pods/log or pods/exec.

---

Role, ClusterRole, and Binding Scope

A Role contains namespace-scoped permissions in one namespace. A ClusterRole can include cluster-scoped resources such as nodes and can also serve as a reusable permission template.

Binding behavior is the crucial part:

If the same application role is needed in 30 namespaces, define one ClusterRole and create a RoleBinding in each namespace. Do not use a ClusterRoleBinding merely to avoid repeated bindings; it silently expands the blast radius.

---

Verify Positive and Negative Requirements

kubectl auth can-i list pods -n finance \
  --as=system:serviceaccount:finance:report-reader
kubectl auth can-i get pods/log -n finance \
  --as=system:serviceaccount:finance:report-reader
kubectl auth can-i delete pods -n finance \
  --as=system:serviceaccount:finance:report-reader
kubectl auth can-i get secrets -n finance \
  --as=system:serviceaccount:finance:report-reader
kubectl auth can-i list pods -n payroll \
  --as=system:serviceaccount:finance:report-reader

A good test proves required actions return yes and forbidden actions return no. kubectl auth can-i --list is useful for exploration, but explicit checks are better regression tests.

Impersonation itself is privileged. A successful --as test proves authorization under the impersonated identity only if your current identity may impersonate it.

---

High-Risk Permissions That Look Harmless

Permission to create Pods in a namespace may enable mounting Secrets, using powerful service accounts, or accessing node-mounted paths if admission controls allow it. Permission to create or patch RoleBindings can turn an existing powerful role into the caller's role. Permission to read Secrets exposes credentials. Permission to use pods/exec can expose the identity and data of a running application.

Wildcards are future permissions too. A rule with resources: ["*"] may automatically cover a resource introduced after the original review. Prefer named verbs and resources in application-facing roles.

Also avoid distributing static service-account token Secrets. Modern workloads normally receive short-lived, projected tokens. Set this when a Pod does not call the Kubernetes API:

spec:
  automountServiceAccountToken: false

---

A Practical Review Workflow

kubectl get role,rolebinding -A
kubectl get clusterrolebinding -o wide
kubectl -n finance describe rolebinding report-reader
kubectl get clusterrole platform-viewer -o yaml

For each binding, identify subjects, roleRef, effective scope, wildcard rules, secret access, workload creation, exec/attach, escalation-related RBAC changes, and whether the identity is still active. Remember that RBAC permissions are additive; there is no deny rule. Removing one binding does not remove access granted elsewhere.

Use groups for humans where possible and workload-specific service accounts for applications. Avoid binding normal workloads to the namespace's default ServiceAccount. Separate deployment automation from runtime identity: an application rarely needs the same permissions its delivery pipeline needs.

Practice writing the exact Pod and ConfigMap rules, binding them, and proving deletion remains denied in Enforce Least-Privilege RBAC. The Kubernetes theory course covers authentication, authorization, admission, and Pod security as separate control layers.