Ensure Kubelet Only Makes Use Strong Cryptographic Ciphers
More Info:
Ensure that the Kubelet is configured to only use strong cryptographic ciphers.
Risk Level
Medium
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
On every worker node, back up the existing kubelet config and systemd drop-in (if present):
sudo cp -a /var/lib/kubelet/config.yaml /var/lib/kubelet/config.yaml.bak.$(date +%F_%H%M%S) 2>/dev/null || truesudo cp -a /etc/systemd/system/kubelet.service.d/10-kubeadm.conf /etc/systemd/system/kubelet.service.d/10-kubeadm.conf.bak.$(date +%F_%H%M%S) 2>/dev/null || true -
On every worker node, configure strong ciphers in the kubelet config file
/var/lib/kubelet/config.yaml(if the file exists and is used) by adding or updating thetlsCipherSuitesfield under the top-level config (create the list if missing):sudo sed -i '/^tlsCipherSuites:/d' /var/lib/kubelet/config.yaml 2>/dev/null || truesudo 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
Adjust placement/indentation if your file has a different structure; ensure it is valid YAML.
3. On every worker node, configure strong ciphers via kubelet arguments (if the kubelet is started with flags via systemd) by editing `/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` and setting `--tls-cipher-suites` to the approved list (either add or replace an existing value). Open the file in an editor:
```bash
sudo vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
Ensure the KUBELET_CONFIG_ARGS / KUBELET_EXTRA_ARGS / ExecStart= line contains:
--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
Save and exit. If both the config file and flags specify ciphers, ensure they are consistent; prefer the config file as the single source where possible.
-
On every worker node, reload systemd and restart kubelet (note: restarting kubelet temporarily disrupts node-level operations and may evict or reschedule pods depending on your cluster configuration):
sudo systemctl daemon-reloadsudo systemctl restart kubelet.service -
On every worker node, verify that the kubelet process is running and (if started via flags) that the
--tls-cipher-suitesargument reflects only the strong cipher list:/bin/ps -fC kubeletConfirm the output shows kubelet running and, where applicable, includes:
--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.
Using kubectl
kubectl cannot configure kubelet’s TLS cipher suites because this setting lives in host-level files and flags on each worker node (for example /var/lib/kubelet/config.yaml or the kubelet systemd unit). To remediate this finding, follow the guidance in the Manual Steps section directly on every worker node.
Automation
#!/usr/bin/env bash
#
# Harden kubelet TLS cipher suites on every worker node.
# Usage: run on each worker node as root (e.g. via SSH or Ansible shell).
# Safe to re-run; it will update config only when needed.
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="/var/lib/kubelet/config.yaml"
KUBELET_SYSTEMD_DROPIN="/etc/systemd/system/kubelet.service.d/10-kubeadm.conf"
changed_config=0
changed_systemd=0
echo "==> Hardening kubelet TLS cipher suites on host: $(hostname)"
#------------------------------
# 1) Ensure tlsCipherSuites in kubelet config file (if present)
#------------------------------
if [ -f "$KUBELET_CONFIG" ]; then
echo "-> Detected kubelet config file: $KUBELET_CONFIG"
# Backup once per day (simple rotation)
ts="$(date +%Y%m%d-%H%M%S)"
backup="$KUBELET_CONFIG.bak-$ts"
cp "$KUBELET_CONFIG" "$backup"
echo " Backup created: $backup"
# If tlsCipherSuites is already correct, do nothing
if grep -qE '^[[:space:]]*tlsCipherSuites:' "$KUBELET_CONFIG"; then
if grep -qE "^[[:space:]]*tlsCipherSuites:[[:space:]]*\[$CIPHERS\][[:space:]]*$" "$KUBELET_CONFIG"; then
echo " tlsCipherSuites already set correctly in $KUBELET_CONFIG"
else
echo " Updating existing tlsCipherSuites in $KUBELET_CONFIG"
# Normalize to a single-line array
# This is a simple matcher that replaces any existing tlsCipherSuites line.
# If your file uses multi-line YAML arrays, you may need to adjust manually.
sed -i -E "s|^[[:space:]]*tlsCipherSuites:.*|tlsCipherSuites: [$CIPHERS]|" "$KUBELET_CONFIG"
changed_config=1
fi
else
echo " Adding tlsCipherSuites to $KUBELET_CONFIG"
{
echo ""
echo "tlsCipherSuites: [$CIPHERS]"
} >> "$KUBELET_CONFIG"
changed_config=1
fi
else
echo "-> No kubelet config file found at $KUBELET_CONFIG, skipping file-based config."
fi
#------------------------------
# 2) Ensure --tls-cipher-suites in systemd kubelet drop-in (if present)
#------------------------------
if [ -f "$KUBELET_SYSTEMD_DROPIN" ]; then
echo "-> Detected kubelet systemd drop-in: $KUBELET_SYSTEMD_DROPIN"
ts="$(date +%Y%m%d-%H%M%S)"
backup="$KUBELET_SYSTEMD_DROPIN.bak-$ts"
cp "$KUBELET_SYSTEMD_DROPIN" "$backup"
echo " Backup created: $backup"
if grep -q -- "--tls-cipher-suites=" "$KUBELET_SYSTEMD_DROPIN"; then
if grep -q -- "--tls-cipher-suites=$CIPHERS" "$KUBELET_SYSTEMD_DROPIN"; then
echo " --tls-cipher-suites already set correctly in $KUBELET_SYSTEMD_DROPIN"
else
echo " Updating existing --tls-cipher-suites in $KUBELET_SYSTEMD_DROPIN"
sed -i -E "s|--tls-cipher-suites=[^[:space:]]*|--tls-cipher-suites=$CIPHERS|g" "$KUBELET_SYSTEMD_DROPIN"
changed_systemd=1
fi
else
echo " Adding --tls-cipher-suites to kubelet ExecStart in $KUBELET_SYSTEMD_DROPIN"
# Append parameter inside ExecStart line
sed -i -E "s|^(ExecStart=.*kubelet)(.*)$|\1 --tls-cipher-suites=$CIPHERS\2|" "$KUBELET_SYSTEMD_DROPIN"
changed_systemd=1
fi
else
echo "-> No kubelet systemd drop-in at $KUBELET_SYSTEMD_DROPIN, skipping flag-based config."
fi
#------------------------------
# 3) Restart kubelet if anything changed
#------------------------------
if [ "$changed_config" -eq 1 ] || [ "$changed_systemd" -eq 1 ]; then
echo "-> Changes detected; reloading systemd and restarting kubelet"
systemctl daemon-reload
systemctl restart kubelet.service
echo " kubelet restarted (this may temporarily disrupt workloads on this node)"
else
echo "-> No changes made; kubelet restart not required."
fi
#------------------------------
# 4) Verification (adapted from audit)
#------------------------------
echo "==> Verification: kubelet process and effective TLS cipher suites"
echo "-- kubelet process:"
/bin/ps -fC kubelet || echo "kubelet process not found"
echo "-- Checking for tlsCipherSuites in $KUBELET_CONFIG (if file exists):"
if [ -f "$KUBELET_CONFIG" ]; then
grep -E '^[[:space:]]*tlsCipherSuites:' "$KUBELET_CONFIG" || echo "tlsCipherSuites not set in $KUBELET_CONFIG"
else
echo "$KUBELET_CONFIG not present"
fi
echo "-- Checking for --tls-cipher-suites flag in kubelet process:"
/bin/ps -C kubelet -o args= | grep -- "--tls-cipher-suites=" || echo "--tls-cipher-suites flag not present on kubelet process"
echo "==> Completed on host: $(hostname)"