Skip to main content

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

Manual Steps
  1. 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.

  2. 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.
  3. Inspect current permissions and usage context

    • Show the binding definition for detailed review:
      # Replace BINDING_NAME with an actual name from step 1
      kubectl 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.

  4. Design and apply least-privilege replacements (if needed)
    For each subject that does not truly require cluster-admin:

    • Create or choose an appropriate Role or ClusterRole that grants only the required permissions.
    • Bind the subject to it with a RoleBinding (namespace-scoped need) or ClusterRoleBinding (cluster-wide but limited actions). For example:
      # Example: bind a user to a more restricted clusterrole
      kubectl 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.

  5. 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 remove
      kubectl delete clusterrolebinding BINDING_NAME

    Do this incrementally, prioritizing clearly non-admin use cases; leave truly administrative identities bound to cluster-admin if justified.

  6. 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.
Using kubectl

Using kubectl

Run these commands from any machine with kubectl access.

  1. 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.

  1. 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: User or kind: Group referring to broad groups such as:
      • system:authenticated
      • system:unauthenticated
      • large IdP groups (e.g. Everyone, Developers, All-Engineers)
    • kind: ServiceAccount referring to:
      • default service accounts (e.g. default in many namespaces)
      • application service accounts that do not truly need full cluster control
    • Multiple, diverse subjects on a single cluster-admin binding, 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.

  1. 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.

Additional Reading: