A kube audit entry shows a front-end ServiceAccount listing secrets cluster-wide — find the RBAC gap
A cluster audit review surfaced the entry below. The front-end service only ever reads one ConfigMap in its own namespace, and it does not use the Kubernetes API for anything else.
Constraints:
- the front-end workload must keep reading that single ConfigMap in namespace
web - no wildcard resource or verb may remain in the resulting rules
- the fix must not rely on the workload choosing to behave
[audit] stage=ResponseComplete verb=list resource=secrets scope=cluster-wide
user=system:serviceaccount:web:frontend-sa
sourceIP=10.42.7.19 (pod frontend-7d9c) decision=allow responseStatus=200
[rbac] ClusterRoleBinding frontend-sa-binding -> ClusterRole frontend-reader
rules apiGroups [""] resources ["*"] verbs ["get","list","watch"]
[pod] frontend-7d9c automountServiceAccountToken not set
Find and fix the misconfiguration.
A ClusterRoleBinding to a role with a wildcard resource lets a namespaced front-end read every Secret in the cluster. Replace it with a namespaced Role naming that one ConfigMap and the verbs needed, bind it with a RoleBinding, and turn token automounting off.
- ✗Reading a ClusterRoleBinding as if it were limited to one namespace
- ✗Assuming read-only verbs make an over-broad role harmless
- ✗Treating the audit log verbosity as the defect rather than the grant
- →How would you find every other binding in the cluster with the same shape?
- →What detection rule would you add so this pattern alerts next time?
The cause is the grant, not the logging. A ClusterRoleBinding extends the role across the whole cluster, and resources ["*"] includes secrets, so from RBAC's point of view the front-end legitimately listed secrets in every namespace. Read-only verbs mitigate nothing here — reading a secret is the leak.
The fix narrows the grant to what the workload actually needs and drops the unused token.
kind: Role
metadata:
namespace: web
name: frontend-config-reader
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["frontend-config"]
verbs: ["get", "watch"]
---
kind: RoleBinding
metadata:
namespace: web
name: frontend-sa-binding
subjects:
- kind: ServiceAccount
name: frontend-sa
roleRef:
kind: Role
name: frontend-config-reader
The old ClusterRoleBinding and ClusterRole should be deleted, and the pod spec should set automountServiceAccountToken: false where the pod never calls the API. It is also worth a detection rule for list secrets by workload ServiceAccounts — that entry should raise an alert.