> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Minimize Wildcard Use Roles And Cluster Roles

### More Info:

Kubernetes Roles and ClusterRoles provide access to resources based on sets of objects and actions that can be taken on those objects. It is possible to set either of these to be the wildcard \* which matches all items.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* APRA CPS 234 (Australia)
* BSI C5 (Germany)
* Brazil LGPD
* CCPA / CPRA (California)
* CIS Critical Security Controls v8
* CIS EKS
* 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

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **List all Roles and ClusterRoles that use wildcards**
           * Run on: any machine with kubectl access
           ```bash theme={null}
           kubectl get roles --all-namespaces -o json | jq '
             .items[] | select(
               .rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
             ) | {kind, metadata: {name, namespace}, rules}' | less

           kubectl get clusterroles -o json | jq '
             .items[] | select(
               .rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
             ) | {kind, metadata: {name}, rules}' | less
           ```

        2. **For each identified Role, export the definition for review/editing**
           * Run on: any machine with kubectl access
           * Example for a namespaced Role (replace values as needed):
           ```bash theme={null}
           kubectl get role <role-name> -n <role-namespace> -o yaml > /tmp/role-<role-name>.yaml
           ```
           * Open the file in an editor and replace `*` in `rules[].verbs`, `rules[].resources`, and `rules[].apiGroups` with the minimal explicit lists required for that Role’s purpose (for example, replace `verbs: ["*"]` with `verbs: ["get","list","watch"]`, and similarly for `resources` and `apiGroups`).

        3. **For each identified ClusterRole, export the definition for review/editing**
           * Run on: any machine with kubectl access
           * Example for a ClusterRole:
           ```bash theme={null}
           kubectl get clusterrole <clusterrole-name> -o yaml > /tmp/clusterrole-<clusterrole-name>.yaml
           ```
           * Edit the file to replace any `*` in `rules[].verbs`, `rules[].resources`, and `rules[].apiGroups` with the narrowest explicit sets needed. Be especially careful with default or system ClusterRoles that may be relied upon by the cluster or add-ons; if they are managed by the platform or an operator, prefer creating a new, custom ClusterRole instead of modifying the managed one.

        4. **(Optional but recommended) Create new, minimal roles instead of broadening existing system roles**
           * Run on: any machine with kubectl access
           * If a system or shared ClusterRole currently uses wildcards, consider:
             1. Leaving the original ClusterRole unchanged.
             2. Creating a new, minimal ClusterRole in a separate manifest file with only the needed verbs, resources, and apiGroups.
             3. Updating RoleBindings/ClusterRoleBindings to point to the new minimal role instead of the wildcard-based one. For example, edit the binding:
             ```bash theme={null}
             kubectl edit clusterrolebinding <binding-name>
             ```
             and change the `roleRef.name` to your new ClusterRole. Save and exit.

        5. **Apply the edited Role and ClusterRole manifests back to the cluster**
           * Run on: any machine with kubectl access
           * For each edited Role file:
           ```bash theme={null}
           kubectl apply -f /tmp/role-<role-name>.yaml
           ```
           * For each edited ClusterRole file:
           ```bash theme={null}
           kubectl apply -f /tmp/clusterrole-<clusterrole-name>.yaml
           ```

        6. **Verification: confirm that no wildcards remain in Roles or ClusterRoles**
           * Run on: any machine with kubectl access
           ```bash theme={null}
           wildcards=$(kubectl get roles --all-namespaces -o json | jq '
             .items[] | select(
               .rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
             )' | wc -l)

           wildcards_clusterroles=$(kubectl get clusterroles -o json | jq '
             .items[] | select(
               .rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
             )' | wc -l)

           total=$((wildcards + wildcards_clusterroles))

           if [ "$total" -gt 0 ]; then
             echo "wildcards_present"
           else
             echo "no_wildcards_in_roles_or_clusterroles"
           fi
           ```
      </Accordion>

      <Accordion title="Using kubectl">
        On any machine with kubectl access:

        1. Identify ClusterRoles using wildcards

        ```bash theme={null}
        kubectl get clusterroles -o json | jq '
          .items[] | select(
            .rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
          ) | .metadata.name' -r
        ```

        2. Inspect each offending ClusterRole
           Replace `<clusterrole-name>` with a name from the previous output:

        ```bash theme={null}
        kubectl get clusterrole <clusterrole-name> -o yaml > /tmp/clusterrole-<clusterrole-name>.yaml
        ```

        3. Edit the manifest to replace wildcards\
           Open the file and replace `*` in `verbs`, `resources`, and `apiGroups` with explicit values appropriate for your use case, for example:

        Before:

        ```yaml theme={null}
        rules:
          - apiGroups: ["*"]
            resources: ["*"]
            verbs: ["*"]
        ```

        After (example – adjust to your needs):

        ```yaml theme={null}
        rules:
          - apiGroups: [""]
            resources:
              - pods
              - pods/log
            verbs:
              - get
              - list
              - watch
        ```

        4. Apply the updated ClusterRole

        ```bash theme={null}
        kubectl apply -f /tmp/clusterrole-<clusterrole-name>.yaml
        ```

        Repeat steps 2–4 for each ClusterRole listed in step 1.

        5. (If Roles are also affected) Repeat for Roles
           List Roles with wildcards:

        ```bash theme={null}
        kubectl get roles --all-namespaces -o json | jq '
          .items[] | select(
            .rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
          ) | "\(.metadata.namespace) \(.metadata.name)"' -r
        ```

        Export, edit, and apply each Role similarly:

        ```bash theme={null}
        kubectl get role <role-name> -n <namespace> -o yaml > /tmp/role-<namespace>-<role-name>.yaml
        kubectl apply -f /tmp/role-<namespace>-<role-name>.yaml
        ```

        6. Verification
           Run the benchmark audit logic again; if nothing is printed, wildcards are no longer present:

        ```bash theme={null}
        wildcards=$(kubectl get roles --all-namespaces -o json | jq '
          .items[] | select(
            .rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
          )' | wc -l)

        wildcards_clusterroles=$(kubectl get clusterroles -o json | jq '
          .items[] | select(
            .rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
          )' | wc -l)

        total=$((wildcards + wildcards_clusterroles))

        if [ "$total" -gt 0 ]; then
          echo "wildcards_present"
        else
          echo "no_wildcards_in_roles_or_clusterroles"
        fi
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        set -euo pipefail

        # PURPOSE:
        # Identify Roles and ClusterRoles that use wildcards ("*") in rules and
        # export them for manual, least-privilege review, then verify the presence
        # of remaining wildcards.
        #
        # This script does NOT auto-edit RBAC, because the correct non-wildcard verbs,
        # resources and apiGroups are application‑specific and must be chosen by an
        # administrator. It is safe to re-run.

        # RUN ON: Any machine with kubectl access and jq installed.

        timestamp="$(date +%Y%m%d-%H%M%S)"
        outdir="rbac-wildcard-review-${timestamp}"
        mkdir -p "${outdir}"

        echo "=== Exporting Roles with wildcard usage for review into: ${outdir} ==="

        # Roles with wildcards
        kubectl get roles --all-namespaces -o json | \
          jq '
            .items[]
            | select(
                .rules[]? |
                (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
              )
          ' > "${outdir}/roles-with-wildcards.json"

        # ClusterRoles with wildcards
        kubectl get clusterroles -o json | \
          jq '
            .items[]
            | select(
                .rules[]? |
                (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
              )
          ' > "${outdir}/clusterroles-with-wildcards.json"

        echo "=== Summary of objects using wildcards (for manual hardening) ==="
        echo "Roles:"
        jq -r '.[].metadata | "\(.namespace)/\(.name)"' "${outdir}/roles-with-wildcards.json" 2>/dev/null || echo "  (none)"
        echo "ClusterRoles:"
        jq -r '.[].metadata.name' "${outdir}/clusterroles-with-wildcards.json" 2>/dev/null || echo "  (none)"

        cat <<'EOF'

        NEXT STEPS (manual, per benchmark remediation):
        1. For each Role or ClusterRole listed above, open it for editing, for example:
           - Role:
               kubectl -n <namespace> edit role <name>
           - ClusterRole:
               kubectl edit clusterrole <name>

        2. In .rules[], replace any "*" in:
           - verbs        (e.g., ["get","list","watch"] instead of ["*"])
           - resources    (e.g., ["pods","deployments"] instead of ["*"])
           - apiGroups    (e.g., ["","apps"] instead of ["*"])
           with the minimum specific values needed by the workloads.

        3. Save and exit the editor to apply the updated RBAC objects.

        This process is intentionally manual because the correct least-privilege set of
        verbs/resources/apiGroups depends on your applications and policies.
        EOF

        echo
        echo "=== Verification: checking for remaining wildcard usage (same logic as audit) ==="

        wildcards=$(kubectl get roles --all-namespaces -o json | jq '
          .items[] | select(
            .rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
          )' | wc -l | tr -d ' ')

        wildcards_clusterroles=$(kubectl get clusterroles -o json | jq '
          .items[] | select(
            .rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
          )' | wc -l | tr -d ' ')

        total=$((wildcards + wildcards_clusterroles))

        if [ "$total" -gt 0 ]; then
          echo "wildcards_present: ${total} Role(s)/ClusterRole(s) still contain wildcards."
          echo "Review and edit remaining items until this reports zero."
        else
          echo "No wildcard usage detected in Roles or ClusterRoles."
        fi
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
