> ## 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 Access To Create Pods

### More Info:

The ability to create pods can be abused to run privileged workloads or escalate privileges. This permission should be restricted to only required service accounts.

### Risk Level

High

### Address

Security

### Compliance Standards

* CIS AKS

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **List all Roles/ClusterRoles that can create pods**\
           Run on any machine with kubectl access:
           ```bash theme={null}
           kubectl get clusterrole -o json \
             | jq -r '.items[]
               | select(.rules[]? 
                 | any(.apiGroups[]? == "" and .resources[]? == "pods" and .verbs[]? == "create"))
               | .metadata.name'

           kubectl get role --all-namespaces -o json \
             | jq -r '.items[]
               | select(.rules[]? 
                 | any(.apiGroups[]? == "" and .resources[]? == "pods" and .verbs[]? == "create"))
               | (.metadata.namespace + " " + .metadata.name)'
           ```

        2. **Review each identified Role/ClusterRole’s scope and necessity**\
           For each name from step 1, inspect full rules and annotations:
           ```bash theme={null}
           kubectl get clusterrole <clusterrole-name> -o yaml
           kubectl get role -n <namespace> <role-name> -o yaml
           ```
           Decide whether the subjects using this role truly need to create pods, or if they could use higher‑level abstractions (Deployments/Jobs) or narrower permissions instead.

        3. **Identify who is bound to these Roles/ClusterRoles**\
           For each Role/ClusterRole discovered, list RoleBindings/ClusterRoleBindings:
           ```bash theme={null}
           # ClusterRole bindings
           kubectl get clusterrolebindings -o json \
             | jq -r '.items[]
               | select(.roleRef.kind=="ClusterRole" and .roleRef.name=="<clusterrole-name>")
               | .metadata.name'

           # Role bindings in all namespaces
           kubectl get rolebindings --all-namespaces -o json \
             | jq -r '.items[]
               | select(.roleRef.kind=="Role" and .roleRef.name=="<role-name>" and .metadata.namespace=="<namespace>")
               | (.metadata.namespace + " " + .metadata.name)'
           ```
           Then inspect each binding to see which users/groups/serviceaccounts are granted pod creation:
           ```bash theme={null}
           kubectl get clusterrolebinding <binding-name> -o yaml
           kubectl get rolebinding -n <namespace> <binding-name> -o yaml
           ```

        4. **Decide and implement least-privilege changes**\
           For each combination of Role/ClusterRole and binding:
           * If pod creation is not required: remove `create` on `pods` from the role rules.
             ```bash theme={null}
             kubectl edit clusterrole <clusterrole-name>
             kubectl edit role -n <namespace> <role-name>
             ```
             In the editor, delete `create` from the `verbs` list for the `pods` resource, or remove the rule stanza entirely if no longer needed.
           * If some but not all subjects need this permission: create a new, narrowly scoped Role/ClusterRole just for those subjects, and update bindings so only those specific serviceaccounts/users/groups are bound to it.

        5. **Tighten or remove unnecessary bindings**\
           Where overly broad subjects are found (e.g., groups like `system:authenticated` or wildcard-like coverage):
           * Replace broad bindings with bindings to specific service accounts or users that actually require pod creation.
           * Remove RoleBindings/ClusterRoleBindings that are no longer needed:
             ```bash theme={null}
             kubectl delete clusterrolebinding <binding-name>
             kubectl delete rolebinding -n <namespace> <binding-name>
             ```

        6. **Verify that pod creation access is minimized**\
           Re-run the evidence commands to confirm only the intended Roles/ClusterRoles retain pod creation:
           ```bash theme={null}
           kubectl get clusterrole -o json | jq -r '.items[]
             | select(.rules[]? 
               | any(.apiGroups[]? == "" and .resources[]? == "pods" and .verbs[]? == "create"))
             | .metadata.name'

           kubectl get role --all-namespaces -o json | jq -r '.items[]
             | select(.rules[]? 
               | any(.apiGroups[]? == "" and .resources[]? == "pods" and .verbs[]? == "create"))
             | (.metadata.namespace + " " + .metadata.name)'
           ```
           Confirm that each remaining role with `create` on `pods` is intentionally required and bound only to the minimal set of subjects.
      </Accordion>

      <Accordion title="Using kubectl">
        ### Using kubectl

        Run the following from any machine with kubectl access.

        1. List all Roles/ClusterRoles that can create pods

        ```bash theme={null}
        kubectl get clusterrole -o json \
          | jq -r '.items[]
            | select(.rules[]? 
              | (.verbs[]? | contains("create")) 
              and (.resources[]? | contains("pods")))
            | .metadata.name' \
          | sort -u
        ```

        ```bash theme={null}
        kubectl get role --all-namespaces -o json \
          | jq -r '.items[]
            | select(.rules[]? 
              | (.verbs[]? | contains("create")) 
              and (.resources[]? | contains("pods")))
            | "\(.metadata.namespace)/\(.metadata.name)"' \
          | sort -u
        ```

        Problem indication: Any role/clusterrole appears here that is not clearly intended to create pods (for example, broad “admin”-style roles granted to many subjects, or generic application roles).

        2. Inspect detailed rules for each identified role

        For ClusterRoles (replace `<clusterrole-name>` with each name from step 1):

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

        For Roles (replace `<namespace>` and `<role-name>`):

        ```bash theme={null}
        kubectl get role -n <namespace> <role-name> -o yaml
        ```

        In the `rules` section, look for:

        * `resources: ["pods"]` (or including `pods`)
        * `verbs: ["create"]` (or including `create` or `*`)

        Problem indication:\
        Rules that allow `create` on `pods` (directly, via `*` verbs, or via `*` resources) tied to functions that do not strictly require pod creation, or overly broad rules (e.g., `verbs: ["*"]` or `resources: ["*"]`).

        3. See who is bound to these Roles/ClusterRoles

        For each ClusterRole:

        ```bash theme={null}
        kubectl get clusterrolebinding -o yaml \
          | yq '.items[]
            | select(.roleRef.kind == "ClusterRole" and .roleRef.name == "<clusterrole-name>")'
        ```

        For each namespaced Role:

        ```bash theme={null}
        kubectl get rolebinding -n <namespace> -o yaml \
          | yq '.items[]
            | select(.roleRef.kind == "Role" and .roleRef.name == "<role-name>")'
        ```

        Problem indication:\
        Bindings that grant these permissions to:

        * `system:authenticated`, `system:unauthenticated`, or other large groups.
        * Generic groups like “developers” or many service accounts that do not need to create pods.
        * User/service account identities where pod creation is not part of their function.

        4. Quick check for obviously over‑broad bindings

        ```bash theme={null}
        kubectl get clusterrolebinding -o json \
          | jq -r '.items[]
            | select(.subjects[]? 
              | (.name == "system:authenticated" or .name == "system:unauthenticated"))
            | .metadata.name' \
          | sort -u
        ```

        ```bash theme={null}
        kubectl get clusterrolebinding -o yaml | grep -E "system:authenticated|system:unauthenticated" -n
        ```

        Problem indication:\
        Any of these broad subjects bound to roles that have `create` on `pods` from step 1.

        5. Verification after manual adjustments

        After you manually edit Roles/ClusterRoles/Bindings (with `kubectl edit` or manifests), re-run:

        ```bash theme={null}
        kubectl get clusterrole -o json | jq -r '.items[]
          | select(.rules[]? 
            | (.verbs[]? | contains("create")) 
            and (.resources[]? | contains("pods")))
          | .metadata.name' | sort -u
        ```

        ```bash theme={null}
        kubectl get role --all-namespaces -o json | jq -r '.items[]
          | select(.rules[]? 
            | (.verbs[]? | contains("create")) 
            and (.resources[]? | contains("pods")))
          | "\(.metadata.namespace)/\(.metadata.name)"' | sort -u
        ```

        Then re-check bindings for any remaining roles that still have pod `create` and confirm they are restricted only to the specific service accounts/users that truly require this capability.
      </Accordion>

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

        # This script inspects Roles and ClusterRoles that can create pods.
        # Run on any machine with kubectl access and a context pointing to the target cluster.

        echo "=== ClusterRoles with 'create' on pods ==="
        kubectl get clusterroles -o json \
          | jq -r '
            .items[]
            | . as $cr
            | [
                $cr.metadata.name,
                (
                  [
                    .rules[]
                    | select(
                        (.resources // []) | index("pods")
                        and
                        (.verbs // []) | index("create")
                      )
                  ] | length
                )
              ]
            | select(.[1] > 0)
            | .[0]
          ' | sort | uniq \
          | while read -r cr; do
              echo "ClusterRole: $cr"
              kubectl get clusterrole "$cr" -o yaml
              echo "-----"
            done

        echo
        echo "=== Roles with 'create' on pods (all namespaces) ==="
        kubectl get roles --all-namespaces -o json \
          | jq -r '
            .items[]
            | . as $r
            | [
                $r.metadata.namespace,
                $r.metadata.name,
                (
                  [
                    .rules[]
                    | select(
                        (.resources // []) | index("pods")
                        and
                        (.verbs // []) | index("create")
                      )
                  ] | length
                )
              ]
            | select(.[2] > 0)
            | .[0] + " " + .[1]
          ' | sort \
          | while read -r ns name; do
              echo "Role: $name (namespace: $ns)"
              kubectl get role "$name" -n "$ns" -o yaml
              echo "-----"
            done

        echo
        echo "=== RoleBindings and ClusterRoleBindings referencing those roles ==="

        echo "# ClusterRoleBindings using ClusterRoles that can create pods"
        kubectl get clusterrolebindings -o json \
          | jq -r '
            .items[]
            | select(.roleRef.kind == "ClusterRole")
            | . as $rb
            | $rb.roleRef.name as $crName
            | $rb.metadata.name + " " + $crName
          ' | while read -r rb cr; do
              # Check if this ClusterRole is in the risky set (can create pods)
              if kubectl get clusterrole "$cr" -o json 2>/dev/null \
                | jq -e '
                    [
                      .rules[]
                      | select(
                          (.resources // []) | index("pods")
                          and
                          (.verbs // []) | index("create")
                        )
                    ] | length > 0
                  ' >/dev/null
              then
                echo "ClusterRoleBinding: $rb -> ClusterRole: $cr"
                kubectl get clusterrolebinding "$rb" -o yaml
                echo "-----"
              fi
            done

        echo
        echo "# RoleBindings using Roles that can create pods"
        kubectl get rolebindings --all-namespaces -o json \
          | jq -r '
            .items[]
            | select(.roleRef.kind == "Role")
            | .metadata.namespace + " " + .metadata.name + " " + .roleRef.name
          ' | while read -r ns rb role; do
              if kubectl get role "$role" -n "$ns" -o json 2>/dev/null \
                | jq -e '
                    [
                      .rules[]
                      | select(
                          (.resources // []) | index("pods")
                          and
                          (.verbs // []) | index("create")
                        )
                    ] | length > 0
                  ' >/dev/null
              then
                echo "RoleBinding: $rb (namespace: $ns) -> Role: $role"
                kubectl get rolebinding "$rb" -n "$ns" -o yaml
                echo "-----"
              fi
            done

        cat <<'EOF'

        How to interpret this output:

        1. Any ClusterRole or Role shown has the ability to create pods somewhere in the cluster.
        2. For each such Role/ClusterRole, review:
           - rules: ensure "resources: [pods]" with "verbs: [create]" is truly required.
           - scope: wide-scoped roles (e.g., in kube-system, default, or custom infra namespaces) deserve extra scrutiny.
        3. For each associated RoleBinding/ClusterRoleBinding:
           - Check the `subjects` section (users, groups, service accounts).
           - Investigate whether each subject actually needs to create pods.
           - Service accounts that do not run controllers, operators, or deployment tools typically should NOT need pod creation rights.

        Potential problem indicators:
        - Generic or broad roles (e.g., "admin", "edit", custom "dev-*") that grant create on pods and are bound to many users or groups.
        - ClusterRoles with create on pods bound via ClusterRoleBinding to:
          - `system:authenticated`, `system:unauthenticated`, or large identity groups (e.g., "Developers", "Everyone").
        - Service accounts in application namespaces that are not part of a deployment/orchestration component but still have create on pods.

        Use `kubectl edit role -n <namespace> <role>` and
        `kubectl edit clusterrole <name>` to manually apply least privilege,
        removing "create" on "pods" where it is not strictly required.

        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
