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

# Pods That Do Not Use The API Should Disable Token Automount

### More Info:

Verifies automountServiceAccountToken is false for pods that do not call the Kubernetes API. A mounted token is a ready-made credential for an attacker who lands in the pod.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* Cloudanix Best Practice

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. Identify noncompliant pods and their owners (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl get pods --all-namespaces -o json | jq -r '
             [ .items[]
             | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
             | .metadata as $m
             | ([ ($m.ownerReferences // [])[] | select(.controller) ] | first) as $own
             | (.spec.automountServiceAccountToken == false) as $ok
             | select($ok | not)
             | "\($m.namespace) \($m.name) \($own.kind) \($own.name) \(.spec.serviceAccountName // "default")"
             ][]'
           ```
           Review each listed workload and decide whether it legitimately needs to call the Kubernetes API; only proceed for those that do not.

        2. For workloads managed by controllers (Deployment/StatefulSet/DaemonSet/Job/CronJob), edit the controller to set `automountServiceAccountToken: false` at the pod spec level (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl -n NAMESPACE edit DEPLOYMENT_NAME
           ```
           In the opened manifest, under `spec.template.spec`, add or change:
           ```yaml theme={null}
           spec:
             template:
               spec:
                 automountServiceAccountToken: false
           ```
           Save and exit; Kubernetes will roll out updated pods.

        3. For standalone Pods you control directly (no controller ownerReference), edit the Pod spec and re-create it (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl -n NAMESPACE get pod POD_NAME -o yaml > /tmp/pod-POD_NAME.yaml
           ```
           Edit `/tmp/pod-POD_NAME.yaml` and under `spec` add:
           ```yaml theme={null}
           spec:
             automountServiceAccountToken: false
           ```
           Then delete and re-create:
           ```bash theme={null}
           kubectl -n NAMESPACE delete pod POD_NAME
           kubectl -n NAMESPACE apply -f /tmp/pod-POD_NAME.yaml
           ```

        4. Optionally harden shared ServiceAccounts so all attached pods disable token automount by default (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl -n NAMESPACE edit serviceaccount SERVICEACCOUNT_NAME
           ```
           Add:
           ```yaml theme={null}
           automountServiceAccountToken: false
           ```
           Be sure this ServiceAccount is not used by workloads that need Kubernetes API access.

        5. For pods that legitimately need the Kubernetes API, document the decision and ensure least-privilege RBAC:
           ```bash theme={null}
           kubectl -n NAMESPACE get rolebinding,clusterrolebinding -o wide | grep SERVICEACCOUNT_NAME || true
           ```
           Adjust Roles/ClusterRoles separately so the token, where kept, has only necessary permissions.

        6. Verify remediation (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl get pods --all-namespaces -o json | jq -r '
             [ .items[]
             | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
             | .metadata as $m
             | (.spec.automountServiceAccountToken == false) as $ok
             | select($ok | not)
             ] as $rows
             | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
           ```
           Confirm the output is `is_compliant=true` or that remaining flagged pods are those you intentionally allowed to keep tokens.
      </Accordion>

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

        1. Identify one non‑compliant pod (example):

        ```bash theme={null}
        kubectl get pods -A \
          -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,SA:.spec.serviceAccountName,AUTO:.spec.automountServiceAccountToken' \
          | grep -v ' true$' | grep -v ' false$' | grep -v NAMESPACE
        ```

        2. Get the owning workload and current pod spec:

        ```bash theme={null}
        kubectl get pod POD_NAME -n POD_NAMESPACE -o yaml > /tmp/pod-debug.yaml
        ```

        Check `.metadata.ownerReferences` to see if it is owned by a Deployment, StatefulSet, Job, CronJob, etc. You must edit the owning workload, not the live Pod.

        3. Patch a Deployment to disable token automount for pods that do not need the API (example for a Deployment owner):

        ```bash theme={null}
        kubectl patch deployment DEPLOYMENT_NAME -n POD_NAMESPACE \
          --type='strategic' \
          -p '{
            "spec": {
              "template": {
                "spec": {
                  "automountServiceAccountToken": false
                }
              }
            }
          }'
        ```

        For other controllers, replace `deployment` with `statefulset`, `daemonset`, `job`, or `cronjob` as appropriate.

        4. If the pod is standalone (no ownerReferences), edit the Pod manifest source and re‑apply it declaratively. Example manifest snippet:

        ```yaml theme={null}
        apiVersion: v1
        kind: Pod
        metadata:
          name: example-pod
          namespace: example-namespace
        spec:
          automountServiceAccountToken: false
          containers:
          - name: app
            image: your-image
        ```

        Apply it:

        ```bash theme={null}
        kubectl apply -f path/to/pod.yaml
        ```

        5. Verification (matches the audit intent):

        ```bash theme={null}
        kubectl get pods --all-namespaces -o json | jq -r '
          [ .items[]
          | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | .metadata as $m
          | (.spec.automountServiceAccountToken == false) as $ok
          | "ns=\($m.namespace) name=\($m.name) automountServiceAccountToken=\(if .spec.automountServiceAccountToken == null then "unset" else .spec.automountServiceAccountToken end) is_compliant=\(if $ok then "true" else "false" end)"
          ] as $rows
          | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Disable automountServiceAccountToken for pods that do NOT need the Kubernetes API.
        #
        # IMPORTANT: This script does NOT change anything automatically.
        # For each non-compliant Pod, it:
        #   - Shows current Pod spec
        #   - Shows owning controller (if any)
        #   - Prints a kubectl patch command you can copy, review, and run
        #
        # This is deliberate: the benchmark specifies that pods which legitimately
        # call the API must be reviewed, not blindly remediated.
        #
        # Run on: any machine with kubectl access to the cluster
        # Requirements: bash, kubectl, jq

        set -euo pipefail

        echo "=== Scanning for pods with automountServiceAccountToken not explicitly set to false ==="

        # Reuse the audit logic to list only non-compliant pods (outside system namespaces)
        non_compliant_json="$(kubectl get pods --all-namespaces -o json | jq '
          .items[]
          | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | select(.spec.automountServiceAccountToken != false)
        ')"

        if [[ -z "${non_compliant_json}" ]]; then
          echo "No non-compliant pods found. Cluster is compliant for this control."
          exit 0
        fi

        echo "Non-compliant pods detected. Listing details and suggested patches."
        echo

        # Iterate each offending pod
        echo "${non_compliant_json}" | jq -c '.' | while read -r pod; do
          ns="$(jq -r '.metadata.namespace' <<< "${pod}")"
          name="$(jq -r '.metadata.name' <<< "${pod}")"
          sa="$(jq -r '.spec.serviceAccountName // "default"' <<< "${pod}")"
          owner_kind="$(jq -r '[.metadata.ownerReferences[]? | select(.controller)] | first.kind // "Pod"' <<< "${pod}")"
          owner_name="$(jq -r '[.metadata.ownerReferences[]? | select(.controller)] | first.name // ""' <<< "${pod}")"

          echo "-----------------------------------------------------------------"
          echo "Pod: ${ns}/${name}"
          echo "  ServiceAccount: ${sa}"
          echo "  Controller: ${owner_kind}${owner_name:+/${owner_name}}"

          if [[ "${owner_kind}" == "Pod" || -z "${owner_kind}" || "${owner_name}" == "null" ]]; then
            echo "  NOTE: This is a standalone Pod (not controlled by a higher-level workload)."
            echo "  Review whether this Pod ever calls the Kubernetes API. If it does NOT,"
            echo "  you can set automountServiceAccountToken=false directly on the Pod spec."
            echo
            echo "  Suggested patch (standalone Pod):"
            cat <<EOF
        kubectl -n ${ns} patch pod ${name} --type merge -p '{
          "spec": {
            "automountServiceAccountToken": false
          }
        }'
        EOF
          else
            echo "  NOTE: This Pod is managed by a controller. You MUST patch the controller"
            echo "  (e.g., Deployment, StatefulSet, DaemonSet, Job, CronJob, etc.), not the Pod."
            echo "  Review whether this workload ever calls the Kubernetes API. If it does NOT,"
            echo "  you can set automountServiceAccountToken=false in the pod template."
            echo
            echo "  Suggested patch (controller template):"
            # For typical workload types we can provide a generic patch.
            # User must adjust 'spec.template.spec' path if their controller is custom.
            case "${owner_kind}" in
              Deployment|StatefulSet|DaemonSet)
                cat <<EOF
        kubectl -n ${ns} patch ${owner_kind,,} ${owner_name} --type merge -p '{
          "spec": {
            "template": {
              "spec": {
                "automountServiceAccountToken": false
              }
            }
          }
        }'
        EOF
                ;;
              Job)
                cat <<EOF
        kubectl -n ${ns} patch job ${owner_name} --type merge -p '{
          "spec": {
            "template": {
              "spec": {
                "automountServiceAccountToken": false
              }
            }
          }
        }'
        EOF
                ;;
              CronJob)
                cat <<EOF
        kubectl -n ${ns} patch cronjob ${owner_name} --type merge -p '{
          "spec": {
            "jobTemplate": {
              "spec": {
                "template": {
                  "spec": {
                    "automountServiceAccountToken": false
                  }
                }
              }
            }
          }
        }'
        EOF
                ;;
              *)
                echo "  Unrecognized or custom controller kind: ${owner_kind}"
                echo "  Inspect its spec and add automountServiceAccountToken: false under the Pod template:"
                echo "    - For most controllers, this is under .spec.template.spec"
                echo "    - For CronJob, it is under .spec.jobTemplate.spec.template.spec"
                echo
                echo "  Generic example (adjust apiVersion/kind/path as needed):"
                cat <<'EOF'
        kubectl -n <namespace> patch <kind> <name> --type merge -p '{
          "spec": {
            "template": {
              "spec": {
                "automountServiceAccountToken": false
              }
            }
          }
        }'
        EOF
                ;;
            esac
          fi
          echo
        done

        echo "-----------------------------------------------------------------"
        echo "Review and run the suggested kubectl patch commands ONLY for workloads"
        echo "that do NOT need to call the Kubernetes API."

        echo
        echo "=== Verification (re-run the benchmark-style audit) ==="
        kubectl get pods --all-namespaces -o json | jq -r '
          [ .items[]
          | select(.metadata.namespace as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | (.spec.automountServiceAccountToken == false) as $ok
          | select($ok | not)
          ] as $rows
          | if ($rows | length) == 0 then "is_compliant=true" else "Non-compliant pods remain; review above output." end'
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
