Ensure Etcd Cafile Argument Is Appropriate
More Info:
etcd should be configured to make use of TLS encryption for client connections.
Risk Level
Low
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
On every control plane node, confirm the current kube-apiserver manifest and running args:
sudo cat /etc/kubernetes/manifests/kube-apiserver.yaml/bin/ps -ef | grep kube-apiserver | grep -v grep -
Ensure you have a CA file that issued the etcd server/client certificates (replace the path below with the actual CA if different):
ls -l /etc/kubernetes/pki/etcd/ca.crtsudo chmod 600 /etc/kubernetes/pki/etcd/ca.crtsudo chown root:root /etc/kubernetes/pki/etcd/ca.crt -
Edit the kube-apiserver static pod manifest on every control plane node to add or correct the
--etcd-cafileflag (this edit will automatically restart the kube-apiserver container when the file is saved):sudo vi /etc/kubernetes/manifests/kube-apiserver.yamlUnder
spec.containers[0].command, ensure there is a line similar to:- --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crtSave and exit the editor.
-
(If etcd is external and using different CA) Adjust the path in step 3 to the correct etcd CA file, and make sure the file exists and is readable by root:
ls -l /path/to/etcd-ca.crtsudo chmod 600 /path/to/etcd-ca.crtsudo chown root:root /path/to/etcd-ca.crt -
Wait for the kubelet to detect the manifest change and restart the kube-apiserver pod. Confirm the pod is running:
sudo crictl ps | grep kube-apiserver || sudo docker ps | grep kube-apiserver -
Verify the kube-apiserver is now started with the correct
--etcd-cafileargument on every control plane node:/bin/ps -ef | grep kube-apiserver | grep -v grep | grep -- '--etcd-cafile='
Using kubectl
kubectl cannot modify the kube-apiserver static pod manifest or its process flags, so it cannot be used to set the --etcd-cafile argument. To remediate this finding, you must edit /etc/kubernetes/manifests/kube-apiserver.yaml directly on every control plane node as described in the Manual Steps section.
Automation
#!/usr/bin/env bash
#
# Fix: Ensure kube-apiserver is configured with --etcd-cafile
# Scope: every control plane node
#
# Requirements:
# - Run as root on each control plane node
# - Static pod manifest at /etc/kubernetes/manifests/kube-apiserver.yaml
# - etcd CA file present at /etc/kubernetes/pki/etcd/ca.crt (adjust ETCD_CA_FILE below if different)
set -euo pipefail
MANIFEST="/etc/kubernetes/manifests/kube-apiserver.yaml"
BACKUP_DIR="/etc/kubernetes/manifests/backup-$(date +%Y%m%d)"
ETCD_CA_FILE="/etc/kubernetes/pki/etcd/ca.crt"
echo "[INFO] Verifying prerequisites..."
if [[ $EUID -ne 0 ]]; then
echo "[ERROR] This script must be run as root." >&2
exit 1
fi
if [[ ! -f "$MANIFEST" ]]; then
echo "[ERROR] kube-apiserver manifest not found at $MANIFEST" >&2
exit 1
fi
if [[ ! -f "$ETCD_CA_FILE" ]]; then
echo "[ERROR] Etcd CA file not found at $ETCD_CA_FILE" >&2
echo "[HINT] Place the correct etcd CA file on this node and update ETCD_CA_FILE in this script if needed." >&2
exit 1
fi
mkdir -p "$BACKUP_DIR"
BACKUP_FILE="$BACKUP_DIR/kube-apiserver.yaml.$(date +%H%M%S)"
cp -p "$MANIFEST" "$BACKUP_FILE"
echo "[INFO] Backup created at $BACKUP_FILE"
echo "[INFO] Ensuring --etcd-cafile is configured in kube-apiserver manifest..."
# If argument already present, update its value in-place; otherwise, add it.
if grep -q -- "--etcd-cafile=" "$MANIFEST"; then
# Idempotent replacement of existing value
sed -i "s#--etcd-cafile=.*#--etcd-cafile=${ETCD_CA_FILE}#g" "$MANIFEST"
else
# Insert argument under the 'command:' section for kube-apiserver
# This keeps the YAML valid and is safe to re-run (guarded by grep above).
awk -v cafile="$ETCD_CA_FILE" '
$0 ~ /- kube-apiserver$/ && in_cmd == 0 {
print $0
in_cmd=1
next
}
in_cmd == 1 && $0 ~ /^ *-/ {
# First argument line after the binary; insert our flag before it once
if (!inserted) {
print " - --etcd-cafile=" cafile
inserted=1
}
print $0
next
}
{ print $0 }
END {
if (!inserted) {
# If we never saw arguments, append the flag at the end of the file
print " - --etcd-cafile=" cafile
}
}
' "$MANIFEST" > "${MANIFEST}.tmp" && mv "${MANIFEST}.tmp" "$MANIFEST"
fi
echo "[INFO] Manifest updated. kube-apiserver static pod will be restarted automatically by kubelet."
echo "[INFO] Waiting for kube-apiserver process to reflect new flag..."
# Give kubelet time to restart the static pod
sleep 20
# Verification: confirm kube-apiserver is running with the correct --etcd-cafile argument
echo "[INFO] Verifying kube-apiserver process flags..."
if /bin/ps -ef | grep kube-apiserver | grep -v grep | grep -q -- "--etcd-cafile=${ETCD_CA_FILE}"; then
echo "[SUCCESS] kube-apiserver is running with --etcd-cafile=${ETCD_CA_FILE}"
exit 0
else
echo "[ERROR] kube-apiserver is NOT running with the expected --etcd-cafile flag." >&2
echo "[INFO] Current kube-apiserver process line(s):" >&2
/bin/ps -ef | grep kube-apiserver | grep -v grep >&2
exit 1
fi