API Server Should Set Etcd CA File
More Info:
Verifies that --etcd-cafile is set so the API server verifies the etcd server certificate against a trusted certificate authority.
Risk Level
High
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Log in to each control plane node
ssh root@<control-plane-node-ip> -
Confirm the current ownership of the API server manifest file
stat -c '%n %U:%G' /etc/kubernetes/manifests/kube-apiserver.yaml -
Change the file owner and group to root:root (if not already)
chown root:root /etc/kubernetes/manifests/kube-apiserver.yaml -
(Optional) Reconfirm file permissions are appropriate (readable only by root and system processes)
chmod 600 /etc/kubernetes/manifests/kube-apiserver.yamlls -l /etc/kubernetes/manifests/kube-apiserver.yaml -
Repeat steps 1–4 on every control plane node in the cluster.
-
Verification (on each control plane node)
/bin/sh -c 'if test -e /etc/kubernetes/manifests/kube-apiserver.yaml; then stat -c %U:%G /etc/kubernetes/manifests/kube-apiserver.yaml; fi'
Using kubectl
kubectl cannot modify file ownership or other host-level settings for /etc/kubernetes/manifests/kube-apiserver.yaml on control plane nodes. This finding must be fixed directly on each control plane node’s filesystem; see the Manual Steps section for the exact commands to run over SSH.
Automation
#!/usr/bin/env bash
#
# Automation: Fix ownership of kube-apiserver manifest on control plane nodes
# Target: run on every control plane node (as root)
#
# Usage: sudo /path/to/fix-kube-apiserver-owner.sh
set -euo pipefail
MANIFEST_PATH="/etc/kubernetes/manifests/kube-apiserver.yaml"
DESIRED_OWNER="root"
DESIRED_GROUP="root"
CHANGED=0
echo "Checking kube-apiserver manifest ownership on this control plane node..."
if [ ! -e "${MANIFEST_PATH}" ]; then
echo "WARNING: ${MANIFEST_PATH} does not exist on this node; nothing to do."
exit 0
fi
# Get current ownership
CURRENT_OWNER="$(stat -c %U "${MANIFEST_PATH}")"
CURRENT_GROUP="$(stat -c %G "${MANIFEST_PATH}")"
echo "Current ownership: ${CURRENT_OWNER}:${CURRENT_GROUP}"
echo "Desired ownership: ${DESIRED_OWNER}:${DESIRED_GROUP}"
# Apply fix only if needed
if [ "${CURRENT_OWNER}" != "${DESIRED_OWNER}" ] || [ "${CURRENT_GROUP}" != "${DESIRED_GROUP}" ]; then
echo "Updating ownership to ${DESIRED_OWNER}:${DESIRED_GROUP}..."
chown "${DESIRED_OWNER}:${DESIRED_GROUP}" "${MANIFEST_PATH}"
CHANGED=1
else
echo "Ownership already correct; no change needed."
fi
# Verification (same as audit command)
echo "Verifying ownership..."
VERIFY_OUTPUT="$(stat -c %U:%G "${MANIFEST_PATH}")"
echo "stat -c %U:%G ${MANIFEST_PATH} -> ${VERIFY_OUTPUT}"
if [ "${VERIFY_OUTPUT}" != "${DESIRED_OWNER}:${DESIRED_GROUP}" ]; then
echo "ERROR: Ownership verification failed; expected ${DESIRED_OWNER}:${DESIRED_GROUP}."
exit 1
fi
if [ "${CHANGED}" -eq 1 ]; then
echo "Ownership successfully updated and verified."
else
echo "No changes were required; ownership is correct and verified."
fi
exit 0