Skip to main content

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

Manual Steps
  1. 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
  1. Edit the controller manager static pod manifest on that control plane node:
sudo vi /etc/kubernetes/manifests/kube-controller-manager.yaml
  1. 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.

  1. 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).

  1. Repeat steps 1–4 on every other control plane node.

  2. 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)"