> ## 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 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 GKE
* 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, namespace: .metadata.namespace, name: .metadata.name, rules: .rules}' | less

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

        2. For each Role with wildcards, decide the minimum required permissions
           * For each Role listed above, determine:
             * The exact verbs actually needed (e.g., `get`, `list`, `watch`, `create`, `update`, `patch`, `delete`).
             * The exact resources (e.g., `pods`, `deployments`, `configmaps`) and apiGroups (e.g., `""`, `"apps"`) required.
           * Document these decisions before editing so you can justify that wildcards are required only where strictly necessary (if ever).

        3. Edit Roles to replace wildcards with specific verbs/resources/apiGroups
           * Run on: any machine with kubectl access
           * For each affected Role, edit it interactively:
           ```bash theme={null}
           kubectl edit role <role-name> -n <namespace>
           ```
           * In the opened YAML, locate `.rules` and replace:
             * `verbs: ["*"]` with an explicit list, for example:
               ```yaml theme={null}
               verbs: ["get", "list", "watch"]
               ```
             * `resources: ["*"]` with only needed resources, for example:
               ```yaml theme={null}
               resources: ["pods", "pods/log"]
               ```
             * `apiGroups: ["*"]` with specific groups, for example:
               ```yaml theme={null}
               apiGroups: [""]
               ```
           * Save and exit the editor to apply the change.

        4. Edit ClusterRoles to replace wildcards with specific verbs/resources/apiGroups
           * Run on: any machine with kubectl access
           * For each affected ClusterRole, edit it interactively:
           ```bash theme={null}
           kubectl edit clusterrole <clusterrole-name>
           ```
           * Adjust `.rules` the same way as in step 3, replacing any `*` in `verbs`, `resources`, or `apiGroups` with the minimum specific values needed.
           * For built‑in or add‑on ClusterRoles managed by the platform or an operator, review carefully; if changing them might break functionality, prefer:
             * Creating a new, more restrictive ClusterRole.
             * Updating your RoleBindings/ClusterRoleBindings to use the new role instead of the wildcarded one.

        5. For GitOps or manifest‑managed clusters, update source manifests
           * Run on: any machine with access to your IaC/Git repo
           * Locate Role and ClusterRole definitions containing wildcards, for example with:
           ```bash theme={null}
           grep -R --include='*.yaml' -n 'verbs: \["*"\]\|resources: \["*"\]\|apiGroups: \["*"\]' /absolute/path/to/your/manifests
           ```
           * Edit those YAML files to match the changes you applied via `kubectl edit` (specific verbs/resources/apiGroups).
           * Commit and push the changes so the GitOps/IaC source of truth matches the live cluster.

        6. Verification: confirm wildcards are no longer present
           * 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">
        1. Identify the specific ClusterRoles using wildcards\
           Run on: any machine with kubectl access

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

        For each ClusterRole name returned (example: `example-clusterrole`), proceed with the next steps.

        2. Export the existing ClusterRole manifest for editing\
           Run on: any machine with kubectl access

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

        3. Edit the manifest to remove wildcards\
           Open `example-clusterrole.yaml` in an editor and, under `.rules`, replace each `*` with the minimum required specific values. For example, change:

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

        to something like:

        ```yaml theme={null}
        rules:
        - apiGroups: [""]              # core API group
          resources:
            - pods
            - services
          verbs:
            - get
            - list
            - watch
        ```

        Adjust `apiGroups`, `resources`, and `verbs` to the least-privilege set actually needed for that ClusterRole.

        4. Apply the updated ClusterRole\
           Run on: any machine with kubectl access

        ```bash theme={null}
        kubectl apply -f example-clusterrole.yaml
        ```

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

        5. 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="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Minimize wildcard use in Roles and ClusterRoles (CIS GKE 4.1.3)
        #
        # Scope: run on any machine with kubectl access and jq installed.
        # This script is ASSISTED / SEMI-AUTOMATIC:
        # - It does NOT blindly rewrite RBAC.
        # - It finds Roles/ClusterRoles using wildcards, exports them, and opens them for
        #   manual, least-privilege editing, then reapplies them.
        #
        # Idempotency:
        # - Safe to re-run; it will re-check, re-export, and allow re-editing the same objects.
        # - Only 'kubectl apply' is used; no deletes.
        #
        # OPERATIONAL NOTE:
        # - Changing RBAC may immediately remove access from users/service accounts.
        # - Carefully review each object and test access for affected subjects.

        set -euo pipefail

        # CONFIG
        OUTPUT_DIR="${PWD}/rbac-wildcards-$(date +%Y%m%d-%H%M%S)"
        EDITOR_CMD="${EDITOR:-vi}"   # Change to your preferred editor if desired

        mkdir -p "${OUTPUT_DIR}/roles" "${OUTPUT_DIR}/clusterroles"

        echo "Discovering Roles and ClusterRoles that use wildcards in rules..."

        # Function: list wildcard RBAC objects in JSON
        list_wildcard_objects() {
          local kind="$1"   # roles or clusterroles
          if [[ "${kind}" == "roles" ]]; then
            kubectl get roles --all-namespaces -o json
          else
            kubectl get clusterroles -o json
          fi
        }

        # Extract Roles with wildcards
        roles_json="$(list_wildcard_objects roles || echo '{}')"
        clusterroles_json="$(list_wildcard_objects clusterroles || echo '{}')"

        roles_with_wildcards=$(echo "${roles_json}" | jq -r '
          .items[]? |
          select(.rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")) |
          "\(.metadata.namespace),\(.metadata.name)"
        ')

        clusterroles_with_wildcards=$(echo "${clusterroles_json}" | jq -r '
          .items[]? |
          select(.rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*")) |
          .metadata.name
        ')

        if [[ -z "${roles_with_wildcards}" && -z "${clusterroles_with_wildcards}" ]]; then
          echo "No Roles or ClusterRoles with wildcard rules found."
          exit 0
        fi

        echo "Exporting affected Roles and ClusterRoles to ${OUTPUT_DIR} for review..."

        # Export Roles
        if [[ -n "${roles_with_wildcards}" ]]; then
          echo "Roles with wildcards:"
          echo "${roles_with_wildcards}" | while IFS=, read -r ns name; do
            echo "  - ${ns}/${name}"
            out="${OUTPUT_DIR}/roles/${ns}__${name}.yaml"
            kubectl get role "${name}" -n "${ns}" -o yaml > "${out}"
          done
        else
          echo "No roles with wildcards."
        fi

        # Export ClusterRoles
        if [[ -n "${clusterroles_with_wildcards}" ]]; then
          echo "ClusterRoles with wildcards:"
          echo "${clusterroles_with_wildcards}" | while read -r name; do
            [[ -z "${name}" ]] && continue
            echo "  - ${name}"
            out="${OUTPUT_DIR}/clusterroles/${name}.yaml"
            kubectl get clusterrole "${name}" -o yaml > "${out}"
          done
        else
          echo "No clusterroles with wildcards."
        fi

        cat <<'EOF'

        MANUAL REMEDIATION REQUIRED (per RBAC best practices):
        - For each exported YAML in the output directory:
          * Identify any occurrence of:
              verbs: ["*"] or verbs: - "*"
              resources: ["*"] or resources: - "*"
              apiGroups: ["*"] or apiGroups: - "*"
          * Replace "*" with the minimal explicit list of verbs/resources/apiGroups
            actually required for that Role/ClusterRole.
          * Be cautious: over-restricting may break workloads; under-restricting defeats this control.

        You will now be dropped into an editor, one file at a time, to make those changes.
        Save and exit the editor to move to the next file.

        EOF

        read -r -p "Press Enter to start editing affected YAML files, or Ctrl+C to abort..."

        # Edit and apply Roles
        for f in "${OUTPUT_DIR}/roles/"*.yaml; do
          [[ ! -e "${f}" ]] && break
          echo "Editing Role manifest: ${f}"
          "${EDITOR_CMD}" "${f}"

          echo "Applying Role manifest: ${f}"
          kubectl apply -f "${f}"
        done

        # Edit and apply ClusterRoles
        for f in "${OUTPUT_DIR}/clusterroles/"*.yaml; do
          [[ ! -e "${f}" ]] && break
          echo "Editing ClusterRole manifest: ${f}"
          "${EDITOR_CMD}" "${f}"

          echo "Applying ClusterRole manifest: ${f}"
          kubectl apply -f "${f}"
        done

        echo "Re-running wildcard audit to verify remediation..."

        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"
          echo "Remaining objects with wildcards detected: ${total}"
          echo "Re-run the script and further tighten RBAC, or manually inspect with:"
          echo "  kubectl get roles --all-namespaces -o yaml | grep -n \"- \\\"*\\\"\" -n"
          echo "  kubectl get clusterroles -o yaml | grep -n \"- \\\"*\\\"\" -n"
          exit 1
        fi

        echo "No remaining Roles or ClusterRoles with wildcard verbs/resources/apiGroups."
        echo "Remediation for CIS GKE 4.1.3 appears complete."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
