> ## 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 Admission Control Plugin ServiceAccount Is Set

### More Info:

Automate service accounts management.

### Risk Level

Medium

### 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, review existing ServiceAccounts to understand what is already in use (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl get serviceaccounts --all-namespaces -o wide
           ```
           If needed, create or adjust ServiceAccounts for your workloads according to your environment’s requirements:
           ```bash theme={null}
           kubectl create serviceaccount <name> -n <namespace>
           ```

        2. On every control plane node, back up the existing kube-apiserver static pod manifest:
           ```bash theme={null}
           sudo cp -a /etc/kubernetes/manifests/kube-apiserver.yaml /etc/kubernetes/manifests/kube-apiserver.yaml.backup
           ```

        3. On every control plane node, open the kube-apiserver manifest for editing:
           ```bash theme={null}
           sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
           ```

        4. In the `spec.containers[0].command` section, locate the `--disable-admission-plugins` argument.
           * If it includes `ServiceAccount`, remove `ServiceAccount` from the comma-separated list, leaving the other plugins unchanged.
           * If `--disable-admission-plugins` is not present, no change is needed for this argument.\
             Save and exit the editor.\
             Note: Editing this file will cause the kubelet to restart the kube-apiserver static pod.

        5. Wait for the kube-apiserver pod to restart and become Ready (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl get pods -n kube-system -l component=kube-apiserver -o wide
           ```

        6. Verify on every control plane node that the kube-apiserver process is now running without `ServiceAccount` in `--disable-admission-plugins`:
           ```bash theme={null}
           /bin/ps -ef | grep kube-apiserver | grep -v grep
           ```
           Inspect the output and confirm that either `--disable-admission-plugins` is absent or, if present, its value does not contain `ServiceAccount`.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify the kube-apiserver static pod manifest or its process flags on the control plane node. To remediate this finding, you must edit `/etc/kubernetes/manifests/kube-apiserver.yaml` directly on every control plane node; see the Manual Steps section for detailed guidance.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Automation: Ensure ServiceAccount admission plugin is NOT disabled
        # Scope: Run on every control plane node
        # Effect: Edits /etc/kubernetes/manifests/kube-apiserver.yaml
        # Note: Changing this static pod manifest will restart the kube-apiserver.

        set -euo pipefail

        KUBE_APISERVER_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
        BACKUP_SUFFIX="$(date +%Y%m%d%H%M%S)"

        if [ ! -f "$KUBE_APISERVER_MANIFEST" ]; then
          echo "ERROR: $KUBE_APISERVER_MANIFEST not found on this node. Are you on a control plane node?"
          exit 1
        fi

        if ! command -v python3 >/dev/null 2>&1; then
          echo "ERROR: python3 is required for safe YAML manipulation."
          exit 1
        fi

        echo "Creating backup: ${KUBE_APISERVER_MANIFEST}.${BACKUP_SUFFIX}"
        cp -p "$KUBE_APISERVER_MANIFEST" "${KUBE_APISERVER_MANIFEST}.${BACKUP_SUFFIX}"

        python3 << 'PYEOF'
        import sys, re, copy
        from pathlib import Path

        path = Path("/etc/kubernetes/manifests/kube-apiserver.yaml")
        text = path.read_text()

        # Very small YAML editor tailored for kube-apiserver command args line.
        # Goal: ensure --disable-admission-plugins does NOT contain ServiceAccount.
        lines = text.splitlines()
        changed = False

        def process_arg_list(arg_str: str) -> str:
            """
            Given a comma-separated list (e.g. 'NamespaceLifecycle,ServiceAccount,NodeRestriction'),
            remove 'ServiceAccount' token if present and deduplicate commas.
            """
            parts = [p.strip() for p in arg_str.split(",") if p.strip()]
            parts = [p for p in parts if p != "ServiceAccount"]
            return ",".join(parts)

        new_lines = []
        for line in lines:
            if "--disable-admission-plugins" in line:
                orig_line = line

                # Match patterns like:
                #   - --disable-admission-plugins=Something,ServiceAccount,Other
                #   - --disable-admission-plugins=ServiceAccount
                #   --disable-admission-plugins=ServiceAccount,Other
                def repl(m):
                    pre = m.group(1)
                    val = m.group(2)
                    new_val = process_arg_list(val)
                    return f"{pre}{new_val}"

                new_line = re.sub(
                    r"(--disable-admission-plugins=)([^ \"']+)",
                    repl,
                    line
                )

                if new_line != orig_line:
                    changed = True
                line = new_line
            new_lines.append(line)

        if changed:
            new_text = "\n".join(new_lines) + ("\n" if text.endswith("\n") else "")
            path.write_text(new_text)

        PYEOF

        echo "Configuration updated. kube-apiserver static pod will be reloaded automatically."

        # Verification: ensure kube-apiserver is running and ServiceAccount is NOT in --disable-admission-plugins
        echo "Waiting briefly for kube-apiserver to stabilize..."
        sleep 10

        echo "Current kube-apiserver process flags:"
        /bin/ps -ef | grep kube-apiserver | grep -v grep || {
          echo "ERROR: kube-apiserver process not found. Check pod status."
          exit 1
        }

        if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--disable-admission-plugins"; then
          if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--disable-admission-plugins=.*ServiceAccount"; then
            echo "FAIL: ServiceAccount still present in --disable-admission-plugins."
            exit 1
          fi
        fi

        echo "PASS: ServiceAccount admission plugin is not disabled on this control plane node."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/admin/kube-apiserver/](https://kubernetes.io/docs/admin/kube-apiserver/)
