Ensure Cluster Admin Role Is Only Used Where Required
More Info:
The RBAC role cluster-admin provides wide-ranging powers over the environment and should be used only where and when needed.
Risk Level
High
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS Critical Security Controls v8
- CIS OKE
- CMMC 2.0
- CSA Cloud Controls Matrix v4
- DPDPA
- Digital Operational Resilience Act (EU)
- Essential 8
- ISO/IEC 27017
- ISO/IEC 27018
- ISO/IEC 27701
- KSA PDPL
- MAS Technology Risk Management (Singapore)
- MITRE ATT&CK (Cloud)
- NIS2 Directive
- NIST SP 800-171
- NYDFS 23 NYCRR 500
- SWIFT Customer Security Controls Framework
- Sarbanes-Oxley IT General Controls
- Securities and Exchange Board of India (SEBI) - Cloud Security Adoption Framework
- UK NCSC Cyber Assessment Framework
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
List all cluster-admin bindings and their subjects
- Run on: any machine with kubectl access
kubectl get clusterrolebindings -o jsonpath='{range .items[?(@.roleRef.name=="cluster-admin")]}{.metadata.name}{"\n"}{range .subjects[*]} {"kind:"}{.kind}{" name:"}{.name}{" namespace:"}{.namespace}{"\n"}{end}{"---\n"}{end}'Save the output; it shows exactly who/what is bound to
cluster-admin. -
Assess necessity of cluster-admin for each subject
For each subject (User/Group/ServiceAccount) in the output:- Determine what application, team, or automation owns it.
- Ask/decide what operations it actually needs (e.g., namespace-scoped, specific CRDs, read-only vs write).
Document whether full cluster-wide admin is justified or whether a reduced-scope role would be sufficient.
-
Inspect current permissions and usage context
- Show the binding definition for detailed review:
# Replace BINDING_NAME with an actual name from step 1kubectl get clusterrolebinding BINDING_NAME -o yaml
- Optionally, check what clusterroles are already available that might fit better:
kubectl get clusterroles
Use this to determine if you can map the subject to an existing lower-privilege ClusterRole/Role or if you must create a custom one.
- Show the binding definition for detailed review:
-
Design and apply least-privilege replacements (if needed)
For each subject that does not truly require cluster-admin:- Create or choose an appropriate
RoleorClusterRolethat grants only the required permissions. - Bind the subject to it with a
RoleBinding(namespace-scoped need) orClusterRoleBinding(cluster-wide but limited actions). For example:# Example: bind a user to a more restricted clusterrolekubectl create clusterrolebinding limited-admin-binding \--clusterrole=<lower-privilege-clusterrole-name> \--user=<user-identifier>
Confirm the new binding reflects the intended scope and verbs before proceeding.
- Create or choose an appropriate
-
Remove unneeded cluster-admin bindings
Once a subject has appropriate replacement bindings and you are confident operations continue to work:- Delete the unnecessary cluster-admin binding(s).
- Run on: any machine with kubectl access
# Replace BINDING_NAME with the specific clusterrolebinding to removekubectl delete clusterrolebinding BINDING_NAME
Do this incrementally, prioritizing clearly non-admin use cases; leave truly administrative identities bound to cluster-admin if justified.
-
Re-verify cluster-admin usage and document exceptions
- Re-run the evidence command:
kubectl get clusterrolebindings -o jsonpath='{range .items[?(@.roleRef.name=="cluster-admin")]}{.metadata.name}{"\n"}{range .subjects[*]} {"kind:"}{.kind}{" name:"}{.name}{" namespace:"}{.namespace}{"\n"}{end}{"---\n"}{end}'
- Confirm that only identities with a clear, documented operational need remain bound to
cluster-admin, and record these exceptions (who, why, and approval) for future audits.
- Re-run the evidence command:
Using kubectl
Using kubectl
Run these commands from any machine with kubectl access.
- List all ClusterRoleBindings that grant
cluster-admin
kubectl get clusterrolebindings -o jsonpath='{range .items[?(@.roleRef.kind=="ClusterRole" && @.roleRef.name=="cluster-admin")]}{.metadata.name}{"\n"}{end}'
If this prints one or more names, those bindings are candidates for review. Each name is a binding that grants full cluster‑admin privileges.
- Inspect each identified ClusterRoleBinding in detail
Replace <binding-name> with one name from the previous command.
kubectl get clusterrolebinding <binding-name> -o yaml
Review the subjects section:
- Problem indicators:
kind: Userorkind: Groupreferring to broad groups such as:system:authenticatedsystem:unauthenticated- large IdP groups (e.g.
Everyone,Developers,All-Engineers)
kind: ServiceAccountreferring to:- default service accounts (e.g.
defaultin many namespaces) - application service accounts that do not truly need full cluster control
- default service accounts (e.g.
- Multiple, diverse subjects on a single
cluster-adminbinding, suggesting it’s used as a catch‑all.
These are strong signals that cluster-admin is over‑used and should be replaced with narrower, task‑specific roles.
- Summarize which subjects have
cluster-admin
To quickly see just subjects and names:
kubectl get clusterrolebindings -o json \
| jq -r '.items[]
| select(.roleRef.kind=="ClusterRole" and .roleRef.name=="cluster-admin")
| "\(.metadata.name):\n" +
( .subjects[]? | " - kind: \(.kind) | name: \(.name) | namespace: \(.namespace // "-") | apiGroup: \(.apiGroup // "-")" )'
Review for:
- Bindings used as “global admin for everyone”.
- Service accounts used by workloads rather than by cluster operators.
These outputs tell you who is getting cluster-admin; a human must decide which bindings are justified and where to replace them with less‑privileged roles.
Automation
#!/usr/bin/env bash
#
# Report all ClusterRoleBindings that grant cluster-admin
# and list their subjects for review.
#
# Run on: any machine with kubectl access and correct context
# Usage: ./report-cluster-admin-bindings.sh
set -euo pipefail
echo "=== ClusterRoleBindings granting cluster-admin ==="
echo
# 1) List all ClusterRoleBindings that reference cluster-admin
kubectl get clusterrolebindings -o json \
| jq -r '
.items[]
| select(.roleRef.kind=="ClusterRole" and .roleRef.name=="cluster-admin")
| {
name: .metadata.name,
roleKind: .roleRef.kind,
roleName: .roleRef.name,
subjects: (
.subjects // []
| map({
kind: .kind,
name: .name,
namespace: (.namespace // ""),
apiGroup: (.apiGroup // "")
})
)
}
' | jq -c '.'
echo
echo "=== Human-readable summary ==="
echo
kubectl get clusterrolebindings -o json \
| jq -r '
.items[]
| select(.roleRef.kind=="ClusterRole" and .roleRef.name=="cluster-admin")
| (
"ClusterRoleBinding: " + .metadata.name
+ "\n RoleRef: " + .roleRef.kind + "/" + .roleRef.name
+ (
if (.subjects // [] | length) == 0
then "\n Subjects: (none)"
else (
"\n Subjects:"
+ (
.subjects // []
| map(
"\n - kind: " + .kind
+ ", name: " + .name
+ (if .namespace then ", namespace: " + .namespace else "" end)
+ (if .apiGroup then ", apiGroup: " + .apiGroup else "" end)
)
| join("")
)
)
)
+ "\n"
)
'
echo "=== Notes ==="
cat <<'EOF'
Each listed ClusterRoleBinding grants full cluster-admin privileges to its subjects.
What indicates a potential problem:
- Any binding where the subject is:
- An individual User that does not require full cluster-wide admin.
- A Group that includes many or generic users (e.g., 'developers', 'default', 'system:authenticated').
- A ServiceAccount used by a specific application or namespace-scoped component.
- A broad or unclear identity from an external IdP (e.g., 'everyone', '*', or large SSO groups).
Review actions (manual, per binding/subject):
- Confirm who/what the subject is and why they need cluster-admin.
- If they only need limited permissions, design/create a narrower Role or ClusterRole.
- Rebind them to that lesser-privileged role.
- Then delete the cluster-admin ClusterRoleBinding if it is no longer needed:
kubectl delete clusterrolebinding <binding-name>
This review and adjustment step is manual; it cannot be safely fully automated.
EOF
Interpreting output
- If the script prints no ClusterRoleBindings in the summary, the check is likely passing: no subjects are granted
cluster-admin. - Any ClusterRoleBinding shown is a candidate for review; treat especially as problematic when:
- The subject is a generic group (e.g.,
system:authenticated, large SSO groups). - The subject is an app/service account that only requires namespace or limited actions.
- The purpose of the binding is unclear to the cluster owner.
- The subject is a generic group (e.g.,