Skip to main content

Certificate Authorities File Permissions Are Restrictive

More Info:

Ensure that the certificate authorities file has permissions of 644 or more restrictive.

Risk Level

Medium

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. On every worker node, identify the certificate authority file the kubelet is using:

    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
    printf 'Using CA file: %s\n' "$CAFILE"
  2. On every worker node, review the current permissions and ownership of the CA file:

    stat "$CAFILE"
  3. On every worker node, set the permissions of the CA file to 644 as required:

    chmod 644 "$CAFILE"
  4. (Optional but recommended) On every worker node, ensure the CA file is owned by root:

    chown root:root "$CAFILE"
  5. On every worker node, verify the permissions are now 644 or more restrictive:

    stat -c permissions=%a "$CAFILE"
Using kubectl

kubectl cannot modify file permissions on worker node files such as /var/lib/kubelet/config.yaml or the kubelet --client-ca-file path; this must be fixed directly on every worker node via host-level access (SSH or similar). Refer to the Manual Steps section for the exact commands to correct the certificate authorities file permissions.

Automation
#!/usr/bin/env bash
#
# Automation: Restrict certificate authorities file permissions for kubelet
# Applies to: every worker node (run on each node, e.g. via SSH or Ansible shell)
# Idempotent: safe to re-run

set -euo pipefail

echo "=== Detecting kubelet client CA file ==="

# Try to detect --client-ca-file from kubelet process
CAFILE="$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq || true)"

# Fallback to default if not set
if [ -z "${CAFILE}" ]; then
CAFILE="/etc/kubernetes/pki/ca.crt"
fi

echo "Using client CA file path: ${CAFILE}"

# Check existence
if [ ! -e "${CAFILE}" ]; then
echo "ERROR: Client CA file does not exist: ${CAFILE}" >&2
exit 1
fi

# Show current permissions
CURRENT_PERMS="$(stat -c '%a' "${CAFILE}")"
echo "Current permissions on ${CAFILE}: ${CURRENT_PERMS}"

# Desired permissions: 644 (or more restrictive)
DESIRED_PERMS="644"

# Only relax permissions if they are less restrictive than 644
# (e.g., 666, 664, 777). If already 644 or more restrictive (e.g., 600),
# we leave them as-is to avoid weakening security.
# A simple numeric comparison works for typical cases; if in doubt, we always
# set to 644 for permissions > 644.
if [ "${CURRENT_PERMS}" -gt "${DESIRED_PERMS}" ]; then
echo "Updating permissions on ${CAFILE} to ${DESIRED_PERMS}"
chmod "${DESIRED_PERMS}" "${CAFILE}"
else
echo "Permissions are already 644 or more restrictive; no change needed."
fi

echo "=== Verifying result ==="
# Re-run the benchmark-style check for this node
CAFILE_VERIFY="$(ps -ef | grep kubelet | grep -v apiserver | grep -- --client-ca-file= | awk -F '--client-ca-file=' '{print $2}' | awk '{print $1}' | uniq || true)"
if [ -z "${CAFILE_VERIFY}" ]; then
CAFILE_VERIFY="/etc/kubernetes/pki/ca.crt"
fi

if [ -e "${CAFILE_VERIFY}" ]; then
stat -c "Verified permissions=%a on ${CAFILE_VERIFY}" "${CAFILE_VERIFY}"
else
echo "WARNING: Verification failed; CA file not found at ${CAFILE_VERIFY}" >&2
exit 1
fi

echo "=== Completed on this node ==="

Usage:

  • Run on every worker node, for example:
ssh worker-node-1 'bash -s' < ./fix_kubelet_ca_permissions.sh
ssh worker-node-2 'bash -s' < ./fix_kubelet_ca_permissions.sh

This script:

  • Detects the kubelet --client-ca-file (or defaults to /etc/kubernetes/pki/ca.crt).
  • Sets permissions to 644 only if they are currently less restrictive than 644.
  • Re-runs a verification similar to the audit command and prints the resulting permissions.

Additional Reading: