> ## 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 In Roles And ClusterRoles

### More Info:

Wildcards in RBAC verbs, resources or apiGroups grant broad, hard-to-audit permissions. They should be replaced with explicit objects and actions.

### Risk Level

Critical

### Address

Security

### Compliance Standards

* CIS GKE

### 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 -r '
             .items[] |
             select(.rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")) |
             "ROLE " + .metadata.namespace + "/" + .metadata.name
           '

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

        2. For each reported ClusterRole, export it to a manifest for review and editing (example for one ClusterRole named `example-clusterrole`):
           ```bash theme={null}
           kubectl get clusterrole example-clusterrole -o yaml > /tmp/example-clusterrole.yaml
           ```

        3. Manually review `/tmp/example-clusterrole.yaml` and replace wildcard entries with explicit values:
           * Replace `verbs: ["*"]` or `- "*"` with an explicit verb list such as `["get","list","watch","create","update","patch","delete"]` as needed.
           * Replace `resources: ["*"]` with only the required resource names, for example `["pods","deployments"]`.
           * Replace `apiGroups: ["*"]` with the specific API groups needed, for example `["","apps"]`.
           * Remove any rule entries that are not actually required for the workloads using this ClusterRole.

        4. Apply the edited ClusterRole back to the cluster (example):
           ```bash theme={null}
           kubectl apply -f /tmp/example-clusterrole.yaml
           ```

        5. If any wildcard-bearing Role objects (namespaced) were reported, repeat steps 2–4 for those, substituting `kubectl get role -n <namespace> <name> -o yaml > /tmp/<name>.yaml` and `kubectl apply -f /tmp/<name>.yaml`.

        6. Verification (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">
        This control is MANUAL. There is no one-shot kubectl fix, because each wildcard must be evaluated and replaced with explicit permissions case‑by‑case.

        Below are practical review steps and kubectl commands to help you identify, inspect, and update ClusterRoles.

        ### 1. Identify ClusterRoles using wildcards

        Run on: any machine with kubectl access.

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

        Optionally, see full definitions:

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

        ### 2. Inspect an individual ClusterRole

        Pick a ClusterRole name from the list and inspect it:

        ```bash theme={null}
        kubectl get clusterrole <CLUSTERROLE_NAME> -o yaml
        ```

        Decision guidance during review:

        * **Is this a built‑in or system role?**
          * Names like `cluster-admin`, `system:*`, or cloud‑provider managed roles often legitimately use wildcards and are relied upon by the platform. Avoid changing them unless you fully understand the impact.
        * **Is this a custom role for an application or team?**
          * Prefer replacing `*` in `verbs`, `resources`, or `apiGroups` with just the specific items actually needed.
        * **Is the role even used?**
          * Check ClusterRoleBindings to see if it’s bound to any subjects. If unused, consider deletion instead of tightening.

        List bindings that use a given ClusterRole:

        ```bash theme={null}
        kubectl get clusterrolebindings -o json | jq '
          .items[]
          | select(.roleRef.kind=="ClusterRole" and .roleRef.name=="<CLUSTERROLE_NAME>")
          | {name: .metadata.name, subjects: .subjects}'
        ```

        ### 3. Edit a ClusterRole to remove wildcards

        Run on: any machine with kubectl access.

        Interactive edit:

        ```bash theme={null}
        kubectl edit clusterrole <CLUSTERROLE_NAME>
        ```

        In the opened YAML:

        * Replace `verbs: ["*"]` or `verbs: - "*"`
          * With an explicit list, e.g.:

            ```yaml theme={null}
            verbs:
              - get
              - list
              - watch
              - create
              - update
              - patch
              - delete
            ```

          * Choose only the verbs actually required by the workload.

        * Replace `resources: ["*"]` or `resources: - "*"`
          * With explicit resources, for example:

            ```yaml theme={null}
            resources:
              - pods
              - pods/log
              - deployments
              - configmaps
            ```

        * Replace `apiGroups: ["*"]` or `apiGroups: - "*"`
          * With specific API groups, for example:

            ```yaml theme={null}
            apiGroups:
              - ""
              - apps
              - batch
            ```

        Repeat for each rule under `rules:` that uses `*`.

        Declarative approach using manifests (preferred for GitOps/IaC):

        1. Export the current role to a file:

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

        2. Edit the file with your editor, replacing `*` as described above.

        3. Apply the updated manifest:

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

        Operational impact: tightening a ClusterRole can break workloads or tooling that previously relied on broad access. After each change, confirm that affected applications and users still function as expected.

        ### 4. Optionally remove unused overly‑broad ClusterRoles

        If you confirmed a ClusterRole has no bindings and is not needed:

        ```bash theme={null}
        kubectl delete clusterrole <CLUSTERROLE_NAME>
        ```

        ### 5. Verification

        Re-run the audit for ClusterRoles to confirm wildcard usage has been eliminated or intentionally minimized:

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

        echo "clusterroles_with_wildcards=${wildcards_clusterroles}"
        ```

        You can also list remaining offending ClusterRoles by name:

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

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Purpose:
        #   Assist review of wildcard use in ClusterRoles by exporting and listing
        #   them for manual editing, then verifying reduction of wildcards.
        #
        # Scope:
        #   Run on any machine with kubectl access to the cluster.
        #
        # NOTES:
        #   - This check is MANUAL in the benchmark: there is no safe, generic way
        #     to automatically replace "*" with specific verbs/resources/apiGroups.
        #   - This script does NOT change any RBAC objects. It only:
        #       * Identifies ClusterRoles using wildcards
        #       * Exports them into separate YAMLs for human review/edit
        #       * Helps you re-apply your edited manifests
        #       * Verifies wildcard usage afterwards
        #
        # Requirements:
        #   - kubectl installed and configured with sufficient permissions
        #   - jq installed

        set -euo pipefail

        OUT_DIR="${OUT_DIR:-./clusterrole-wildcards-$(date +%Y%m%d%H%M%S)}"

        echo "[*] Detecting ClusterRoles that use wildcards in verbs, resources, or apiGroups..."

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

        if [[ -z "${wildcards_clusterroles_json}" ]]; then
          echo "[*] No ClusterRoles with wildcard verbs/resources/apiGroups found."
          exit 0
        fi

        mkdir -p "${OUT_DIR}"

        echo "${wildcards_clusterroles_json}" | jq -r '.metadata.name' | sort -u > "${OUT_DIR}/clusterroles_with_wildcards.txt"

        echo "[*] ClusterRoles with wildcards:"
        cat "${OUT_DIR}/clusterroles_with_wildcards.txt"
        echo
        echo "[*] Exporting each affected ClusterRole to individual YAML manifests in: ${OUT_DIR}"

        # Export each affected ClusterRole
        while read -r cr_name; do
          if [[ -z "${cr_name}" ]]; then
            continue
          fi
          out_file="${OUT_DIR}/clusterrole-${cr_name}.yaml"
          echo "  - Exporting ClusterRole/${cr_name} -> ${out_file}"
          kubectl get clusterrole "${cr_name}" -o yaml > "${out_file}"
        done < "${OUT_DIR}/clusterroles_with_wildcards.txt"

        cat <<'EOF'

        [MANUAL ACTION REQUIRED]

        1) Review each exported ClusterRole manifest in the output directory.
           For each rule, where possible:
             - Replace verbs: ["*"] with an explicit list, e.g. ["get","list","watch"]
             - Replace resources: ["*"] with explicit resources, e.g. ["pods","deployments"]
             - Replace apiGroups: ["*"] with only the required apiGroups, e.g. ["","apps"]

        2) Save your edited YAML files.

        3) To apply your edited ClusterRoles back to the cluster, run:

           # Replace <OUT_DIR> with the directory printed above
           kubectl apply -f <OUT_DIR>/

           (You can safely re-run this command; it is idempotent.)

        EOF

        read -rp "[?] Have you already edited the manifests and applied them? [y/N]: " CONFIRM
        CONFIRM=${CONFIRM:-n}

        if [[ "${CONFIRM}" =~ ^[Yy]$ ]]; then
          echo "[*] Verifying wildcard usage after your changes..."

          # Re-run the wildcard detection, but scoped to the previously affected ClusterRoles
          remaining=$(kubectl get clusterroles -o json | jq --argfile names "${OUT_DIR}/clusterroles_with_wildcards.txt" '
            .items[]
            | select(.metadata.name as $n | ($names | map(select(. == $n)) | length) > 0)
            | select(
                .rules[]?
                | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")
              )
            | .metadata.name
          ' | sort -u || true)

          if [[ -z "${remaining}" ]]; then
            echo "[*] Verification passed: no wildcards remain in the previously flagged ClusterRoles."
          else
            echo "[!] Verification found remaining wildcards in these ClusterRoles:"
            echo "${remaining}"
            echo "[!] Please re-check these manifests and further restrict wildcard use where possible."
          fi
        else
          echo "[*] Skipping verification because manifests have not been edited/applied yet."
          echo "[*] After you apply your changes, you can re-run this script to re-check."
        fi
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
