> ## 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.

# Ensure Make Iptables Util Chains Argument Is Enabled

### More Info:

Allow Kubelet to manage iptables.

### Risk Level

High

### Address

Security

### Compliance Standards

* APRA CPS 234 (Australia)
* BSI C5 (Germany)
* Brazil LGPD
* CCPA / CPRA (California)
* CIS Critical Security Controls v8
* CIS EKS
* CMMC 2.0
* CSA Cloud Controls Matrix v4
* DPDPA
* Digital Operational Resilience Act (EU)
* ISO/IEC 27017
* ISO/IEC 27018
* ISO/IEC 27701
* KSA PDPL
* MAS Technology Risk Management (Singapore)
* MITRE ATT\&CK (Cloud)
* NIS2 Directive
* NIST SP 800-171
* NYDFS 23 NYCRR 500
* SWIFT Customer Security Controls Framework
* Sarbanes-Oxley IT General Controls
* UK NCSC Cyber Assessment Framework

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. On every worker node, check how kubelet is configured and whether the flag is already set:

        ```bash theme={null}
        ps -fC kubelet
        cat /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf 2>/dev/null || echo "no 10-kubelet-args.conf"
        grep -i makeiptablesutilchains /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf 2>/dev/null || echo "flag not in systemd args"
        grep -i makeIPTablesUtilChains /etc/kubernetes/kubelet/kubelet-config.json 2>/dev/null || echo "field not in kubelet-config.json"
        ```

        2. If using the kubelet config file (preferred), edit `/etc/kubernetes/kubelet/kubelet-config.json` on every worker node to set `makeIPTablesUtilChains` to `true` (create or update the field in the top-level config object):

        ```bash theme={null}
        vi /etc/kubernetes/kubelet/kubelet-config.json
        ```

        Add or change the line so it reads (with a trailing comma if required by surrounding JSON):

        ```json theme={null}
        "makeIPTablesUtilChains": true
        ```

        3. Ensure the systemd drop-in does not override this flag; on every worker node, remove any `--make-iptables-util-chains` argument from the kubelet args file:

        ```bash theme={null}
        sed -i.bak '/--make-iptables-util-chains/d' /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf
        ```

        4. If instead you are using only executable arguments (no kubelet config file), edit the kubelet args file on every worker node to explicitly set the flag:

        ```bash theme={null}
        vi /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf
        ```

        In the line defining `KUBELET_ARGS=...` (or equivalent), ensure it includes:

        ```bash theme={null}
        --make-iptables-util-chains=true
        ```

        and save the file.

        5. On every worker node, reload systemd and restart kubelet so the change takes effect (this will restart the kubelet process):

        ```bash theme={null}
        systemctl daemon-reload
        systemctl restart kubelet.service
        systemctl status kubelet -l
        ```

        6. Verify on every worker node that kubelet is now running with `--make-iptables-util-chains=true` or that the config file contains `"makeIPTablesUtilChains": true`:

        ```bash theme={null}
        ps -fC kubelet
        grep -i makeIPTablesUtilChains /etc/kubernetes/kubelet/kubelet-config.json 2>/dev/null || echo "not using kubelet config file"
        grep -i -- '--make-iptables-util-chains' /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf 2>/dev/null || echo "flag not set in systemd args"
        ```
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot change the kubelet’s `--make-iptables-util-chains` setting because it is a host-level configuration controlled by files and systemd units on every worker node (for example `/etc/kubernetes/kubelet/kubelet-config.json` or `/etc/systemd/system/kubelet.service.d/10-kubelet-args.conf`). To remediate this finding, follow the guidance in the Manual Steps section on each worker node.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Fix CISEKS 3.2.7: Ensure Kubelet --make-iptables-util-chains is enabled
        # Scope: every worker node
        #
        # Usage:
        #   - Copy to each worker node and run as root:
        #       chmod +x fix-make-iptables-util-chains.sh
        #       sudo ./fix-make-iptables-util-chains.sh
        #
        # Idempotent: safe to re-run.

        set -euo pipefail

        KUBELET_SYSTEMD_DIR="/etc/systemd/system/kubelet.service.d"
        KUBELET_ARGS_DROPIN="${KUBELET_SYSTEMD_DIR}/10-kubelet-args.conf"
        KUBELET_CONFIG_JSON="/etc/kubernetes/kubelet/kubelet-config.json"

        backup_file() {
          local f="$1"
          if [ -f "$f" ]; then
            local ts
            ts="$(date +%Y%m%d%H%M%S)"
            cp -p "$f" "${f}.bak-${ts}"
          fi
        }

        ensure_dir() {
          local d="$1"
          if [ ! -d "$d" ]; then
            mkdir -p "$d"
          fi
        }

        update_kubelet_config_json() {
          if [ ! -f "$KUBELET_CONFIG_JSON" ]; then
            # If this node doesn't use kubelet-config.json, skip this method.
            return
          fi

          backup_file "$KUBELET_CONFIG_JSON"

          # If file is empty, initialize minimal JSON
          if [ ! -s "$KUBELET_CONFIG_JSON" ]; then
            echo '{}' > "$KUBELET_CONFIG_JSON"
          fi

          # Use jq if available for safe JSON editing
          if command -v jq >/dev/null 2>&1; then
            local tmp
            tmp="$(mktemp)"
            jq '.makeIPTablesUtilChains = true' "$KUBELET_CONFIG_JSON" > "$tmp"
            mv "$tmp" "$KUBELET_CONFIG_JSON"
          else
            # Fallback: simple text-based update (assumes file is valid JSON already)
            # 1) Remove existing makeIPTablesUtilChains entries
            sed -i '/"makeIPTablesUtilChains"/d' "$KUBELET_CONFIG_JSON"
            # 2) Insert at end of top-level object before closing }
            #    Handles both single-line and multi-line JSON objects.
            if grep -q '}' "$KUBELET_CONFIG_JSON"; then
              # Ensure trailing comma before insertion if needed
              # Add comma to last non-empty, non-{, non-[ line before final }
              awk '
                BEGIN{last_nonbrace_line=0}
                NF{
                  if ($0 !~ /^[[:space:]]*[\{\[]/ && $0 !~ /^[[:space:]]*}$/) last_nonbrace_line=NR
                }
                {lines[NR]=$0}
                END{
                  for(i=1;i<=NR;i++){
                    if(i==last_nonbrace_line && lines[i] !~ /, *$/) {
                      sub(/[[:space:]]*$/,"",lines[i])
                      lines[i]=lines[i] ","
                    }
                    print lines[i]
                  }
                }
              ' "$KUBELET_CONFIG_JSON" > "${KUBELET_CONFIG_JSON}.tmp"
              mv "${KUBELET_CONFIG_JSON}.tmp" "$KUBELET_CONFIG_JSON"
              # Insert our field before the final }
              sed -i '$i \  "makeIPTablesUtilChains": true' "$KUBELET_CONFIG_JSON"
            else
              # Worst case: just force a minimal object
              echo '{ "makeIPTablesUtilChains": true }' > "$KUBELET_CONFIG_JSON"
            fi
          fi
        }

        clean_systemd_arg_override() {
          # Remove any explicit --make-iptables-util-chains from drop-in so config file wins
          if [ -f "$KUBELET_ARGS_DROPIN" ]; then
            backup_file "$KUBELET_ARGS_DROPIN"
            # Remove argument occurrences from the KUBELET_ARGS line
            sed -i 's/--make-iptables-util-chains[=:][^[:space:]]*//g' "$KUBELET_ARGS_DROPIN"
            # Collapse double spaces
            sed -i 's/  \+/ /g' "$KUBELET_ARGS_DROPIN"
          fi
        }

        ensure_systemd_arg_if_no_config() {
          # If kubelet-config.json does not exist, enforce via systemd args
          if [ -f "$KUBELET_CONFIG_JSON" ]; then
            return
          fi

          ensure_dir "$KUBELET_SYSTEMD_DIR"
          [ -f "$KUBELET_ARGS_DROPIN" ] || touch "$KUBELET_ARGS_DROPIN"

          backup_file "$KUBELET_ARGS_DROPIN"

          # Ensure we do not duplicate the argument
          if grep -q -- '--make-iptables-util-chains' "$KUBELET_ARGS_DROPIN"; then
            # Normalize it to true
            sed -i 's/--make-iptables-util-chains[=:][^[:space:]]*/--make-iptables-util-chains:true/g' "$KUBELET_ARGS_DROPIN"
          else
            if grep -q '^KUBELET_ARGS=' "$KUBELET_ARGS_DROPIN"; then
              # Append to existing KUBELET_ARGS
              sed -i 's/^KUBELET_ARGS="\([^"]*\)"/KUBELET_ARGS="\1 --make-iptables-util-chains:true"/' "$KUBELET_ARGS_DROPIN"
            else
              # Create new KUBELET_ARGS line
              echo 'KUBELET_ARGS="--make-iptables-util-chains:true"' >> "$KUBELET_ARGS_DROPIN"
            fi
          fi
        }

        restart_kubelet() {
          systemctl daemon-reload
          systemctl restart kubelet.service
          systemctl status kubelet -l --no-pager || true
        }

        verify() {
          echo "Verification: checking kubelet process args and live config (if available)..."
          if command -v ps >/dev/null 2>&1; then
            /bin/ps -fC kubelet || true
          fi

          # Try configz if kubectl is configured on this node (optional)
          if command -v kubectl >/dev/null 2>&1; then
            if kubectl cluster-info >/dev/null 2>&1; then
              kubectl proxy --port=8001 >/tmp/kubectl-proxy.log 2>&1 &
              PROXY_PID=$!
              sleep 3
              NODE_NAME="$(hostname -f 2>/dev/null || hostname)"
              echo "Attempting configz check via API for node: ${NODE_NAME}"
              curl -sSL "http://localhost:8001/api/v1/nodes/${NODE_NAME}/proxy/configz" | \
                grep -i "makeIPTablesUtilChains" || true
              kill "${PROXY_PID}" >/dev/null 2>&1 || true
            fi
          fi
        }

        main() {
          # Prefer Method 1 if kubelet-config.json exists, per remediation guidance
          if [ -f "$KUBELET_CONFIG_JSON" ]; then
            update_kubelet_config_json
            clean_systemd_arg_override
          else
            # Fall back to Method 2 (systemd args)
            ensure_systemd_arg_if_no_config
          fi

          restart_kubelet
          verify
        }

        main "$@"
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/admin/kubelet/](https://kubernetes.io/docs/admin/kubelet/)
