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

# Container Network Interface File Ownership Should Be root:root

### More Info:

Verifies that Container Network Interface configuration files are owned by root:root so only privileged users can modify pod networking configuration.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* CIS Kubernetes

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. On every control plane node, identify the CNI config directory used by kubelet (if not already known):

           ```bash theme={null}
           ps -ef | grep kubelet | grep -- --cni-conf-dir
           ```

        2. On every control plane node, list current ownership of CNI configuration files to see which need fixing (use the directory from step 1 if different):

           ```bash theme={null}
           sudo find /etc/cni/net.d -mindepth 1 -maxdepth 1 -type f -exec stat -c '%n %U:%G' {} \;
           ```

        3. On every control plane node, change ownership of all CNI configuration files to root:root:

           ```bash theme={null}
           sudo chown root:root /etc/cni/net.d/*
           ```

        4. On every control plane node, also ensure ownership of any CNI network state files under /var/lib/cni/networks is root:root (if the directory exists):

           ```bash theme={null}
           if [ -d /var/lib/cni/networks ]; then
             sudo find /var/lib/cni/networks -type f -exec chown root:root {} +
           fi
           ```

        5. On every control plane node, verify CNI configuration files now have owner and group root:root:

           ```bash theme={null}
           ps -ef | grep kubelet | grep -- --cni-conf-dir | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' | \
             xargs -I{} find {} -mindepth 1 | xargs --no-run-if-empty stat -c '%n %U:%G'
           ```

        6. On every control plane node, verify CNI network state files (if present) are also owned by root:root:

           ```bash theme={null}
           find /var/lib/cni/networks -type f 2> /dev/null | xargs --no-run-if-empty stat -c '%n %U:%G'
           ```
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot modify Container Network Interface file ownership because this setting is controlled by host-level filesystem permissions on each control plane node. To remediate this finding, log into every control plane node and follow the commands in the Manual Steps section to set the CNI configuration files to `root:root`.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Fix CNI config file ownership to root:root on every control plane node
        # Scope: run on every control plane node (as root or with sudo)
        # Safe to re-run (idempotent)

        set -euo pipefail

        echo "=== Detecting CNI configuration directory from kubelet flags (if present) ==="

        CNI_CONF_DIRS=()

        # Try to detect from running kubelet process
        if pgrep -x kubelet >/dev/null 2>&1; then
          # Extract --cni-conf-dir argument if present
          DETECTED_DIRS=$(ps -ef | grep kubelet | grep -v grep \
            | grep -- --cni-conf-dir \
            | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' || true)

          if [ -n "${DETECTED_DIRS}" ]; then
            while IFS= read -r d; do
              [ -n "$d" ] && CNI_CONF_DIRS+=("$d")
            done <<< "${DETECTED_DIRS}"
          fi
        fi

        # Fallback to common default if none detected
        DEFAULT_DIRS=(
          "/etc/cni/net.d"
        )
        for d in "${DEFAULT_DIRS[@]}"; do
          CNI_CONF_DIRS+=("$d")
        done

        # De-duplicate directories
        uniq_dirs=()
        for d in "${CNI_CONF_DIRS[@]}"; do
          skip=false
          for u in "${uniq_dirs[@]}"; do
            if [ "$u" = "$d" ]; then
              skip=true
              break
            fi
          done
          $skip || uniq_dirs+=("$d")
        done
        CNI_CONF_DIRS=("${uniq_dirs[@]}")

        echo "CNI configuration directories to process:"
        for d in "${CNI_CONF_DIRS[@]}"; do
          echo " - $d"
        done

        echo
        echo "=== Fixing ownership to root:root where directories exist ==="

        for dir in "${CNI_CONF_DIRS[@]}"; do
          if [ -d "$dir" ]; then
            echo "Processing directory: $dir"
            # Change ownership of files and subdirectories to root:root (idempotent)
            chown -R root:root "$dir"
          else
            echo "Directory not present, skipping: $dir"
          fi
        done

        # Also fix ownership under /var/lib/cni/networks if present (used by audit)
        if [ -d "/var/lib/cni/networks" ]; then
          echo "Processing directory: /var/lib/cni/networks"
          chown -R root:root /var/lib/cni/networks
        else
          echo "Directory not present, skipping: /var/lib/cni/networks"
        fi

        echo
        echo "=== Verification (should report only root:root) ==="

        # Replicate the audit logic to confirm ownership
        # 1) CNI config files
        if pgrep -x kubelet >/dev/null 2>&1; then
          ps -ef | grep kubelet | grep -v grep | grep -- --cni-conf-dir \
            | sed 's%.*cni-conf-dir[= ]\([^ ]*\).*%\1%' \
            | xargs -I{} find {} -mindepth 1 2>/dev/null \
            | xargs --no-run-if-empty stat -c '%n %U:%G' \
            | sort -u || true
        fi

        # Fallback verification for default /etc/cni/net.d
        if [ -d "/etc/cni/net.d" ]; then
          find /etc/cni/net.d -mindepth 1 -maxdepth 1 -type f 2>/dev/null \
            | xargs --no-run-if-empty stat -c '%n %U:%G' \
            | sort -u || true
        fi

        # 2) /var/lib/cni/networks files
        if [ -d "/var/lib/cni/networks" ]; then
          find /var/lib/cni/networks -type f 2>/dev/null \
            | xargs --no-run-if-empty stat -c '%n %U:%G' \
            | sort -u || true
        fi

        echo
        echo "If any entries above are not 'root:root', investigate and correct them manually."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
