Kubernetes RBAC Audit: Find Actual Access
This guide walks you through auditing Kubernetes Role-Based Access Control (RBAC) to determine exactly which permissions each user, group, or service account currently holds. You’ll learn to enumerate roles, bindings, and effective permissions using kubectl commands and a few essential tools. No prior RBAC expertise is required, but basic familiarity with kubectl and Kubernetes objects is assumed.
What You’ll Need
- Access to a Kubernetes cluster (or multiple clusters) with
kubectlconfigured. - Permissions to read RBAC objects (roles, clusterroles, rolebindings, clusterrolebindings). Typically cluster-admin or a custom role with get/list on these resources.
- Optional:
jqfor JSON parsing, andkubectlpluginkubectl-who-canfor reverse lookup. - If you have a large cluster, consider using a tool like
rbac-lookuporkubeauditto automate the process, but manual steps below work for any size.
Step-by-Step
- List all RBAC objects. Start by getting a complete inventory. Run:
kubectl get roles -A kubectl get clusterroles kubectl get rolebindings -A kubectl get clusterrolebindings
Save these to files for reference. For a quick count, use
kubectl get roles -A --no-headers | wc -l. - Identify subjects. Subjects are users, groups, or service accounts that are bound to roles. Extract them from all bindings:
kubectl get rolebindings -A -o json | jq -r '.items[].subjects[]? | .kind + "/" + .name' kubectl get clusterrolebindings -o json | jq -r '.items[].subjects[]? | .kind + "/" + .name'
This gives you a list of unique subjects. Note that users and groups are not actual Kubernetes objects; they are strings defined by the authentication provider (e.g., OIDC, certificates).
- Map each subject to its roles. For each subject, find which RoleBindings and ClusterRoleBindings reference it. You can do this manually by inspecting the JSON output, or use a script. For a single subject, say
alice, run:kubectl get rolebindings -A -o json | jq --arg s "alice" '.items[] | select(.subjects[]?.name == $s) | .metadata.namespace + "/" + .metadata.name + " -> " + .roleRef.kind + "/" + .roleRef.name' kubectl get clusterrolebindings -o json | jq --arg s "alice" '.items[] | select(.subjects[]?.name == $s) | .metadata.name + " -> " + .roleRef.kind + "/" + .roleRef.name'
Repeat for each subject, or write a loop.
- Expand roles to permissions. Once you know which roles a subject has, list the rules (verbs and resources) for each role. For a role named
my-rolein namespacedev:kubectl get role my-role -n dev -o json | jq '.rules'
For a clusterrole:
kubectl get clusterrole my-clusterrole -o json | jq '.rules'
This shows the permissions like
{"apiGroups":[""],"resources":["pods"],"verbs":["get","list"]}. - Use kubectl auth can-i to verify effective access. Instead of manually combining roles, use
kubectl auth can-ito check what a subject can do against a specific resource. For example, to check if useralicecan list pods in namespacedev:kubectl auth can-i list pods -n dev --as alice
For a service account, use
--as=system:serviceaccount:dev:sa-name. This command returnsyesorno. To check all verbs for a resource, you can loop over verbs. - Audit service accounts specifically. Service accounts are often overlooked. List all service accounts and their associated rolebindings:
kubectl get serviceaccounts -A
Then for each SA, find bindings using the subject name
system:serviceaccount:<namespace>:<name>. - Look for overly permissive bindings. Pay special attention to bindings to
cluster-admin,admin,edit, orviewdefault clusterroles. Also check for wildcard verbs (*) and resources (*) in custom roles. Usekubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin")'to see who is cluster-admin. - Generate a report. Compile your findings into a spreadsheet or document. For each subject, list the roles and the specific permissions. You can use
kubectl get rolebindings -A -o json | jq -r '.items[] | [.metadata.namespace, .metadata.name, .subjects[].name, .roleRef.name] | @tsv'to get a tab-separated list.
Common Mistakes
- Forgetting about groups. Users may be part of groups that grant permissions. Always check group bindings, not just individual users.
- Ignoring aggregation. Some ClusterRoles use
aggregationRuleto combine other ClusterRoles. When you list rules, you must expand aggregated roles manually;kubectl get clusterroleshows the selector, not the final rules. - Assuming namespace roles don’t affect other namespaces. RoleBindings are scoped to a namespace, but ClusterRoleBindings apply cluster-wide. A subject can have both.
- Not considering system:authenticated and system:unauthenticated. These groups apply to all authenticated (or unauthenticated) users. Check bindings to these groups.
- Only checking get/list. Permissions include create, update, patch, delete, and others. Make sure you audit all verbs.
Tips
- Use
kubectl get rolebindings -A -o yamlto see the full structure, which is often easier to read than JSON. - For a quick high-level view, use
kubectl describe clusterrolebindingandkubectl describe rolebinding -n <ns>. - Install
kubectl-who-canplugin:kubectl krew install who-can. Then runkubectl who-can get podsto see who can get pods across all namespaces. - Automate with a script that loops over all subjects and roles. Use
jqto parse JSON output. - Regularly audit RBAC after any changes to roles or bindings. Consider using a CI/CD pipeline to run a script that checks for risky permissions.
Troubleshooting
- Permission denied when listing RBAC objects. You need at least
getandliston roles, rolebindings, clusterroles, and clusterrolebindings. If you can’t get these, ask your cluster admin for a read-only role. - kubectl auth can-i returns “no” but you expect “yes”. Double-check the subject name. For users, it must match the username exactly (e.g., from the certificate CN). For service accounts, use the full
system:serviceaccount:<ns>:<name>format. Also check if the subject is part of a group that has the permission. - Aggregated ClusterRoles are confusing. To expand them, look at the
aggregationRulefield and then fetch the ClusterRoles that match the label selector. You can usekubectl get clusterroles -l <selector>to list them. - Large clusters with many bindings. Use
kubectl get ... -o jsonand process withjqto avoid hitting terminal limits. Consider writing a script to output a CSV. - Subjects not appearing in bindings. Remember that users can be authenticated via OIDC or other providers, and they may have permissions through the
system:authenticatedgroup. Check bindings to that group.
Frequently Asked Questions
How do I find out what a specific user can do?
Use kubectl auth can-i --list --as <username> to see all permissions for that user. This is the quickest way to get a comprehensive view.
What is the difference between Role and ClusterRole?
A Role grants permissions within a specific namespace, while a ClusterRole grants permissions cluster-wide (or across all namespaces when bound via RoleBinding). ClusterRoles can also be used for non-namespaced resources like nodes.
How do I audit service accounts?
List all service accounts with kubectl get sa -A, then for each SA, check rolebindings that reference system:serviceaccount:<ns>:<name>. Use kubectl auth can-i --list --as system:serviceaccount:<ns>:<name> to see its permissions.
Why do I see permissions for system:authenticated group?
This group automatically includes all authenticated users. If a ClusterRoleBinding binds to this group, every user has those permissions. Audit these bindings carefully.
Can I audit RBAC without cluster-admin?
Yes, as long as you have read access to RBAC objects. If your role has get and list on roles, rolebindings, clusterroles, and clusterrolebindings, you can perform the audit.
How often should I audit RBAC?
Ideally, after any change to roles or bindings, and at least quarterly. Regular audits help catch privilege creep and misconfigurations.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.