Skip to main content

Ensure Client Certificate Authorities File Ownership Is Root

More Info:

Ensure that the certificate authorities file ownership is set to root:root.

Risk Level

Low

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. On every worker node, identify the client CA file path used by kubelet:

    CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq)
    if test -z "$CAFILE"; then CAFILE=/etc/kubernetes/pki/ca.crt; fi
    echo "$CAFILE"
  2. Review the file and confirm it is the correct client CA for your environment (to avoid changing ownership on an unintended file):

    ls -l "$CAFILE"
    openssl x509 -in "$CAFILE" -text -noout 2>/dev/null || echo "Not a certificate file, verify manually"

    If this is not the expected CA, stop and determine the correct CA file before proceeding.

  3. Change the file ownership to root:root (only after confirming in step 2):

    sudo chown root:root "$CAFILE"
  4. (Optional but recommended) Restrict permissions to read-only for root if compatible with your tooling:

    sudo chmod 600 "$CAFILE"
  5. Verify the ownership is now root:root using the audit logic on the same worker node:

    CAFILE=$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq)
    if test -z "$CAFILE"; then CAFILE=/etc/kubernetes/pki/ca.crt; fi
    if test -e "$CAFILE"; then stat -c %U:%G "$CAFILE"; fi

    Confirm the output is:

    root:root
Using kubectl

kubectl cannot change file ownership on worker node filesystems, including the kubelet client CA file referenced by /var/lib/kubelet/config.yaml. To fix this finding you must adjust file ownership directly on every worker node at the host level; follow the guidance in the Manual Steps section.

Automation
#!/usr/bin/env bash
#
# Fix CISKubernetes 4.1.8:
# Ensure that the client certificate authorities file ownership is set to root:root
#
# Scope: run on every worker node as root.
# Safe to re-run (idempotent).

set -euo pipefail

echo "=== Detecting kubelet --client-ca-file on this node ==="

# Derive the client CA file path from the running kubelet process, if present.
CAFILE="$(ps -ef \
| grep kubelet \
| grep -v apiserver \
| grep -- '--client-ca-file=' \
| awk -F '--client-ca-file=' '{print $2}' \
| awk '{print $1}' \
| uniq \
| head -n1 || true)"

# Fallback to default if not detected from process
if [ -z "${CAFILE}" ]; then
CAFILE="/etc/kubernetes/pki/ca.crt"
echo "No --client-ca-file flag detected; falling back to default: ${CAFILE}"
else
echo "Detected --client-ca-file: ${CAFILE}"
fi

# If the file does not exist, report and exit non-zero for visibility
if [ ! -e "${CAFILE}" ]; then
echo "ERROR: Client CA file does not exist: ${CAFILE}" >&2
exit 1
fi

echo "=== Current ownership of ${CAFILE} ==="
stat -c '%n %U:%G %a' "${CAFILE}"

# Apply remediation: ensure owner and group are root:root
echo "=== Setting ownership to root:root on ${CAFILE} ==="
chown root:root "${CAFILE}"

# Verification (adapted from audit command)
echo "=== Verifying ownership of client CA file ==="
OWNERSHIP="$(stat -c '%U:%G' "${CAFILE}")"
echo "Ownership after change: ${OWNERSHIP}"

if [ "${OWNERSHIP}" = "root:root" ]; then
echo "SUCCESS: ${CAFILE} is owned by root:root"
exit 0
else
echo "FAILURE: ${CAFILE} ownership is not root:root (got ${OWNERSHIP})" >&2
exit 1
fi

Usage (on every worker node, as root):

chmod +x /usr/local/sbin/fix-kubelet-client-ca-ownership.sh
/usr/local/sbin/fix-kubelet-client-ca-ownership.sh

Additional Reading: