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

# API Server Should Disable Anonymous Authentication

### More Info:

Verifies that the API server --anonymous-auth argument is set to false. Allowing anonymous requests lets unauthenticated users access the API and is a critical exposure.

### Risk Level

Critical

### Address

Security

### Compliance Standards

* CIS Kubernetes

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Identify how users currently authenticate**
           * On any machine with `kubectl` access, list all `ClusterRoleBinding` and `RoleBinding` objects to see which subjects (users, groups, service accounts) have access:
             ```bash theme={null}
             kubectl get clusterrolebindings.authorization.k8s.io -o yaml > /tmp/clusterrolebindings.yaml
             kubectl get rolebindings.authorization.k8s.io --all-namespaces -o yaml > /tmp/rolebindings.yaml
             ```
           * Review these files for `kind: ServiceAccount` used as long‑lived “users” (e.g., bound to broad cluster roles like `cluster-admin` or used outside pods).

        2. **Locate and review OIDC (or other user auth) configuration**
           * On every control plane node, inspect the API server static pod manifest to see what authentication mechanisms are configured:
             ```bash theme={null}
             sudo cat /etc/kubernetes/manifests/kube-apiserver.yaml
             ```
           * In the `command:` section, look for flags such as `--oidc-issuer-url`, `--oidc-client-id`, `--oidc-username-claim`, `--oidc-groups-claim`, or webhook/token file auth flags.
           * If no non–service-account user auth mechanism is configured, plan an OIDC or other supported auth integration before removing any service-account-based user access.

        3. **Inventory service accounts used as “users”**
           * On any machine with `kubectl` access, list all service accounts and their tokens/secrets:
             ```bash theme={null}
             kubectl get serviceaccounts --all-namespaces -o yaml > /tmp/serviceaccounts.yaml
             kubectl get secrets --all-namespaces -o yaml > /tmp/secrets.yaml
             ```
           * Correlate service accounts that:
             * Are referenced in out-of-cluster automation, scripts, or CI/CD as bearer tokens.
             * Have powerful bindings (e.g., `cluster-admin`) from step 1.
           * Document which external systems rely on these tokens.

        4. **Plan and, if appropriate, migrate those “user” identities to OIDC (or another user auth)**
           * Work with your identity team to create proper user or group identities in your IdP and configure Kubernetes API server OIDC flags in `/etc/kubernetes/manifests/kube-apiserver.yaml` (or equivalent mechanism) according to your platform’s guidance.
           * For each external system identified in step 3, update its configuration to use OIDC (or other non–service-account) auth instead of embedding a service account token.
           * Apply any manifest changes to `/etc/kubernetes/manifests/kube-apiserver.yaml`; be aware that editing this file will restart the API server pod on that control plane node.

        5. **Tighten or remove service account–based user access**
           * Once alternate auth is working, on any machine with `kubectl` access, remove or reduce broad RBAC bindings that treat service accounts as users (example for a specific binding):
             ```bash theme={null}
             kubectl delete clusterrolebinding <binding-name>
             ```
           * Optionally delete no-longer-needed service accounts and their secrets:
             ```bash theme={null}
             kubectl delete serviceaccount <name> -n <namespace>
             ```
           * Ensure remaining service accounts are only used by in-cluster workloads and have least-privilege roles.

        6. **Verify current state and document residual exceptions**
           * Re-run evidence collection to confirm that no service accounts are bound as generic user identities:
             ```bash theme={null}
             kubectl get clusterrolebindings.authorization.k8s.io -o yaml | grep -n "kind: ServiceAccount" -n
             kubectl get rolebindings.authorization.k8s.io --all-namespaces -o yaml | grep -n "kind: ServiceAccount" -n
             ```
           * For any remaining intentional uses (e.g., machine-to-machine automation that cannot yet use OIDC), document the justification, scope, and planned remediation timeline, as this check is inherently manual and risk-based.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot change API server process flags or the static pod manifest at `/etc/kubernetes/manifests/kube-apiserver.yaml` on control plane nodes. To address this finding, make the change directly on each control plane node’s host configuration as described in the Manual Steps section.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Purpose: Report where service account tokens are being used as user credentials,
        #          so you can manually review and decide if they are appropriate.
        #
        # Requirements:
        #   - Run on any machine with:
        #       * kubectl installed
        #       * KUBECONFIG pointing at the cluster
        #   - kubectl must have sufficient RBAC to:
        #       * list secrets, serviceaccounts, pods, configmaps
        #       * list clusterrolebindings and rolebindings

        set -euo pipefail

        echo "=== 1. ServiceAccount tokens and where they are mounted into Pods ==="
        echo

        # List all serviceaccount token secrets (Kubernetes 1.24+ uses bound tokens; older clusters may still have 'kubernetes.io/service-account-token')
        kubectl get secrets --all-namespaces -o jsonpath='{range .items[?(@.type=="kubernetes.io/service-account-token")]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.metadata.annotations["kubernetes.io/service-account.name"]}{"\n"}{end}' \
          | sort || true

        echo
        echo "Above columns: NAMESPACE  SECRET_NAME  SERVICEACCOUNT_NAME"
        echo "These secrets represent long-lived service account tokens. They are risky if used by humans or external systems as 'user' credentials."
        echo

        echo "=== 2. Pods with service account token volume mounts or automount enabled ==="
        echo

        # Pods that explicitly mount service account token secrets as volumes
        echo "-- Pods explicitly mounting SA token secrets as volumes --"
        kubectl get pods --all-namespaces -o json \
          | jq -r '
              .items[]
              | {
                  ns: .metadata.namespace,
                  pod: .metadata.name,
                  sa: .spec.serviceAccountName,
                  volumes: (.spec.volumes // [])
                }
              | select([.volumes[]? | select(.secret != null) | .secret.secretName] | length > 0)
              | "\(.ns)\t\(.pod)\t\(.sa)"' 2>/dev/null | sort || true

        echo
        echo "Columns: NAMESPACE  POD_NAME  SERVICEACCOUNT"
        echo "Pods listed here are explicitly mounting secrets (which may be service account tokens)."
        echo "Investigate each secret to ensure it is not being used as a user credential outside the pod."
        echo

        # Pods with automountServiceAccountToken explicitly true
        echo "-- Pods with automountServiceAccountToken=true --"
        kubectl get pods --all-namespaces -o json \
          | jq -r '
              .items[]
              | select(.spec.automountServiceAccountToken == true)
              | "\(.metadata.namespace)\t\(.metadata.name)\t\(.spec.serviceAccountName)"' 2>/dev/null | sort || true

        echo
        echo "Columns: NAMESPACE  POD_NAME  SERVICEACCOUNT"
        echo "These pods automatically receive a service account token. Confirm that the token is used only for in-cluster workload auth, not as a user credential."
        echo

        echo "=== 3. ServiceAccounts with automountServiceAccountToken not disabled ==="
        echo

        kubectl get serviceaccounts --all-namespaces -o json \
          | jq -r '
              .items[]
              | {
                  ns: .metadata.namespace,
                  sa: .metadata.name,
                  auto: (if .automountServiceAccountToken == false then "false" else "true-or-default" end)
                }
              | "\(.ns)\t\(.sa)\t\(.auto)"' 2>/dev/null | sort || true

        echo
        echo "Columns: NAMESPACE  SERVICEACCOUNT  AUTOMOUNT_SA_TOKEN"
        echo "'true-or-default' means the pod will usually get a token mounted unless disabled at the Pod spec."
        echo "Risk is higher for service accounts used by humans or external automation as a substitute for proper user/OIDC auth."
        echo

        echo "=== 4. ClusterRoleBindings / RoleBindings referencing ServiceAccounts ==="
        echo

        echo "-- ClusterRoleBindings with ServiceAccount subjects --"
        kubectl get clusterrolebindings.rbac.authorization.k8s.io -o json \
          | jq -r '
              .items[]
              | select(.subjects != null)
              | {
                  name: .metadata.name,
                  role: .roleRef.name,
                  subjects: [.subjects[] | select(.kind=="ServiceAccount") | "\(.namespace)/\(.name)"]
                }
              | select(.subjects | length > 0)
              | "\(.name)\t\(.role)\t\(.subjects | join(","))"' 2>/dev/null | sort || true

        echo
        echo "Columns: CLUSTERROLEBINDING  CLUSTERROLE  SERVICEACCOUNT_SUBJECTS"
        echo "These service accounts have cluster-scoped permissions. If any are used by humans via tokens, that violates the intent of this control."
        echo

        echo "-- RoleBindings with ServiceAccount subjects --"
        kubectl get rolebindings.rbac.authorization.k8s.io --all-namespaces -o json \
          | jq -r '
              .items[]
              | select(.subjects != null)
              | {
                  ns: .metadata.namespace,
                  name: .metadata.name,
                  role: .roleRef.name,
                  subjects: [.subjects[] | select(.kind=="ServiceAccount") | "\(.namespace // "'"'"'")/\(.name)"]
                }
              | select(.subjects | length > 0)
              | "\(.ns)\t\(.name)\t\(.role)\t\(.subjects | join(","))"' 2>/dev/null | sort || true

        echo
        echo "Columns: NAMESPACE  ROLEBINDING  ROLE  SERVICEACCOUNT_SUBJECTS"
        echo "Again, if any of these service accounts are used directly as user credentials, that is a problem."
        echo

        echo "=== 5. ConfigMaps that might be distributing SA tokens as credentials (heuristic) ==="
        echo

        # Heuristic: look for strings that look like bearer tokens in ConfigMaps (very rough; may have false positives)
        kubectl get configmaps --all-namespaces -o yaml | \
          awk '
            /^apiVersion: v1/ {ns="";name=""}
            /^  namespace:/ {ns=$2}
            /^  name:/ {name=$2}
            /eyJhbGciOi/ {
              print ns "\t" name "\t" "possible-JWT-like-string"
            }' | sort || true

        echo
        echo "Columns: NAMESPACE  CONFIGMAP  NOTE"
        echo "This is a heuristic for JWT-like strings (e.g., SA tokens) stored in ConfigMaps, possibly to be used as credentials by humans or external systems."
        echo

        echo "=== Interpretation guidance ==="
        cat <<'EOF'

        The following outputs indicate a potential problem that requires manual review:

        - Any long-lived 'kubernetes.io/service-account-token' secrets used:
          * outside the cluster (e.g., in CI/CD, scripts, local kubeconfigs), or
          * by humans as if they were user credentials.
        - Pods or automation that mount SA token secrets and then expose them to users or external systems.
        - ServiceAccounts with broad RBAC (especially cluster-admin) where their token is used interactively.
        - ConfigMaps or other artifacts distributing SA tokens for use as client credentials.

        This script does NOT automatically fix anything.
        Use it to:
          1. Identify high-privilege or widely used ServiceAccounts.
          2. Confirm how their tokens are used.
          3. Migrate those use cases to proper user authentication (e.g., OIDC, SSO, short-lived tokens)
             instead of relying on service account tokens for user access.

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