> ## 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 A Unique Certificate Authority Is Used For Etcd

### More Info:

A dedicated --trusted-ca-file should be used for etcd so it does not share a certificate authority with the wider cluster. Using a separate CA limits the blast radius if another components CA is compromised.

### 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 etcd (control plane) node, identify the current etcd manifest and TLS settings:
           ```bash theme={null}
           sudo cat /etc/kubernetes/manifests/etcd.yaml
           ```
           Note any existing `--trusted-ca-file=...` flag under the etcd container `command:` section and any other TLS flags such as `--cert-file`, `--key-file`, and `--peer-trusted-ca-file`.

        2. On every etcd node, create a dedicated CA for etcd (do NOT reuse the cluster CA). Example using OpenSSL:
           ```bash theme={null}
           sudo mkdir -p /etc/etcd/pki
           cd /etc/etcd/pki

           sudo openssl genrsa -out etcd-ca.key 4096
           sudo openssl req -x509 -new -nodes -key etcd-ca.key -subj "/CN=etcd-ca" -days 3650 -out etcd-ca.crt
           ```
           Adjust subject, key size, and duration to match your security policy.

        3. On every etcd node, issue an etcd server certificate signed by this dedicated CA and restrict permissions:
           ```bash theme={null}
           cd /etc/etcd/pki

           sudo openssl genrsa -out etcd-server.key 4096
           sudo openssl req -new -key etcd-server.key -subj "/CN=etcd" -out etcd-server.csr

           sudo openssl x509 -req -in etcd-server.csr -CA etcd-ca.crt -CAkey etcd-ca.key \
             -CAcreateserial -out etcd-server.crt -days 3650 -extensions v3_req -extfile <(cat <<EOF
           ```

        \[ v3\_req ]
        basicConstraints = CA:FALSE
        keyUsage = digitalSignature,keyEncipherment
        extendedKeyUsage = serverAuth,clientAuth
        subjectAltName = @alt\_names

        \[ alt\_names ]
        DNS.1 = localhost
        DNS.2 = etcd
        IP.1  = 127.0.0.1
        EOF
        )
        sudo chmod 600 /etc/etcd/pki/etcd-ca.key /etc/etcd/pki/etcd-server.key
        sudo chown root:root /etc/etcd/pki/\*

        ````

        4. On every etcd node, edit `/etc/kubernetes/manifests/etcd.yaml` to use the dedicated CA and certificates. Open the file:
        ```bash
        sudo vi /etc/kubernetes/manifests/etcd.yaml
        ````

        Under the etcd container `command:` list, ensure you add or update the following flags to point to the dedicated CA and certs:

        ```yaml theme={null}
        - --cert-file=/etc/etcd/pki/etcd-server.crt
        - --key-file=/etc/etcd/pki/etcd-server.key
        - --trusted-ca-file=/etc/etcd/pki/etcd-ca.crt
        ```

        Also, if peer TLS is enabled, align peer CA/certs to this same dedicated CA:

        ```yaml theme={null}
        - --peer-cert-file=/etc/etcd/pki/etcd-server.crt
        - --peer-key-file=/etc/etcd/pki/etcd-server.key
        - --peer-trusted-ca-file=/etc/etcd/pki/etcd-ca.crt
        ```

        Save and exit. Editing this static pod manifest will cause the kubelet to restart the etcd pod automatically; brief etcd/control-plane disruption may occur.

        5. On every etcd node, confirm the etcd pod has restarted and is healthy:
           ```bash theme={null}
           # from a machine with kubectl access
           kubectl get pods -n kube-system -o wide | grep etcd
           kubectl logs -n kube-system <etcd-pod-name> | tail -n 20
           ```
           Verify there are no TLS or CA-related errors in the logs.

        6. Verification (on every etcd node): ensure the etcd process is running with the dedicated `--trusted-ca-file` flag and that it points to the etcd-specific CA path:
           ```bash theme={null}
           /bin/ps -ef | /bin/grep etcd | /bin/grep -v grep
           ```
           Confirm the command line includes:
           ```text theme={null}
           --trusted-ca-file=/etc/etcd/pki/etcd-ca.crt
           ```
           and that this CA is not the general Kubernetes cluster CA used by other components.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify the etcd static pod manifest or its TLS configuration. This finding must be fixed directly on each etcd node by editing `/etc/kubernetes/manifests/etcd.yaml` and the underlying CA files; follow the Manual Steps section for the required host-level changes.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Automation: Ensure a dedicated --trusted-ca-file is configured for etcd
        #
        # Runs on: every etcd node (typically every control plane node)
        # Requirements:
        #   - This script must be run as root on each etcd node.
        #   - A dedicated etcd CA file must already exist at /etc/kubernetes/pki/etcd/ca.crt
        #     (or adjust ETCD_CA_FILE below to your chosen dedicated etcd CA path).
        #
        # Behavior:
        #   - Backs up /etc/kubernetes/manifests/etcd.yaml once.
        #   - Ensures --trusted-ca-file=<ETCD_CA_FILE> is present in etcd command args.
        #   - Is safe to re-run.
        #   - Triggers an etcd restart via kubelet because the static pod manifest changes.
        #   - Verifies configuration via container inspection and process listing.
        /usr/bin/id -u | /usr/bin/grep -q '^0$' || {
          echo "ERROR: This script must be run as root." >&2
          exit 1
        }

        ETCD_MANIFEST="/etc/kubernetes/manifests/etcd.yaml"
        BACKUP_MANIFEST="/etc/kubernetes/manifests/etcd.yaml.cis-2.7.bak"
        # Path to the dedicated etcd CA. Adjust if your CA is elsewhere.
        ETCD_CA_FILE="/etc/kubernetes/pki/etcd/ca.crt"

        set -euo pipefail

        echo "==> Verifying prerequisites"

        if [ ! -f "$ETCD_MANIFEST" ]; then
          echo "ERROR: etcd manifest not found at $ETCD_MANIFEST. Are you on an etcd/control plane node?" >&2
          exit 1
        fi

        if [ ! -f "$ETCD_CA_FILE" ]; then
          echo "ERROR: etcd CA file not found at $ETCD_CA_FILE." >&2
          echo "Create a dedicated etcd CA per etcd documentation, then re-run this script." >&2
          exit 1
        fi

        echo "==> Backing up etcd manifest (one-time)"

        if [ ! -f "$BACKUP_MANIFEST" ]; then
          cp -p "$ETCD_MANIFEST" "$BACKUP_MANIFEST"
          echo "Backup created at $BACKUP_MANIFEST"
        else
          echo "Backup already exists at $BACKUP_MANIFEST; not overwriting."
        fi

        echo "==> Ensuring --trusted-ca-file is configured for etcd"

        # If the correct --trusted-ca-file is already present, no change is needed.
        if /usr/bin/grep -q -- "--trusted-ca-file=${ETCD_CA_FILE}" "$ETCD_MANIFEST"; then
          echo "etcd manifest already includes --trusted-ca-file=${ETCD_CA_FILE}; no update required."
        else
          # Remove any existing --trusted-ca-file argument lines to avoid conflicts.
          # This is conservative and idempotent.
          TMP_MANIFEST="$(mktemp)"
          /usr/bin/grep -v -- "--trusted-ca-file=" "$ETCD_MANIFEST" > "$TMP_MANIFEST"

          # Insert the correct argument. We do a simple append to the command args section.
          # This assumes etcd is run as a static pod with a 'command:' list
          # which is the default for kubeadm-based clusters.
          if /usr/bin/grep -q 'command:' "$TMP_MANIFEST"; then
            # Append the argument as a new list item after the 'command:' section.
            # This awk preserves all existing content and adds the flag in the command args list.
            awk -v ca_arg="    - --trusted-ca-file=${ETCD_CA_FILE}" '
              /command:/ && in_cmd==0 {
                print $0
                in_cmd=1
                next
              }
              in_cmd==1 && /^\s*- / {
                print $0
                last_cmd_line=NR
                next
              }
              in_cmd==1 && !/^\s*- / {
                if (!inserted) {
                  print ca_arg
                  inserted=1
                }
                in_cmd=0
                print $0
                next
              }
              {
                print $0
              }
              END {
                if (in_cmd==1 && !inserted) {
                  print ca_arg
                }
              }
            ' "$TMP_MANIFEST" > "${TMP_MANIFEST}.new"
            mv "${TMP_MANIFEST}.new" "$TMP_MANIFEST"
          else
            # If no explicit command list found, just append comment + flag for manual adjustment.
            echo "# Added by CIS 2.7 automation: ensure etcd uses a dedicated trusted CA" >> "$TMP_MANIFEST"
            echo "# NOTE: Add the following to the etcd container command/args if not picked up automatically:" >> "$TMP_MANIFEST"
            echo "# --trusted-ca-file=${ETCD_CA_FILE}" >> "$TMP_MANIFEST"
          fi

          mv "$TMP_MANIFEST" "$ETCD_MANIFEST"
          echo "Updated $ETCD_MANIFEST with --trusted-ca-file=${ETCD_CA_FILE}"
          echo "NOTE: Because this is a static pod manifest, kubelet will restart the etcd pod automatically."
        fi

        echo "==> Waiting for etcd pod to restart (up to 60 seconds)"
        # Give kubelet a short time window to restart etcd after manifest change.
        sleep 10

        echo "==> Verification step 1: confirm etcd process has the correct --trusted-ca-file flag"
        /bin/ps -ef | /bin/grep etcd | /bin/grep -v grep || {
          echo "WARNING: etcd process not found in ps output. Check kubelet and etcd pod status." >&2
        }

        if /bin/ps -ef | /bin/grep etcd | /bin/grep -v grep | /bin/grep -q -- "--trusted-ca-file=${ETCD_CA_FILE}"; then
          echo "Verification OK: etcd process is using --trusted-ca-file=${ETCD_CA_FILE}"
        else
          echo "WARNING: etcd process does not show --trusted-ca-file=${ETCD_CA_FILE} in ps output." >&2
          echo "Inspect the etcd pod and container args to ensure the flag is being applied." >&2
        fi

        echo "==> Verification step 2: show current etcd process command line for manual review"
        /bin/ps -ef | /bin/grep etcd | /bin/grep -v grep

        echo "Automation for CIS Kubernetes 2.7 completed on this node."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
