> ## 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 Peer Cert File And Peer Key File Arguments Are Appropriate

### More Info:

etcd should be configured to make use of TLS encryption for peer connections.

### 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 etcd (control plane) node, back up the existing static pod manifest and inspect current peer TLS flags:
           ```bash theme={null}
           sudo cp -a /etc/kubernetes/manifests/etcd.yaml /etc/kubernetes/manifests/etcd.yaml.backup.$(date +%F-%H%M%S)
           sudo grep -E 'peer-(cert-file|key-file)' /etc/kubernetes/manifests/etcd.yaml || echo "No peer TLS flags currently set"
           ```

        2. On every etcd node, ensure peer certificate and key files exist on the host (adjust paths as needed for your environment) and set secure permissions:
           ```bash theme={null}
           ls -l /etc/kubernetes/pki/etcd/peer.crt /etc/kubernetes/pki/etcd/peer.key
           sudo chown root:root /etc/kubernetes/pki/etcd/peer.crt /etc/kubernetes/pki/etcd/peer.key
           sudo chmod 600 /etc/kubernetes/pki/etcd/peer.key
           sudo chmod 644 /etc/kubernetes/pki/etcd/peer.crt
           ```
           If these files do not exist, generate or obtain appropriate etcd peer TLS certs/keys following your PKI/etcd documentation before proceeding.

        3. On every etcd node, edit the etcd static pod manifest to configure the peer TLS flags (this change will automatically restart etcd on save):
           ```bash theme={null}
           sudo vi /etc/kubernetes/manifests/etcd.yaml
           ```
           Under the `command:` section for the `etcd` container, add or update the following arguments (ensure they match your actual certificate paths):
           ```yaml theme={null}
           - --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
           - --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
           ```
           Save and exit the editor; kubelet will restart the etcd pod with the new configuration.

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

        5. On any control plane node, validate that etcd is now running with the correct peer TLS flags:
           ```bash theme={null}
           /bin/ps -ef | /bin/grep etcd | /bin/grep -v grep
           ```
           Inspect the output and confirm it includes both:
           * `--peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt`
           * `--peer-key-file=/etc/kubernetes/pki/etcd/peer.key`
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify the etcd static pod manifest or its process flags under `/etc/kubernetes/manifests/etcd.yaml` on the control plane node. To configure the `--peer-cert-file` and `--peer-key-file` arguments, make the changes directly on the host as described in the Manual Steps section.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Automates remediation for:
        # "Ensure Peer Cert File And Peer Key File Arguments Are Appropriate" (CIS Kubernetes 2.4)
        #
        # Scope: Run on every etcd node (typically every control plane node) with root privileges.
        #
        # This script:
        #   - Backs up /etc/kubernetes/manifests/etcd.yaml
        #   - Ensures --peer-cert-file and --peer-key-file flags are present and set
        #   - Leaves any existing values unchanged if they already point to the desired paths
        #   - Verifies the running etcd process flags at the end
        #
        # NOTE: Editing /etc/kubernetes/manifests/etcd.yaml restarts the etcd static pod automatically.
        # NOTE: You MUST set the correct certificate/key paths below before running.
        #

        set -euo pipefail

        ### >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        ### USER-CONFIGURABLE VALUES – ADJUST THESE PATHS IF NEEDED
        ### >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

        PEER_CERT_FILE_PATH="/etc/kubernetes/pki/etcd/peer.crt"
        PEER_KEY_FILE_PATH="/etc/kubernetes/pki/etcd/peer.key"

        ETCD_MANIFEST="/etc/kubernetes/manifests/etcd.yaml"
        BACKUP_DIR="/etc/kubernetes/manifests/backup-etcd-peer-tls"
        TIMESTAMP="$(date +%Y%m%d-%H%M%S)"

        ### >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        ### PRECHECKS
        ### >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

        if [[ $EUID -ne 0 ]]; then
          echo "ERROR: This script must be run as root on the etcd node."
          exit 1
        fi

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

        if [[ ! -f "$PEER_CERT_FILE_PATH" ]]; then
          echo "ERROR: Peer certificate file not found at $PEER_CERT_FILE_PATH"
          echo "Create or place the correct etcd peer TLS certificate at this path, or update PEER_CERT_FILE_PATH in this script."
          exit 1
        fi

        if [[ ! -f "$PEER_KEY_FILE_PATH" ]]; then
          echo "ERROR: Peer key file not found at $PEER_KEY_FILE_PATH"
          echo "Create or place the correct etcd peer TLS key at this path, or update PEER_KEY_FILE_PATH in this script."
          exit 1
        fi

        ### >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        ### BACKUP
        ### >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

        mkdir -p "$BACKUP_DIR"
        cp -a "$ETCD_MANIFEST" "$BACKUP_DIR/etcd.yaml.$TIMESTAMP.bak"
        echo "Backup created at $BACKUP_DIR/etcd.yaml.$TIMESTAMP.bak"

        ### >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        ### UPDATE ETCD MANIFEST
        ### >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        #
        # Strategy:
        #   - If args array exists: ensure both flags exist with desired values
        #   - If args array does not exist: create it and include both flags
        #

        # Helper: ensure a YAML args entry exists and has the desired value
        ensure_arg() {
          local flag="$1"   # e.g. --peer-cert-file
          local value="$2"  # e.g. /etc/kubernetes/pki/etcd/peer.crt

          # If flag exists, replace its value; otherwise, append a new item
          if grep -qE "^\s*-\s*${flag}=" "$ETCD_MANIFEST"; then
            # Replace line in-place
            sed -i -E "s#^(\s*)-\s*${flag}=.*#\1- ${flag}=${value}#g" "$ETCD_MANIFEST"
          else
            # Append under the existing args: list
            # If args: block exists, append, else create it under the etcd container spec.
            if grep -qE "^\s*args:\s*$" "$ETCD_MANIFEST"; then
              # Append just after the args: block (first occurrence)
              awk -v flag="${flag}" -v value="${value}" '
                BEGIN {added=0}
                {
                  print $0
                  if (!added && $0 ~ /^\s*args:\s*$/) {
                    # Determine indentation from this line and use 2 more spaces for list items
                    match($0, /^([[:space:]]*)args:/, m)
                    indent=m[1]"  "
                    print indent"- "flag"="value
                    added=1
                  }
                }
              ' "$ETCD_MANIFEST" > "${ETCD_MANIFEST}.tmp"
              mv "${ETCD_MANIFEST}.tmp" "$ETCD_MANIFEST"
            else
              # No args: block – inject a minimal one into the first container spec
              awk -v flag="${flag}" -v value="${value}" '
                BEGIN {inserted=0}
                {
                  print $0
                  # Look for the first occurrence of "image:" in the etcd container to inject args after it.
                  if (!inserted && $0 ~ /^\s*image:\s*.*etcd/) {
                    match($0, /^([[:space:]]*)image:/, m)
                    indent=m[1]
                    argsindent=indent
                    listindent=argsindent"  "
                    print argsindent"args:"
                    print listindent"- "flag"="value
                    inserted=1
                  }
                }
              ' "$ETCD_MANIFEST" > "${ETCD_MANIFEST}.tmp"
              mv "${ETCD_MANIFEST}.tmp" "$ETCD_MANIFEST"
            fi
          fi
        }

        echo "Ensuring --peer-cert-file is set to ${PEER_CERT_FILE_PATH}"
        ensure_arg "--peer-cert-file" "${PEER_CERT_FILE_PATH}"

        echo "Ensuring --peer-key-file is set to ${PEER_KEY_FILE_PATH}"
        ensure_arg "--peer-key-file" "${PEER_KEY_FILE_PATH}"

        echo "Updated $ETCD_MANIFEST. The kubelet will restart the etcd static pod automatically."

        ### >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        ### VERIFICATION
        ### >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        #
        # Wait for etcd to restart and then confirm flags.
        #

        echo "Waiting up to 60 seconds for etcd process to restart with new flags..."
        sleep 10

        # Simple retry loop
        RETRIES=12
        SLEEP_BETWEEN=5
        SUCCESS=0

        for i in $(seq 1 $RETRIES); do
          if /bin/ps -ef | /bin/grep '[e]tcd' >/dev/null 2>&1; then
            if /bin/ps -ef | /bin/grep '[e]tcd' | grep -q -- "--peer-cert-file=${PEER_CERT_FILE_PATH}"; then
              if /bin/ps -ef | /bin/grep '[e]tcd' | grep -q -- "--peer-key-file=${PEER_KEY_FILE_PATH}"; then
                SUCCESS=1
                break
              fi
            fi
          fi
          sleep "$SLEEP_BETWEEN"
        done

        echo
        echo "Current etcd process command line:"
        /bin/ps -ef | /bin/grep '[e]tcd' || true
        echo

        if [[ "$SUCCESS" -eq 1 ]]; then
          echo "VERIFICATION PASSED: etcd is running with:"
          echo "  --peer-cert-file=${PEER_CERT_FILE_PATH}"
          echo "  --peer-key-file=${PEER_KEY_FILE_PATH}"
          exit 0
        else
          echo "VERIFICATION WARNING: etcd process does not show the expected peer TLS flags after waiting."
          echo "Review $ETCD_MANIFEST and kubelet/etcd logs. The audit command is:"
          echo "  /bin/ps -ef | /bin/grep etcd | /bin/grep -v grep"
          exit 1
        fi
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://coreos.com/etcd/docs/latest/op-guide/security.html](https://coreos.com/etcd/docs/latest/op-guide/security.html)
