> ## 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 Encryption Providers Should Be Appropriately Configured

### More Info:

Verifies that the encryption provider config uses a strong provider such as aescbc, kms or secretbox so secrets at rest are properly encrypted.

### 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. **Identify the encryption provider config file (control plane node)**
           ```bash theme={null}
           ENCRYPTION_PROVIDER_CONFIG=$(ps -ef | grep kube-apiserver | grep -- --encryption-provider-config | sed 's%.*encryption-provider-config[= ]\([^ ]*\).*%\1%')
           echo "$ENCRYPTION_PROVIDER_CONFIG"
           ```
           If this prints nothing, check `/etc/kubernetes/manifests/kube-apiserver.yaml` for an `--encryption-provider-config` flag and its path.

        2. **Back up the existing encryption config and manifest (control plane node)**
           ```bash theme={null}
           mkdir -p /root/enc-backup
           cp -p "$ENCRYPTION_PROVIDER_CONFIG" /root/enc-backup/encryption-config-$(date +%F-%H%M%S).yaml
           cp -p /etc/kubernetes/manifests/kube-apiserver.yaml /root/enc-backup/kube-apiserver-$(date +%F-%H%M%S).yaml
           ```

        3. **Edit the encryption configuration to use a strong provider (control plane node)**\
           Open the file in an editor:
           ```bash theme={null}
           vi "$ENCRYPTION_PROVIDER_CONFIG"
           ```
           Replace or add a resources section using a strong provider (example using `aescbc`):
           ```yaml theme={null}
           apiVersion: apiserver.config.k8s.io/v1
           kind: EncryptionConfiguration
           resources:
             - resources:
                 - secrets
               providers:
                 - aescbc:
                     keys:
                       - name: key1
                         secret: <BASE64_ENCODED_32_BYTE_KEY>
                 - identity: {}
           ```
           Generate a 32‑byte key and base64‑encode it (run in another shell on the same node) and paste it into `secret`:
           ```bash theme={null}
           head -c 32 /dev/urandom | base64
           ```

        4. **Confirm kube-apiserver is using the encryption config (control plane node)**\
           Ensure `/etc/kubernetes/manifests/kube-apiserver.yaml` contains the flag and correct path; edit if needed:
           ```bash theme={null}
           vi /etc/kubernetes/manifests/kube-apiserver.yaml
           ```
           Under `spec.containers[].command`, ensure a line like:
           ```yaml theme={null}
           - --encryption-provider-config=/etc/kubernetes/encryption-config.yaml
           ```
           Save the file; the kube-apiserver static pod will restart automatically when you edit this manifest.

        5. **Optionally re-encrypt existing secrets (any machine with kubectl access)**\
           This is not enforced by the benchmark but is typically required to ensure all stored secrets use the new provider. Run:
           ```bash theme={null}
           kubectl get secrets --all-namespaces -o json | \
             kubectl replace -f -
           ```

        6. **Verification (control plane node)**\
           After the kube-apiserver pod has restarted and is Ready, re-run the audit logic:
           ```bash theme={null}
           ENCRYPTION_PROVIDER_CONFIG=$(ps -ef | grep kube-apiserver | grep -- --encryption-provider-config | sed 's%.*encryption-provider-config[= ]\([^ ]*\).*%\1%')
           if test -e "$ENCRYPTION_PROVIDER_CONFIG"; then
             grep -A1 'providers:' "$ENCRYPTION_PROVIDER_CONFIG" | tail -n1 | grep -o "[A-Za-z]*" | sed 's/^/provider=/'
           fi
           ```
           Confirm the output shows `provider=aescbc`, `provider=kms`, or `provider=secretbox` as the first provider.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify the API server’s `--encryption-provider-config` or the file it points to, because those are host-level settings controlled by `/etc/kubernetes/manifests/kube-apiserver.yaml` on each control plane node. To configure strong encryption providers (aescbc, kms, or secretbox), follow the guidance in the Manual Steps section on the control plane nodes themselves.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Automation: Ensure kube-apiserver is configured with a strong encryption provider
        # Provider choice: aescbc
        #
        # Run on: every control plane node (as root)
        #
        # This script:
        # 1. Locates the kube-apiserver encryption-provider-config file.
        # 2. Creates/updates it to use aescbc if it is weak or missing.
        # 3. Ensures the kube-apiserver manifest points to it.
        # 4. Relies on the kubelet static pod behavior to restart kube-apiserver.
        # 5. Verifies the configuration via the benchmark audit logic.
        #
        # NOTE: This script does NOT generate a secure, random encryption key for you.
        #       You MUST replace the placeholder key with a securely generated one and
        #       re-run the script (safe to re-run).

        set -euo pipefail

        APISERVER_MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
        ENCRYPTION_CONFIG_PATH_DEFAULT="/etc/kubernetes/encryption-config.yaml"
        PLACEHOLDER_KEY="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="  # 32-byte base64 placeholder

        if [[ $EUID -ne 0 ]]; then
          echo "ERROR: This script must be run as root on each control plane node." >&2
          exit 1
        fi

        if [[ ! -f "$APISERVER_MANIFEST" ]]; then
          echo "ERROR: kube-apiserver manifest not found at $APISERVER_MANIFEST" >&2
          exit 1
        fi

        echo ">>> Detecting existing --encryption-provider-config flag..."
        set +e
        CURRENT_CONFIG_PATH=$(grep -E -- '--encryption-provider-config(=| )' "$APISERVER_MANIFEST" 2>/dev/null | \
          sed -E 's/.*--encryption-provider-config[= ]([^ ]*).*/\1/' | head -n1)
        set -e

        if [[ -z "${CURRENT_CONFIG_PATH:-}" ]]; then
          echo "No --encryption-provider-config flag found; will use default path: $ENCRYPTION_CONFIG_PATH_DEFAULT"
          ENCRYPTION_CONFIG_PATH="$ENCRYPTION_CONFIG_PATH_DEFAULT"
        else
          ENCRYPTION_CONFIG_PATH="$CURRENT_CONFIG_PATH"
          echo "Found existing encryption provider config path: $ENCRYPTION_CONFIG_PATH"
        fi

        # Ensure directory exists
        ENCRYPTION_CONFIG_DIR=$(dirname "$ENCRYPTION_CONFIG_PATH")
        mkdir -p "$ENCRYPTION_CONFIG_DIR"
        chmod 700 "$ENCRYPTION_CONFIG_DIR"

        echo ">>> Writing/Updating encryption provider config at $ENCRYPTION_CONFIG_PATH"

        # If an existing file is present, back it up once
        if [[ -f "$ENCRYPTION_CONFIG_PATH" && ! -f "${ENCRYPTION_CONFIG_PATH}.pre-hardening.bak" ]]; then
          cp -p "$ENCRYPTION_CONFIG_PATH" "${ENCRYPTION_CONFIG_PATH}.pre-hardening.bak"
          echo "Backed up existing config to ${ENCRYPTION_CONFIG_PATH}.pre-hardening.bak"
        fi

        cat > "$ENCRYPTION_CONFIG_PATH" <<EOF
        apiVersion: apiserver.config.k8s.io/v1
        kind: EncryptionConfiguration
        resources:
          - resources:
              - secrets
              - configmaps
              - persistentvolumeclaims
              - serviceaccounts
            providers:
              - aescbc:
                  keys:
                    - name: key1
                      secret: ${PLACEHOLDER_KEY}
              - identity: {}
        EOF

        chmod 600 "$ENCRYPTION_CONFIG_PATH"

        echo ">>> Ensuring kube-apiserver manifest references encryption-provider-config..."

        if grep -qE -- '--encryption-provider-config(=| )' "$APISERVER_MANIFEST"; then
          # Update existing flag if path has changed
          if [[ "$ENCRYPTION_CONFIG_PATH" != "$CURRENT_CONFIG_PATH" && -n "${CURRENT_CONFIG_PATH:-}" ]]; then
            sed -i.bak_encprov \
              -E "s#(--encryption-provider-config(=| )).*[[:space:]]#\1${ENCRYPTION_CONFIG_PATH} #g" \
              "$APISERVER_MANIFEST"
            echo "Updated existing --encryption-provider-config flag in kube-apiserver manifest."
          else
            echo "--encryption-provider-config already present; leaving as-is."
          fi
        else
          # Add the flag under the kube-apiserver container args
          # This assumes a standard static pod manifest layout.
          if grep -q 'name: kube-apiserver' "$APISERVER_MANIFEST" && grep -q 'args:' "$APISERVER_MANIFEST"; then
            cp -p "$APISERVER_MANIFEST" "${APISERVER_MANIFEST}.bak_encprov"
            awk -v path="$ENCRYPTION_CONFIG_PATH" '
              /name: kube-apiserver/ { in_apiserver=1 }
              in_apiserver && /args:/ && !added {
                print $0
                indent = match($0, /args:/) - 1
                pad = sprintf("%*s", indent+2, "")
                print pad "- --encryption-provider-config=" path
                added=1
                next
              }
              { print $0 }
            ' "$APISERVER_MANIFEST.bak_encprov" > "$APISERVER_MANIFEST"
            echo "Added --encryption-provider-config flag to kube-apiserver manifest."
          else
            echo "WARNING: Could not safely inject --encryption-provider-config into kube-apiserver manifest." >&2
            echo "         Please edit $APISERVER_MANIFEST manually to add:" >&2
            echo "           - --encryption-provider-config=${ENCRYPTION_CONFIG_PATH}" >&2
          fi
        fi

        echo ">>> Waiting for kube-apiserver static pod restart (triggered by manifest/config change)..."
        echo "    Monitor with: crictl ps | grep kube-apiserver (or docker/ctr as appropriate)."
        sleep 10

        echo ">>> Verifying that a strong encryption provider is configured..."

        # Re-run the benchmark audit logic
        set +e
        ENCRYPTION_PROVIDER_CONFIG=$(ps -ef | grep kube-apiserver | grep -- --encryption-provider-config | \
          sed 's%.*encryption-provider-config[= ]\([^ ]*\).*%\1%')
        if [[ -z "$ENCRYPTION_PROVIDER_CONFIG" ]]; then
          echo "VERIFICATION FAILED: kube-apiserver process does not show --encryption-provider-config flag." >&2
          exit 1
        fi

        PROVIDER_LINE=$(if test -e "$ENCRYPTION_PROVIDER_CONFIG"; then \
          grep -A1 'providers:' "$ENCRYPTION_PROVIDER_CONFIG" | tail -n1; fi)

        PROVIDER_NAME=$(echo "$PROVIDER_LINE" | grep -o "[A-Za-z]*" | sed 's/^/provider=/' | cut -d= -f2)
        set -e

        if [[ "$PROVIDER_NAME" == "aescbc" || "$PROVIDER_NAME" == "kms" || "$PROVIDER_NAME" == "secretbox" ]]; then
          echo "VERIFICATION PASSED: Strong encryption provider in use: $PROVIDER_NAME"
          exit 0
        else
          echo "VERIFICATION FAILED: Expected aescbc/kms/secretbox, found: ${PROVIDER_NAME:-none}" >&2
          echo "Check $ENCRYPTION_PROVIDER_CONFIG and adjust providers accordingly." >&2
          exit 1
        fi
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
