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

# Ensure That Default Service Accounts Are Not Actively Used

### More Info:

Default service accounts should not be actively used by workloads and should have token automounting disabled. Use explicit service accounts scoped to each workloads needs.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* CIS EKS

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Identify all default service accounts and namespaces**\
           Run on: any machine with kubectl access
           ```bash theme={null}
           kubectl get serviceaccount default --all-namespaces -o wide
           ```

        2. **Disable token automount on every default service account**\
           Run on: any machine with kubectl access\
           (Run once per namespace; `default`, `kube-system`, and any others in use.)
           ```bash theme={null}
           for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
             kubectl patch serviceaccount default \
               -n "$ns" \
               --type merge \
               -p '{"automountServiceAccountToken": false}' || true
           done
           ```

        3. **List pods currently using the default service account**\
           Run on: any machine with kubectl access
           ```bash theme={null}
           kubectl get pods --all-namespaces -o jsonpath='{range .items[?(@.spec.serviceAccountName=="default")]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}'
           ```

        4. **Create explicit service accounts for workloads that need API access**\
           Run on: any machine with kubectl access\
           (Example for one namespace; repeat as needed, adjusting names and namespaces.)
           ```bash theme={null}
           kubectl create serviceaccount app-sa -n your-namespace

           # Optionally bind RBAC as required for the workload:
           kubectl create rolebinding app-sa-access \
             --clusterrole=view \
             --serviceaccount=your-namespace:app-sa \
             -n your-namespace
           ```

        5. **Update workloads to use the explicit service accounts and (optionally) disable pod-level automount**\
           Run on: any machine with kubectl access\
           Edit each deployment/statefulset/cronjob/etc. that currently uses `serviceAccountName: default`:
           ```bash theme={null}
           kubectl edit deployment your-deployment -n your-namespace
           ```
           In `.spec.template.spec`:
           ```yaml theme={null}
           serviceAccountName: app-sa          # change from "default"
           automountServiceAccountToken: false # add if the pod should not get a token
           ```

        6. **Verification**\
           Run on: any machine with kubectl access
           ```bash theme={null}
           # 1) Confirm all default SAs have automount disabled
           default_sa_count=$(kubectl get serviceaccounts --all-namespaces -o json | jq '
             [.items[] | select(.metadata.name == "default" and (.automountServiceAccountToken != false))] | length')
           if [ "$default_sa_count" -gt 0 ]; then
             echo "default_sa_not_auto_mounted"
           else
             echo "all_default_sa_automount_disabled"
           fi

           # 2) Confirm no pods are using the default service account
           pods_using_default_sa=$(kubectl get pods --all-namespaces -o json | jq '
             [.items[] | select(.spec.serviceAccountName == "default")] | length')
           if [ "$pods_using_default_sa" -gt 0 ]; then
             echo "default_sa_used_in_pods"
           else
             echo "no_pods_using_default_sa"
           fi
           ```
      </Accordion>

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

        1. Disable token automounting on all existing `default` ServiceAccounts

        ```bash theme={null}
        for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
          kubectl patch serviceaccount default \
            -n "$ns" \
            --type merge \
            -p '{"automountServiceAccountToken": false}'
        done
        ```

        2. For workloads that need API access, create explicit ServiceAccounts and use them in Pod specs

        Example (save as `sa-and-deployment.yaml` and apply):

        ```yaml theme={null}
        apiVersion: v1
        kind: ServiceAccount
        metadata:
          name: app-sa
          namespace: default
        automountServiceAccountToken: true
        ---
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: app-deployment
          namespace: default
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: myapp
          template:
            metadata:
              labels:
                app: myapp
            spec:
              serviceAccountName: app-sa
              containers:
                - name: app
                  image: nginx:stable
        ```

        Apply:

        ```bash theme={null}
        kubectl apply -f sa-and-deployment.yaml
        ```

        3. Optionally, prevent default use in new workloads by setting an explicit ServiceAccount in your own pod/deployment manifests and avoiding `serviceAccountName: default`.

        4. Verification

        ```bash theme={null}
        # 1) Ensure all default SAs have automountServiceAccountToken: false
        kubectl get serviceaccounts --all-namespaces -o json | jq '
          [.items[] | select(.metadata.name == "default" and (.automountServiceAccountToken != false))] | length'

        # 2) Ensure no pods are using the default SA
        kubectl get pods --all-namespaces -o json | jq '
          [.items[] | select(.spec.serviceAccountName == "default")] | length'
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Remediates CISEKS 4.1.5:
        # - Sets automountServiceAccountToken: false on every "default" ServiceAccount
        # - Detects Pods using the default ServiceAccount so they can be remediated
        #
        # Run on: any machine with kubectl access and jq installed

        set -euo pipefail

        echo "==> Ensuring 'default' ServiceAccounts have automountServiceAccountToken: false"

        # Patch all existing 'default' ServiceAccounts cluster-wide
        # This is idempotent: patching with the same value is safe.
        kubectl get serviceaccount --all-namespaces -o json \
          | jq -r '
              .items[]
              | select(.metadata.name=="default")
              | "\(.metadata.namespace)"
            ' \
          | sort -u \
          | while read -r ns; do
              [ -z "$ns" ] && continue
              echo "Patching default ServiceAccount in namespace: $ns"
              kubectl patch serviceaccount default -n "$ns" \
                --type merge \
                -p '{"automountServiceAccountToken": false}' >/dev/null
            done

        echo "==> Verifying ServiceAccount configuration"

        default_sa_count="$(
          kubectl get serviceaccounts --all-namespaces -o json \
            | jq '[.items[] | select(.metadata.name == "default" and (.automountServiceAccountToken != false))] | length'
        )"

        if [ "$default_sa_count" -gt 0 ]; then
          echo "ERROR: Some 'default' ServiceAccounts still do not have automountServiceAccountToken set to false."
          echo "Count: $default_sa_count"
          exit 1
        fi

        echo "All 'default' ServiceAccounts have automountServiceAccountToken: false"

        echo "==> Detecting Pods using the 'default' ServiceAccount (no automatic change)"

        pods_using_default_sa="$(
          kubectl get pods --all-namespaces -o json \
            | jq '[.items[] | select(.spec.serviceAccountName == "default")] | length'
        )"

        if [ "$pods_using_default_sa" -gt 0 ]; then
          echo "Found Pods using the 'default' ServiceAccount: $pods_using_default_sa"
          echo "Listing them for manual remediation (create and bind explicit ServiceAccounts, then update pod specs):"
          kubectl get pods --all-namespaces -o json \
            | jq -r '
                .items[]
                | select(.spec.serviceAccountName == "default")
                | "\(.metadata.namespace) \(.metadata.name)"
              ' \
            | while read -r ns name; do
                echo "  Namespace: $ns  Pod: $name"
              done
        else
          echo "No Pods are currently using the 'default' ServiceAccount."
        fi

        echo "==> Final verification (re-running benchmark audit logic)"

        default_sa_count_check="$(
          kubectl get serviceaccounts --all-namespaces -o json \
            | jq '[.items[] | select(.metadata.name == "default" and (.automountServiceAccountToken != false))] | length'
        )"

        pods_using_default_sa_check="$(
          kubectl get pods --all-namespaces -o json \
            | jq '[.items[] | select(.spec.serviceAccountName == "default")] | length'
        )"

        if [ "$default_sa_count_check" -gt 0 ]; then
          echo "default_sa_not_auto_mounted"
        fi

        if [ "$pods_using_default_sa_check" -gt 0 ]; then
          echo "default_sa_used_in_pods"
        fi

        if [ "$default_sa_count_check" -eq 0 ]; then
          echo "Remediation complete: all 'default' ServiceAccounts have automountServiceAccountToken: false."
        fi

        # Note: Pods still using the 'default' ServiceAccount must be changed by:
        # - Creating explicit ServiceAccounts per workload with only needed permissions
        # - Updating Pod/Deployment specs (.spec.serviceAccountName) to use them
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
