> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Kubelet Read Only Port Argument Set To 0

### More Info:

The kubelet read-only port serves cluster information without authentication or authorization. Setting --read-only-port to 0 disables this unauthenticated endpoint.

### Risk Level

High

### Address

Security

### Compliance Standards

* CIS Kubernetes

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. On every worker node, open the kubelet config file and set `readOnlyPort` to 0 (create the key if missing):
           ```bash theme={null}
           sudo sed -i 's/^readOnlyPort: .*/readOnlyPort: 0/' /var/lib/kubelet/config.yaml || \
           echo "readOnlyPort: 0" | sudo tee -a /var/lib/kubelet/config.yaml
           ```

        2. Still on every worker node, ensure any kubelet systemd drop-in does not override this with a non‑zero flag. Inspect:
           ```bash theme={null}
           sudo grep -R --color -n "read-only-port" /etc/systemd/system/kubelet.service.d /etc/systemd/system/kubelet.service 2>/dev/null || echo "No read-only-port flags found in systemd units."
           ```
           If you see a line like `--read-only-port=10255`, edit the file to set it to 0, for example:
           ```bash theme={null}
           sudo sed -i 's/--read-only-port=[0-9]\+/--read-only-port=0/' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
           ```

        3. Reload systemd and restart kubelet on every worker node (this will briefly disrupt workloads on that node):
           ```bash theme={null}
           sudo systemctl daemon-reload
           sudo systemctl restart kubelet.service
           ```

        4. Verify on every worker node that kubelet is running with `--read-only-port=0` (or not present at all, relying on the config file) using the audit command:
           ```bash theme={null}
           /bin/ps -fC kubelet
           ```
           Inspect the output and confirm:
           * Either there is no `--read-only-port` flag, and
           * If present, it appears only as `--read-only-port=0`.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify kubelet host-level configuration or process flags, so it cannot be used to set `readOnlyPort` to 0. This must be fixed directly on each worker node (for example in `/var/lib/kubelet/config.yaml` or the kubelet systemd drop-in), so follow the guidance in the Manual Steps section on those nodes.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Purpose:
        #   Disable the kubelet read-only port by setting readOnlyPort: 0
        #   in /var/lib/kubelet/config.yaml on every worker node, then
        #   restart kubelet and verify.
        #
        # Usage:
        #   Run on each worker node as root (or with sudo):
        #     sudo bash ./fix-kubelet-readonly-port.sh
        #
        # Idempotent:
        #   Safe to re-run; it preserves existing config and only enforces readOnlyPort: 0.

        set -euo pipefail

        CONFIG_FILE="/var/lib/kubelet/config.yaml"
        BACKUP_DIR="/var/lib/kubelet/backup-$(date +%Y%m%d)"
        SYSTEMD_UNIT="kubelet.service"

        echo "[INFO] Checking kubelet config file at ${CONFIG_FILE}"

        if [[ ! -f "${CONFIG_FILE}" ]]; then
          echo "[ERROR] ${CONFIG_FILE} not found on this node."
          echo "[ERROR] This script only manages kubelet configured via ${CONFIG_FILE}."
          exit 1
        fi

        mkdir -p "${BACKUP_DIR}"

        # Backup once per day (idempotent enough and cheap)
        BACKUP_FILE="${BACKUP_DIR}/config.yaml.$(hostname)"
        if [[ ! -f "${BACKUP_FILE}" ]]; then
          echo "[INFO] Backing up ${CONFIG_FILE} to ${BACKUP_FILE}"
          cp -a "${CONFIG_FILE}" "${BACKUP_FILE}"
        else
          echo "[INFO] Backup ${BACKUP_FILE} already exists; skipping backup."
        fi

        # Ensure readOnlyPort: 0 is present.
        # Strategy:
        #   - If a readOnlyPort line exists, replace its value with 0.
        #   - If no such line exists, append "readOnlyPort: 0" at the end.
        #   This is a simple, line-based edit and assumes no YAML anchors/templates.
        echo "[INFO] Ensuring readOnlyPort is set to 0 in ${CONFIG_FILE}"

        if grep -Eq '^\s*readOnlyPort\s*:' "${CONFIG_FILE}"; then
          # Normalize any existing setting to 0
          sed -i -E 's/^\s*readOnlyPort\s*:.*/readOnlyPort: 0/' "${CONFIG_FILE}"
        else
          echo "readOnlyPort: 0" >> "${CONFIG_FILE}"
        fi

        echo "[INFO] Current readOnlyPort setting:"
        grep -E '^\s*readOnlyPort\s*:' "${CONFIG_FILE}" || echo "[WARN] readOnlyPort line not found after edit"

        # Reload systemd and restart kubelet
        echo "[INFO] Reloading systemd daemon and restarting ${SYSTEMD_UNIT}"
        systemctl daemon-reload
        systemctl restart "${SYSTEMD_UNIT}"

        # Verification: use the same process inspection approach as the audit,
        # and also confirm the config file value.
        echo "[INFO] Verifying kubelet process is running and read-only port is disabled"

        if ! /bin/ps -fC kubelet >/dev/null 2>&1; then
          echo "[ERROR] kubelet process not found after restart. Check systemctl status kubelet."
          exit 1
        fi

        echo "[INFO] kubelet process:"
        /bin/ps -fC kubelet || true

        echo "[INFO] Verifying readOnlyPort in ${CONFIG_FILE} is set to 0"
        if grep -Eq '^\s*readOnlyPort\s*:\s*0\s*$' "${CONFIG_FILE}"; then
          echo "[INFO] readOnlyPort correctly set to 0 in config file."
        else
          echo "[ERROR] readOnlyPort is not set to 0 in ${CONFIG_FILE}. Manual review required."
          exit 1
        fi

        echo "[INFO] Verification complete on this worker node."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
