Skip to main content

Kubelet Only Makes Use Of Strong Cryptographic Ciphers

More Info:

Restricting tlsCipherSuites to strong ciphers prevents the kubelet from negotiating weak or deprecated cryptographic algorithms. This hardens the confidentiality of kubelet TLS connections.

Risk Level

Medium

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. On every worker node, back up the existing kubelet config and (if present) the systemd drop-in:

    sudo cp -a /var/lib/kubelet/config.yaml /var/lib/kubelet/config.yaml.bak.$(date +%s) || true
    sudo cp -a /etc/systemd/system/kubelet.service.d/10-kubeadm.conf /etc/systemd/system/kubelet.service.d/10-kubeadm.conf.bak.$(date +%s) 2>/dev/null || true
  2. On every worker node, edit /var/lib/kubelet/config.yaml to define strong ciphers in the Kubelet config file (create or replace the tlsCipherSuites section as needed):

    sudo sed -i '/^tlsCipherSuites:/,$d' /var/lib/kubelet/config.yaml
    sudo tee -a /var/lib/kubelet/config.yaml >/dev/null <<'EOF'

tlsCipherSuites:

  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 EOF

3. On every worker node, if the kubelet is configured via flags, ensure `--tls-cipher-suites` is set in the systemd drop-in (adjust this file only if your kubelet actually uses it):
```bash
if [ -f /etc/systemd/system/kubelet.service.d/10-kubeadm.conf ]; then
sudo sed -i '/--tls-cipher-suites=/d' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
sudo sed -i 's#^\(ExecStart=.*kubelet\b\)\(.*\)$#\1\2 --tls-cipher-suites=TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384#' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
fi
  1. On every worker node, reload systemd and restart the kubelet (this will disrupt kubelet on the node briefly, so do this node by node):

    sudo systemctl daemon-reload
    sudo systemctl restart kubelet.service
  2. On every worker node, confirm the kubelet process is running with the desired cipher suites flag (if you use flags) and that it has restarted successfully:

    /bin/ps -fC kubelet
    sudo systemctl status kubelet.service --no-pager
  3. Optionally, on every worker node, confirm that either the config file or the flag now specifies only strong ciphers:

    grep -A10 '^tlsCipherSuites:' /var/lib/kubelet/config.yaml || true
    /bin/ps -fC kubelet | grep -- '--tls-cipher-suites' || true
Using kubectl

kubectl cannot modify kubelet host-level configuration such as /var/lib/kubelet/config.yaml or systemd units on worker nodes. To remediate this finding, you must change the kubelet configuration directly on each worker node; follow the guidance in the Manual Steps section.

Automation
#!/usr/bin/env bash
#
# Harden kubelet TLS cipher suites on every worker node.
# Usage: run as root on each worker node (or via SSH/Ansible).
#

set -euo pipefail

CIPHERS="TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"

KUBELET_CONFIG_FILE="/var/lib/kubelet/config.yaml"
KUBELET_SYSTEMD_DROPIN="/etc/systemd/system/kubelet.service.d/10-kubeadm.conf"

echo "==> Hardening kubelet TLS cipher suites on node: $(hostname)"

# Ensure jq and yq are available if needed
need_cmd() {
command -v "$1" >/dev/null 2>&1 || {
echo "ERROR: required command '$1' not found in PATH" >&2
exit 1
}
}

# Prefer config file if it exists; otherwise fall back to systemd flag
if [ -f "$KUBELET_CONFIG_FILE" ]; then
echo "==> Detected kubelet config file at $KUBELET_CONFIG_FILE"

need_cmd yq

# Backup once per run if not already backed up in this session
BACKUP="${KUBELET_CONFIG_FILE}.$(date +%Y%m%d%H%M%S).bak"
cp -p "$KUBELET_CONFIG_FILE" "$BACKUP"
echo " Backup created: $BACKUP"

# Idempotently set tlsCipherSuites
TMP_FILE="$(mktemp)"
yq -y ".tlsCipherSuites = [\"${CIPHERS//,/\",\"}\"]" "$KUBELET_CONFIG_FILE" > "$TMP_FILE"
chmod --reference="$KUBELET_CONFIG_FILE" "$TMP_FILE"
mv "$TMP_FILE" "$KUBELET_CONFIG_FILE"

echo " Updated tlsCipherSuites in $KUBELET_CONFIG_FILE"

else
echo "==> No kubelet config file at $KUBELET_CONFIG_FILE, using systemd flags"

if [ ! -f "$KUBELET_SYSTEMD_DROPIN" ]; then
echo "ERROR: $KUBELET_SYSTEMD_DROPIN not found; cannot set --tls-cipher-suites flag automatically." >&2
echo "Create the file and define kubelet ExecStart with the desired --tls-cipher-suites." >&2
exit 1
fi

# Backup
BACKUP="${KUBELET_SYSTEMD_DROPIN}.$(date +%Y%m%d%H%M%S).bak"
cp -p "$KUBELET_SYSTEMD_DROPIN" "$BACKUP"
echo " Backup created: $BACKUP"

# Idempotently ensure --tls-cipher-suites flag is present with desired value
TMP_FILE="$(mktemp)"
# For simplicity and safety, replace any existing --tls-cipher-suites=... with the desired value,
# or append it if missing, only on the ExecStart line.
awk -v ciphers="$CIPHERS" '
/^ExecStart=/ {
# Remove existing --tls-cipher-suites=... occurrences
gsub(/--tls-cipher-suites=[^ ]+/, "")
# Ensure a single space before appending the flag
sub(/[[:space:]]*$/,"")
print $0 " --tls-cipher-suites=" ciphers
next
}
{ print }
' "$KUBELET_SYSTEMD_DROPIN" > "$TMP_FILE"

chmod --reference="$KUBELET_SYSTEMD_DROPIN" "$TMP_FILE"
mv "$TMP_FILE" "$KUBELET_SYSTEMD_DROPIN"

echo " Updated --tls-cipher-suites in $KUBELET_SYSTEMD_DROPIN"
fi

echo "==> Restarting kubelet (this will briefly disrupt workloads on this node)"
systemctl daemon-reload
systemctl restart kubelet.service

sleep 3

echo "==> Verification: kubelet process and configuration"

# 1) Show kubelet process (as per audit command)
echo "---- kubelet process (ps -fC kubelet) ----"
if ! /bin/ps -fC kubelet; then
echo "ERROR: kubelet process not found after restart." >&2
exit 1
fi

# 2) Verify effective setting depending on method
if [ -f "$KUBELET_CONFIG_FILE" ]; then
need_cmd yq
echo "---- tlsCipherSuites from $KUBELET_CONFIG_FILE ----"
yq '.tlsCipherSuites' "$KUBELET_CONFIG_FILE"
else
echo "---- ExecStart from $KUBELET_SYSTEMD_DROPIN ----"
sed -n 's/^ExecStart=/ExecStart=/p' "$KUBELET_SYSTEMD_DROPIN"
fi

echo "==> Completed on node: $(hostname)"