Skip to main content

Kubelet Kubeconfig File Permissions Are Set Restrictive

More Info:

Ensure that the kubelet kubeconfig file has permissions of 644 or more restrictive.

Risk Level

Medium

Address

Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS Critical Security Controls v8
  • CIS OKE
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • Essential 8
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • MITRE ATT&CK (Cloud)
  • NIS2 Directive
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Manual Steps
  1. On every worker node, check whether the kubelet kubeconfig file exists and view its current permissions:

    ls -l /etc/kubernetes/kubelet.conf
  2. If the file exists, set its permissions to 644 (owner read/write, group read, others read):

    chmod 644 /etc/kubernetes/kubelet.conf
  3. (Optional hardening) Ensure the file is owned by root (adjust if needed):

    chown root:root /etc/kubernetes/kubelet.conf
  4. Verify the new permissions match the benchmark requirement on that worker node:

    stat -c permissions=%a /etc/kubernetes/kubelet.conf

    Confirm the output shows:

    permissions=644
Using kubectl

kubectl cannot modify file permissions on worker node files such as /etc/kubernetes/kubelet.conf; this must be corrected directly on each worker node’s host OS. Please follow the guidance in the Manual Steps section to adjust the permissions and verify the fix.

Automation
#!/usr/bin/env bash
#
# Harden kubelet kubeconfig file permissions on all worker nodes.
# Usage:
# 1) Put all worker node hostnames/IPs into workers.txt (one per line).
# 2) Ensure SSH key-based access is configured and sudo is passwordless.
# 3) Run: ./fix-kubelet-kubeconfig-perms.sh
#
# This script is idempotent and safe to re-run.

set -euo pipefail

WORKER_LIST_FILE="workers.txt"
REMOTE_FILE="/etc/kubernetes/kubelet.conf"
DESIRED_MODE="644"

if [[ ! -f "${WORKER_LIST_FILE}" ]]; then
echo "Missing ${WORKER_LIST_FILE}. Create it with one worker node per line."
exit 1
fi

echo "Starting kubelet kubeconfig permission remediation..."
echo "Target file: ${REMOTE_FILE}"
echo "Desired mode: ${DESIRED_MODE}"
echo

while IFS= read -r NODE || [[ -n "$NODE" ]]; do
# Skip empty/comment lines
[[ -z "$NODE" || "$NODE" =~ ^# ]] && continue

echo "=== Node: ${NODE} ==="

# Check existence
if ! ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new "$NODE" "test -e '${REMOTE_FILE}'" 2>/dev/null; then
echo " [WARN] ${REMOTE_FILE} not found on ${NODE}, skipping."
continue
fi

# Get current permissions
CURRENT_MODE=$(ssh -o BatchMode=yes "$NODE" "stat -c '%a' '${REMOTE_FILE}'" 2>/dev/null || echo "unknown")

if [[ "$CURRENT_MODE" == "unknown" ]]; then
echo " [ERROR] Unable to read current permissions on ${NODE}, skipping."
continue
fi

echo " Current mode: ${CURRENT_MODE}"

# Apply fix only if needed
if [[ "$CURRENT_MODE" != "${DESIRED_MODE}" ]]; then
echo " Updating permissions to ${DESIRED_MODE}..."
ssh -o BatchMode=yes "$NODE" "sudo chmod ${DESIRED_MODE} '${REMOTE_FILE}'"
else
echo " Permissions already set correctly, no change needed."
fi

# Verification (same as audit intent)
VERIFY=$(ssh -o BatchMode=yes "$NODE" "/bin/sh -c 'if test -e ${REMOTE_FILE}; then stat -c permissions=%a ${REMOTE_FILE}; fi'" 2>/dev/null || true)

if [[ "$VERIFY" == "permissions=${DESIRED_MODE}" ]]; then
echo " [OK] Verification passed: ${VERIFY}"
else
echo " [FAIL] Verification FAILED, got: ${VERIFY}"
fi

echo
done < "${WORKER_LIST_FILE}"

echo "Remediation complete."

Additional Reading: