> ## 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 Not Enable The AlwaysAdmit Admission Plugin

### More Info:

Verifies that the AlwaysAdmit admission plugin is not enabled. AlwaysAdmit accepts every request and bypasses all other admission controls.

### Risk Level

High

### Address

Security

### Compliance Standards

* CIS Kubernetes

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. On every control plane node, open the API server static pod manifest in an editor:
           ```bash theme={null}
           sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
           ```

        2. In the `command:` (or `args:`) list of the `kube-apiserver` container, locate any entry that starts with `--enable-admission-plugins=` and remove `AlwaysAdmit` from the comma-separated list. For example, change:
           ```yaml theme={null}
           - --enable-admission-plugins=NamespaceLifecycle,AlwaysAdmit,NodeRestriction
           ```
           to:
           ```yaml theme={null}
           - --enable-admission-plugins=NamespaceLifecycle,NodeRestriction
           ```
           If `AlwaysAdmit` is the only value, you may delete the whole `--enable-admission-plugins=...` line.

        3. Still in the same file, check for any explicit use of the deprecated `--admission-control=` flag and remove `AlwaysAdmit` from that list as well, or remove the flag line entirely if appropriate.

        4. Save the file and exit the editor. The kubelet will detect the manifest change and automatically restart the `kube-apiserver` static pod; expect a brief API server interruption.

        5. After the pod restarts, verify that `AlwaysAdmit` is no longer configured in the running process on that control plane node:
           ```bash theme={null}
           /bin/ps -ef | grep kube-apiserver | grep -v grep | grep AlwaysAdmit || echo "AlwaysAdmit not found"
           ```

        6. Repeat steps 1–5 on every control plane node in the cluster.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify the kube-apiserver static pod manifest or its process flags, so this finding cannot be fixed via the Kubernetes API. The configuration must be changed directly on every control plane node in `/etc/kubernetes/manifests/kube-apiserver.yaml`; see the Manual Steps section for the exact procedure.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Disable the AlwaysAdmit admission plugin in kube-apiserver static pod manifest.
        # Target: every control plane node
        # Safe to re-run; backs up the manifest once per change and only edits when needed.

        set -euo pipefail

        MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
        BACKUP_DIR="/etc/kubernetes/manifests/backup-$(date +%Y%m%d)"
        mkdir -p "$BACKUP_DIR"

        if [[ ! -f "$MANIFEST" ]]; then
          echo "ERROR: $MANIFEST not found. Run this script on a control plane node."
          exit 1
        fi

        # Function: check if AlwaysAdmit is currently enabled in the manifest
        has_always_admit() {
          grep -E -- '--enable-admission-plugins=.*AlwaysAdmit' "$MANIFEST" >/dev/null 2>&1
        }

        # Function: check if AlwaysAdmit is explicitly disabled
        has_always_admit_in_disable() {
          grep -E -- '--disable-admission-plugins=.*AlwaysAdmit' "$MANIFEST" >/dev/null 2>&1
        }

        echo "Inspecting $MANIFEST for AlwaysAdmit..."

        if ! has_always_admit; then
          echo "AlwaysAdmit is not enabled in --enable-admission-plugins. No change needed."
        else
          echo "AlwaysAdmit found in --enable-admission-plugins. Patching manifest..."

          cp -n "$MANIFEST" "$BACKUP_DIR/kube-apiserver.yaml.$(date +%H%M%S)"

          TMP="$(mktemp)"
          cp "$MANIFEST" "$TMP"

          # 1. Remove AlwaysAdmit from any existing --enable-admission-plugins list
          #    Handles both comma-separated and single-value cases.
          python3 - "$TMP" <<'PYCODE'
        import re, sys, shutil, tempfile

        path = sys.argv[1]
        with open(path, 'r', encoding='utf-8') as f:
            data = f.read()

        pattern = re.compile(r'(--enable-admission-plugins=)(\S+)')
        def repl(m):
            prefix, val = m.groups()
            plugins = val.split(',')
            plugins = [p for p in plugins if p != 'AlwaysAdmit']
            if not plugins:
                # remove the flag entirely by returning just a comment marker
                return '# ' + prefix + val
            return prefix + ','.join(plugins)

        new_data = pattern.sub(repl, data)

        fd, tmp_out = tempfile.mkstemp()
        with open(tmp_out, 'w', encoding='utf-8') as f:
            f.write(new_data)
        shutil.move(tmp_out, path)
        PYCODE

          # 2. Optionally ensure AlwaysAdmit is explicitly disabled (defensive),
          #    but only if it's not already present in --disable-admission-plugins.
          if ! has_always_admit_in_disable; then
            echo "Adding AlwaysAdmit to --disable-admission-plugins for defense-in-depth..."

            # If --disable-admission-plugins exists, append; else, add a new arg line.
            if grep -q -- '--disable-admission-plugins=' "$TMP"; then
              python3 - "$TMP" <<'PYCODE'
        import re, sys, shutil, tempfile
        path = sys.argv[1]
        with open(path, 'r', encoding='utf-8') as f:
            data = f.read()

        pattern = re.compile(r'(--disable-admission-plugins=)(\S+)')
        def repl(m):
            prefix, val = m.groups()
            plugins = val.split(',')
            if 'AlwaysAdmit' not in plugins:
                plugins.append('AlwaysAdmit')
            return prefix + ','.join(plugins)

        new_data = pattern.sub(repl, data)
        fd, tmp_out = tempfile.mkstemp()
        with open(tmp_out, 'w', encoding='utf-8') as f:
            f.write(new_data)
        shutil.move(tmp_out, path)
        PYCODE
            else
              # Insert a new argument line under the kube-apiserver container args
              python3 - "$TMP" <<'PYCODE'
        import sys, shutil, tempfile

        path = sys.argv[1]
        with open(path, 'r', encoding='utf-8') as f:
            lines = f.readlines()

        out = []
        inserted = False
        for i, line in enumerate(lines):
            out.append(line)
            if not inserted and line.lstrip().startswith('args:'):
                indent = ' ' * (len(line) - len(line.lstrip()))
                out.append(f"{indent}- --disable-admission-plugins=AlwaysAdmit\n")
                inserted = True

        if not inserted:
            # Fallback: just append at end
            out.append("    - --disable-admission-plugins=AlwaysAdmit\n")

        fd, tmp_out = tempfile.mkstemp()
        with open(tmp_out, 'w', encoding='utf-8') as f:
            f.writelines(out)
        shutil.move(tmp_out, path)
        PYCODE
            fi
          fi

          # Move patched temp file back into place
          mv "$TMP" "$MANIFEST"
          echo "Patched $MANIFEST. kube-apiserver static pod will be restarted by kubelet."
        fi

        echo
        echo "Verification (this may take up to a minute while kube-apiserver restarts)..."

        # Wait until kube-apiserver process is present and does not reference AlwaysAdmit in enable flag
        for i in {1..30}; do
          if /bin/ps -ef | grep kube-apiserver | grep -v grep >/dev/null 2>&1; then
            if ! /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -E -- '--enable-admission-plugins=.*AlwaysAdmit' >/dev/null 2>&1; then
              echo "PASS: kube-apiserver is running and AlwaysAdmit is not enabled."
              exit 0
            fi
          fi
          sleep 2
        done

        echo "WARNING: kube-apiserver process still shows AlwaysAdmit in --enable-admission-plugins."
        echo "Inspect current flags with:"
        echo "/bin/ps -ef | grep kube-apiserver | grep -v grep"
        exit 1
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
