> ## 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 Etcd Cert-File And Key-File Arguments Are Set

### More Info:

The etcd server must be configured with the --cert-file and --key-file arguments so that client-to-server traffic is served over TLS. Without them, etcd traffic carrying all cluster state and secrets is unencrypted.

### 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. On every etcd (control plane) node, confirm the static pod manifest location and current etcd flags:
           ```bash theme={null}
           sudo ls -l /etc/kubernetes/manifests/etcd.yaml
           ps -ef | grep etcd | grep -v grep
           ```

        2. On every etcd node, ensure a certificate and key exist for the etcd server (adjust CN/SANs as needed for your environment):
           ```bash theme={null}
           sudo mkdir -p /etc/etcd/pki
           cd /etc/etcd/pki

           sudo openssl req -newkey rsa:4096 -nodes -keyout etcd.key \
             -x509 -days 365 -out etcd.crt \
             -subj "/CN=etcd.local"
           sudo chmod 600 /etc/etcd/pki/etcd.key
           sudo chmod 644 /etc/etcd/pki/etcd.crt
           ```

        3. On every etcd node, back up the existing etcd static pod manifest:
           ```bash theme={null}
           sudo cp -a /etc/kubernetes/manifests/etcd.yaml /etc/kubernetes/manifests/etcd.yaml.bak
           ```

        4. On every etcd node, edit `/etc/kubernetes/manifests/etcd.yaml` to add the `--cert-file` and `--key-file` arguments to the etcd container command. For example, in the `spec.containers[0].command` list, ensure lines like the following are present (paths must match where you stored the cert and key):
           ```yaml theme={null}
           - --cert-file=/etc/etcd/pki/etcd.crt
           - --key-file=/etc/etcd/pki/etcd.key
           ```
           Save the file. The kubelet will automatically restart the etcd static pod when the manifest changes.

        5. On every etcd node, confirm the etcd pod has restarted successfully:
           ```bash theme={null}
           sudo crictl ps | grep etcd || sudo docker ps | grep etcd
           ```

        6. On every etcd node, verify that the running etcd process includes the required flags:
           ```bash theme={null}
           /bin/ps -ef | /bin/grep etcd | /bin/grep -v grep
           ```
           Ensure the output shows both `--cert-file=/etc/etcd/pki/etcd.crt` and `--key-file=/etc/etcd/pki/etcd.key` (or your chosen paths).
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify the etcd static pod manifest or its process flags; this finding must be fixed directly on each etcd node by editing `/etc/kubernetes/manifests/etcd.yaml`. See the Manual Steps section for the exact host-level changes required.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Remediate: Ensure Etcd --cert-file and --key-file Arguments Are Set
        #
        # Usage (on each etcd/control-plane node):
        #   sudo ETCD_CERT_FILE=/etc/kubernetes/pki/etcd/server.crt \
        #        ETCD_KEY_FILE=/etc/kubernetes/pki/etcd/server.key \
        #        bash ./fix-etcd-cert-key.sh
        #
        # Idempotent: safe to re-run; only adds/updates args if needed.
        # This script edits /etc/kubernetes/manifests/etcd.yaml; kubelet
        # will automatically restart the etcd static pod.

        set -euo pipefail

        ETCD_MANIFEST="/etc/kubernetes/manifests/etcd.yaml"

        # --------- Configuration (must be set via environment) ---------
        CERT_FILE="${ETCD_CERT_FILE:-}"
        KEY_FILE="${ETCD_KEY_FILE:-}"

        if [[ -z "$CERT_FILE" || -z "$KEY_FILE" ]]; then
          echo "ERROR: ETCD_CERT_FILE and ETCD_KEY_FILE environment variables must be set."
          echo "Example:"
          echo "  sudo ETCD_CERT_FILE=/etc/kubernetes/pki/etcd/server.crt \\"
          echo "       ETCD_KEY_FILE=/etc/kubernetes/pki/etcd/server.key \\"
          echo "       bash $0"
          exit 1
        fi

        if [[ ! -f "$CERT_FILE" ]]; then
          echo "ERROR: Certificate file not found: $CERT_FILE"
          exit 1
        fi

        if [[ ! -f "$KEY_FILE" ]]; then
          echo "ERROR: Key file not found: $KEY_FILE"
          exit 1
        fi

        if [[ ! -f "$ETCD_MANIFEST" ]]; then
          echo "ERROR: etcd manifest not found at $ETCD_MANIFEST"
          exit 1
        fi

        # --------- Backup ---------
        BACKUP="${ETCD_MANIFEST}.$(date +%Y%m%d%H%M%S).bak"
        cp "$ETCD_MANIFEST" "$BACKUP"
        echo "Backup created: $BACKUP"

        # --------- Ensure args present/updated ---------
        # This is done by:
        # - removing any existing --cert-file= / --key-file= entries
        # - appending the desired ones under the etcd container args

        tmpfile="$(mktemp)"
        trap 'rm -f "$tmpfile"' EXIT

        awk -v cert="$CERT_FILE" -v key="$KEY_FILE" '
          BEGIN { in_args=0; done_cert=0; done_key=0 }
          {
            # track when we are inside the etcd container args list
            if ($0 ~ /^[[:space:]]*- name:[[:space:]]*etcd[[:space:]]*$/) {
              in_etcd=1
            }
            if (in_etcd && $0 ~ /^[[:space:]]*args:[[:space:]]*$/) {
              in_args=1
            }

            # If we hit another container or end of containers, stop args tracking
            if (in_etcd && $0 ~ /^[[:space:]]*- name:[[:space:]]*[A-Za-z0-9_-]+[[:space:]]*$/ && $0 !~ /- name: *etcd *$/) {
              in_args=0
              in_etcd=0
            }

            # Filter out existing cert/key args
            if (in_args && $0 ~ /--cert-file=/) next
            if (in_args && $0 ~ /--key-file=/)  next

            print $0

            # After we print the args: line, ensure our desired args exist once
            if (in_args && $0 ~ /^[[:space:]]*args:[[:space:]]*$/) {
              # args: line itself, we will append items later
              next
            }

            # Detect end of args list by a line not starting with "- " but only if we were in args
            if (in_args && $0 !~ /^[[:space:]]*-[[:space:]]*"/ && $0 !~ /^[[:space:]]*-[[:space:]]*--/ && $0 !~ /^[[:space:]]*-[[:space:]]*$/) {
              if (!done_cert) {
                print "    - \"--cert-file=" cert "\""
                done_cert=1
              }
              if (!done_key) {
                print "    - \"--key-file=" key "\""
                done_key=1
              }
              in_args=0
            }
          }
        ' "$ETCD_MANIFEST" > "$tmpfile"

        # If awk failed to inject (e.g., unusual manifest structure), fall back to a simpler patch:
        if ! grep -q -- "--cert-file=${CERT_FILE}" "$tmpfile" || ! grep -q -- "--key-file=${KEY_FILE}" "$tmpfile"; then
          echo "Notice: Applying fallback patch logic for args section."

          # Fallback: insert/replace within the etcd container args block using sed
          # 1. Remove existing --cert-file/--key-file lines
          sed -i '/--cert-file=/d' "$ETCD_MANIFEST"
          sed -i '/--key-file=/d' "$ETCD_MANIFEST"

          # 2. Append desired args after the `args:` line for the etcd container
          #    This is heuristic but safe to re-run (duplicates are removed first)
          sed -i "/- name: etcd/{n;/[[:space:]]*args:/{
            a\    - \"--cert-file=${CERT_FILE}\"\n    - \"--key-file=${KEY_FILE}\"
          }}" "$ETCD_MANIFEST"

          tmpfile="$ETCD_MANIFEST"
        else
          mv "$tmpfile" "$ETCD_MANIFEST"
        fi

        echo "Updated $ETCD_MANIFEST with:"
        echo "  --cert-file=${CERT_FILE}"
        echo "  --key-file=${KEY_FILE}"
        echo "kubelet will restart the etcd static pod automatically."

        # --------- Verification ---------
        echo "Waiting for etcd process to reflect new arguments..."
        sleep 10

        echo "Current etcd process command line:"
        /bin/ps -ef | /bin/grep etcd | /bin/grep -v grep || {
          echo "WARNING: etcd process not found. Check pod status with:"
          echo "  crictl ps | grep etcd   # or   docker ps | grep etcd"
          exit 1
        }

        if /bin/ps -ef | /bin/grep etcd | /bin/grep -v grep | /bin/grep -q -- "--cert-file=${CERT_FILE}" &&
           /bin/ps -ef | /bin/grep etcd | /bin/grep -v grep | /bin/grep -q -- "--key-file=${KEY_FILE}"; then
          echo "Verification SUCCESS: etcd is running with --cert-file and --key-file set."
        else
          echo "Verification FAILED: etcd process does not show the expected --cert-file/--key-file."
          echo "Inspect /etc/kubernetes/manifests/etcd.yaml and the etcd pod logs."
          exit 1
        fi
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
