Controller Manager Bind Address Should Be 127.0.0.1
More Info:
Verifies that the controller manager --bind-address is set to 127.0.0.1 so its metrics and health endpoints are not exposed on the network.
Risk Level
High
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
- On every control plane node, back up the existing manifest so you can roll back if needed:
sudo cp -a /etc/kubernetes/manifests/kube-controller-manager.yaml \
/etc/kubernetes/manifests/kube-controller-manager.yaml.bak
- Edit the controller manager static pod manifest on that control plane node:
sudo vi /etc/kubernetes/manifests/kube-controller-manager.yaml
- In the container command/args section, set or correct the bind address flag so it is exactly:
- --bind-address=127.0.0.1
Remove any other --bind-address entries with different values. Save and exit.
Note: updating this static pod manifest will cause the kube-controller-manager pod to be restarted automatically by the kubelet.
- Wait for the kube-controller-manager pod to restart and become Running on that node:
sudo crictl ps | grep kube-controller-manager || sudo docker ps | grep kube-controller-manager
(use whichever container runtime command is available on that node).
-
Repeat steps 1–4 on every other control plane node.
-
Verify on each control plane node that the controller manager is now running with the correct bind address:
/bin/ps -ef | grep kube-controller-manager | grep -v grep | grep -- '--bind-address=127.0.0.1'
Using kubectl
kubectl cannot modify the kube-controller-manager static pod manifest or its process flags. This finding must be fixed directly on each control plane node by editing /etc/kubernetes/manifests/kube-controller-manager.yaml; see the Manual Steps section for exact host-level instructions.
Automation
#!/usr/bin/env bash
#
# Remediation: Ensure kube-controller-manager --bind-address is set to 127.0.0.1
# Scope: Run on every control plane node (with sudo/root). Safe to re-run.
#
set -euo pipefail
MANIFEST="/etc/kubernetes/manifests/kube-controller-manager.yaml"
BACKUP_DIR="/etc/kubernetes/manifests/backup-cis-1.3.7"
REQUIRED_BIND="127.0.0.1"
echo "==> Starting remediation for kube-controller-manager bind-address on host: $(hostname)"
if [[ $EUID -ne 0 ]]; then
echo "ERROR: This script must be run as root (or via sudo)." >&2
exit 1
fi
if [[ ! -f "${MANIFEST}" ]]; then
echo "ERROR: Manifest ${MANIFEST} not found on this node. Is this a control plane node?" >&2
exit 1
fi
mkdir -p "${BACKUP_DIR}"
TS="$(date +%Y%m%d-%H%M%S)"
BACKUP_FILE="${BACKUP_DIR}/kube-controller-manager.yaml.${TS}"
echo "==> Backing up ${MANIFEST} to ${BACKUP_FILE}"
cp -p "${MANIFEST}" "${BACKUP_FILE}"
echo "==> Ensuring --bind-address=${REQUIRED_BIND} in ${MANIFEST}"
# This operation is idempotent:
# - If --bind-address exists, update its value.
# - If it does not exist, add it under the existing command list.
# 1) If an existing --bind-address arg is present, replace its value
if grep -q -- "--bind-address=" "${MANIFEST}"; then
sed -i "s/--bind-address=[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}/--bind-address=${REQUIRED_BIND}/" "${MANIFEST}"
else
# 2) Append --bind-address argument under the kube-controller-manager container args/command
# Try to append to an existing `- --bind-address` style list; if not present, we append a new line.
# This assumes a standard kubeadm-style static pod manifest.
if grep -q "kube-controller-manager" "${MANIFEST}"; then
# Insert after the line containing "kube-controller-manager" container command/args list item
awk -v bind="--bind-address=${REQUIRED_BIND}" '
/kube-controller-manager/ && in_container==0 {
in_container=1
print $0
next
}
in_container==1 && $0 ~ /^ *- .*/ && inserted==0 {
print $0
print " - " bind
inserted=1
next
}
{ print $0 }
' "${MANIFEST}" > "${MANIFEST}.tmp" || {
echo "ERROR: Failed to update manifest; restoring backup." >&2
cp -p "${BACKUP_FILE}" "${MANIFEST}"
exit 1
}
mv "${MANIFEST}.tmp" "${MANIFEST}"
else
echo "WARNING: Could not confidently locate kube-controller-manager container section."
echo "Appending bind-address line near the end of file; please review manually."
echo " - --bind-address=${REQUIRED_BIND}" >> "${MANIFEST}"
fi
fi
echo "==> Manifest updated. Kubelet will automatically restart the kube-controller-manager static pod."
# Wait a short period for kubelet to recreate/reload the pod
sleep 20
echo "==> Verifying that kube-controller-manager is running with --bind-address=${REQUIRED_BIND}"
# Verification 1: process flags
if /bin/ps -ef | grep kube-controller-manager | grep -v grep | grep -q -- "--bind-address=${REQUIRED_BIND}"; then
echo "PASS: kube-controller-manager process shows --bind-address=${REQUIRED_BIND}"
else
echo "FAIL: kube-controller-manager process does NOT show --bind-address=${REQUIRED_BIND}" >&2
echo " Run: /bin/ps -ef | grep kube-controller-manager | grep -v grep" >&2
exit 1
fi
# Verification 2: manifest content
if grep -q -- "--bind-address=${REQUIRED_BIND}" "${MANIFEST}"; then
echo "PASS: ${MANIFEST} contains --bind-address=${REQUIRED_BIND}"
else
echo "FAIL: ${MANIFEST} does NOT contain --bind-address=${REQUIRED_BIND}" >&2
exit 1
fi
echo "==> Remediation complete on host: $(hostname)"