> ## 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 The CNI In Use Supports NetworkPolicies

### More Info:

Without a CNI plugin that supports NetworkPolicies, traffic between pods cannot be restricted. Use a plugin that enforces network policy.

### 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. **Identify the current CNI plugin and its capabilities**
           * Run on: any machine with kubectl access
           * Commands:
             ```bash theme={null}
             kubectl get pods -n kube-system -o wide
             kubectl get daemonset -n kube-system
             kubectl get pods -n kube-system -l k8s-app=calico-node --ignore-not-found
             kubectl get pods -n kube-system -l k8s-app=weave-net --ignore-not-found
             kubectl get pods -n kube-system -l k8s-app=cilium --ignore-not-found
             kubectl get pods -n kube-system -l k8s-app=flannel --ignore-not-found
             kubectl get pods -n kube-system -l k8s-app=kube-router --ignore-not-found
             ```
           * From these outputs, determine which CNI is installed and consult its official documentation to verify whether it implements Kubernetes `NetworkPolicy`.

        2. **Check whether NetworkPolicy objects are being used**
           * Run on: any machine with kubectl access
           * Commands:
             ```bash theme={null}
             kubectl get networkpolicy --all-namespaces
             ```
           * If no `NetworkPolicy` resources exist, document that policies are not in use and decide whether you want to start using them. If they exist, proceed to validate that they are enforced.

        3. **Functionally test whether NetworkPolicies are enforced**
           * Run on: any machine with kubectl access
           * Create a test namespace and pods:
             ```bash theme={null}
             kubectl create namespace np-test
             kubectl run np-allowed -n np-test --image=nginx --port=80 --labels=role=allowed --restart=Never
             kubectl run np-denied -n np-test --image=nginx --port=80 --labels=role=denied --restart=Never
             kubectl run np-client -n np-test --image=busybox --restart=Never --command -- sh -c "sleep 3600"
             kubectl wait --for=condition=ready pod -n np-test --all --timeout=120s
             ```
           * Verify baseline connectivity (should be allowed before any policy):
             ```bash theme={null}
             kubectl exec -n np-test np-client -- wget -qO- http://np-allowed.np-test.svc.cluster.local
             kubectl exec -n np-test np-client -- wget -qO- http://np-denied.np-test.svc.cluster.local
             ```

        4. **Apply a restrictive NetworkPolicy and observe behavior**
           * Run on: any machine with kubectl access
           * Create a policy that only allows traffic to `np-allowed` from pods with label `access=granted`:
             ```bash theme={null}
             cat <<'EOF' | kubectl apply -f -
             apiVersion: networking.k8s.io/v1
             kind: NetworkPolicy
             metadata:
               name: allow-from-granted-only
               namespace: np-test
             spec:
               podSelector:
                 matchLabels:
                   role: allowed
               policyTypes:
               - Ingress
               ingress:
               - from:
                 - podSelector:
                     matchLabels:
                       access: granted
             EOF
             ```
           * Label the client incorrectly and test (should be blocked if NetworkPolicy is enforced):
             ```bash theme={null}
             kubectl label pod -n np-test np-client access=denied --overwrite
             kubectl exec -n np-test np-client -- wget -qO- http://np-allowed.np-test.svc.cluster.local --timeout=5
             ```
           * Then label it correctly and test again (should succeed if enforced):
             ```bash theme={null}
             kubectl label pod -n np-test np-client access=granted --overwrite
             kubectl exec -n np-test np-client -- wget -qO- http://np-allowed.np-test.svc.cluster.local --timeout=5
             ```
           * If connectivity is unaffected by the policy, your current CNI is not enforcing `NetworkPolicy`.

        5. **Decide and plan remediation if NetworkPolicies are not enforced**
           * If the CNI does not support `NetworkPolicy`, or the tests above show no enforcement:
             * Document the current CNI and its limitations.
             * Select a CNI that supports Kubernetes `NetworkPolicy` and is compatible with your environment (for example, Calico, Cilium, Weave Net, Kube-router; verify support in their documentation).
             * Plan a migration window, including:
               * Reading the chosen CNI’s install/migration guide for your Kubernetes distribution.
               * Capturing current CNI manifests in `kube-system`:
                 ```bash theme={null}
                 kubectl get daemonset,deploy,cm,svc -n kube-system -o wide
                 kubectl get daemonset -n kube-system -o yaml > /tmp/kube-system-daemonsets.yaml
                 ```
               * Assessing impact on existing workloads and any current (even if non‑enforced) `NetworkPolicy` objects.

        6. **Clean up test resources and re-verify after any CNI change**
           * Run on: any machine with kubectl access
           * Clean up test namespace:
             ```bash theme={null}
             kubectl delete namespace np-test
             ```
           * After migrating to a CNI that supports `NetworkPolicy`, repeat steps 2–4 to confirm that:
             * `NetworkPolicy` objects exist (if you use them), and
             * Connectivity tests change as expected when policies are applied, demonstrating that the CNI now enforces network policies.
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1. Identify which CNI plugin is in use
        # Run on: any machine with kubectl access

        kubectl get pods -n kube-system -o wide | egrep 'calico|cilium|weave|flannel|canal|antrea|azure-cni|amazon-vpc-cni|gke|ovn|tigera|cni'

        # Also list all DaemonSets in kube-system (most CNIs run as a DaemonSet)
        kubectl get daemonsets -n kube-system -o wide
        ```

        **What to look for**

        * Pods/DaemonSets named like:
          * `calico-node`, `calico-typha`, `tigera-operator` → Calico (supports NetworkPolicy)
          * `cilium`, `cilium-agent` → Cilium (supports NetworkPolicy)
          * `kube-flannel-ds` or `flannel-*` → Flannel (basic Flannel **does NOT** enforce NetworkPolicy)
          * `weave-net` → Weave Net (supports NetworkPolicy)
          * `kube-router` → kube-router (supports NetworkPolicy)
          * `antrea-agent` → Antrea (supports NetworkPolicy)
          * Cloud CNIs (`amazon-vpc-cni-*`, `azure-cni-*`, `gke-*`, `ovn-kubernetes`, etc.) → check their docs for NetworkPolicy support.
        * If you see only `kube-proxy` and no obvious CNI pods, or see a home‑grown/unknown CNI without clear documentation, treat this as “unknown/likely not supporting NetworkPolicy” until verified.

        ***

        ```bash theme={null}
        # 2. Check whether any NetworkPolicy objects exist
        # Run on: any machine with kubectl access

        kubectl get networkpolicy --all-namespaces
        ```

        **What to look for**

        * If **no NetworkPolicy objects** exist but:
          * Security requirements expect pod‑to‑pod isolation, and
          * The CNI supports NetworkPolicy\
            → This is a *policy design gap*, not a CNI capability problem.
        * If many `NetworkPolicy` objects exist, but the CNI is known **not** to support them (e.g., plain Flannel):
          * This indicates a **serious problem**: policies are being defined but are not enforced at all.

        ***

        ```bash theme={null}
        # 3. Inspect an example NetworkPolicy spec
        # Run on: any machine with kubectl access

        # Replace NAMESPACE and NAME with a policy you saw above
        kubectl get networkpolicy -n NAMESPACE NAME -o yaml
        ```

        **What to look for**

        * Confirm these are Kubernetes `kind: NetworkPolicy` (not a CRD from some other system).
        * If the CNI is known not to support NetworkPolicy, any such spec is effectively **documentation only**, not enforced.

        ***

        ```bash theme={null}
        # 4. (Optional) Quick runtime sanity check of isolation behavior
        # Run on: any machine with kubectl access

        # 4a. Create a test namespace
        kubectl create namespace np-test

        # 4b. Create two simple test pods
        kubectl run client -n np-test --image=busybox --restart=Never -- /bin/sh -c "sleep 3600"
        kubectl run server -n np-test --image=nginx --restart=Never

        # Wait for them to be Ready
        kubectl wait --for=condition=Ready pod/client pod/server -n np-test --timeout=120s

        # 4c. Get the server Pod IP
        SERVER_IP=$(kubectl get pod server -n np-test -o jsonpath='{.status.podIP}')
        echo "$SERVER_IP"

        # 4d. Test connectivity BEFORE any NetworkPolicy (should generally succeed in typical clusters)
        kubectl exec -n np-test client -- wget -qO- "http://$SERVER_IP"

        # 4e. Apply a default-deny NetworkPolicy in np-test
        cat << 'EOF' | kubectl apply -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: deny-all
          namespace: np-test
        spec:
          podSelector: {}
          policyTypes:
          - Ingress
        EOF

        # 4f. Test connectivity AGAIN after policy is applied
        kubectl exec -n np-test client -- wget -qO- "http://$SERVER_IP" || echo "connection blocked"
        ```

        **What indicates a problem**

        * If the initial connection (step 4d) fails unexpectedly → there may already be other policies or other controls in place; interpret with caution.
        * **Key check**: after applying the `deny-all` NetworkPolicy (step 4e):
          * If the wget in step 4f **still succeeds consistently** and you are sure:
            * The `deny-all` policy is applied (check with `kubectl get networkpolicy -n np-test deny-all -o yaml`), and
            * There are no other NetworkPolicies allowing this traffic\
              → This strongly suggests the **CNI does not enforce Kubernetes NetworkPolicy** (or is misconfigured).
          * If the wget **fails** or hangs until timeout, this suggests NetworkPolicies are being enforced.

        Clean up the test objects when done:

        ```bash theme={null}
        kubectl delete namespace np-test
        ```

        ***

        ```bash theme={null}
        # 5. Verification summary command (for documentation)
        # Run on: any machine with kubectl access

        # Summarize CNI-related pods and whether NetworkPolicies exist
        echo "=== CNI Pods (kube-system) ==="
        kubectl get pods -n kube-system -o wide | egrep 'calico|cilium|weave|flannel|canal|antrea|azure-cni|amazon-vpc-cni|gke|ovn|tigera|cni' || echo "No known CNI pods found"

        echo "=== NetworkPolicies in the cluster ==="
        kubectl get networkpolicy --all-namespaces || echo "No NetworkPolicies defined"
        ```

        **How to interpret**

        * If the CNI identified above is one that does **not** support NetworkPolicy (e.g., plain Flannel) and there is a requirement to restrict pod‑to‑pod traffic using Kubernetes `NetworkPolicy`, this finding is **not remediated** and you must:
          * Migrate to a CNI that supports NetworkPolicies, or
          * Implement alternative network controls outside Kubernetes.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Check CNI plugins in use and whether NetworkPolicies are likely to be enforced
        # Run on: any machine with kubectl access and cluster-wide RBAC
        #
        # Requires: kubectl, jq

        set -euo pipefail

        echo "=== 1) Detect CNI plugins in use on each node ==="
        kubectl get nodes -o wide | sed 's/^/NODE: /'

        echo
        echo "Node-level CNI detection (from kubelet args and CNI config paths):"
        kubectl get nodes -o name | while read -r node; do
          nodename="${node##*/}"
          echo
          echo "---- ${nodename} ----"

          # Try to detect kubelet CNI-related flags from the kubelet config (if present)
          # This only works on some distros that expose config via the ConfigMap
          if kubectl -n kube-system get cm kubelet-config -o json >/dev/null 2>&1; then
            echo "  kubelet CNI configuration (cluster-wide, from kubelet-config ConfigMap):"
            kubectl -n kube-system get cm kubelet-config -o json \
              | jq -r '.data | to_entries[] | select(.key|test("kubelet")) | .value' \
              | jq -r '.cniConfDir? // "<unknown>", .cniBinDir? // "<unknown>"' \
              | awk 'NR==1{printf "    cniConfDir: %s\n",$0} NR==2{printf "    cniBinDir: %s\n",$0}'
          else
            echo "  kubelet-config ConfigMap not found; CNI paths may need to be checked on nodes directly."
          fi

          # Look for CNI-related DaemonSets on this node via nodeSelector / tolerations
          echo "  CNI-related DaemonSets scheduled on this node:"
          kubectl get daemonsets -A -o json \
            | jq -r --arg NODE "${nodename}" '
                .items[]
                | select(.metadata.name|test("calico|cilium|weave|flannel|antrea|canal|ovn|kube-ovn";"i"))
                | "\(.metadata.namespace)/\(.metadata.name)"' \
              | sed 's/^/    /' || true
        done

        echo
        echo "=== 2) Detect installed CNI plugin components (best-effort from known labels) ==="
        echo "Known network/CNI DaemonSets:"
        kubectl get daemonsets -A \
          | grep -Ei 'calico|cilium|weave|flannel|antrea|canal|ovn|kube-ovn|kube-router|tigera' \
          || echo "  No known CNI DaemonSets matched by heuristic grep."

        echo
        echo "For each candidate CNI, basic capability hints:"
        kubectl get daemonsets -A -o json \
          | jq -r '
            .items[]
            | select(.metadata.name|test("calico|cilium|weave|flannel|antrea|canal|ovn|kube-ovn|kube-router|tigera";"i"))
            | "- CNI: \(.metadata.namespace)/\(.metadata.name)
               Images: \(.spec.template.spec.containers[].image)
               Annotations: \(.metadata.annotations // {} | to_entries[]? | select(.key|test(\"networkpolicy|network-policy|policies\";\"i\")) | .key + \"=\" + .value)"' \
            | sed 's/^[ ]\+//'

        echo
        echo "=== 3) Detect presence of NetworkPolicy objects in the cluster ==="
        kubectl get networkpolicies --all-namespaces || echo "No NetworkPolicies found (no output)."

        echo
        echo "=== 4) Probe whether basic egress isolation is likely enforced (heuristic) ==="
        echo "NOTE: This does NOT prove correctness; it only checks if any default-deny policies exist."
        echo "Default-deny ingress NetworkPolicies:"
        kubectl get networkpolicies --all-namespaces -o json \
          | jq -r '
            .items[]
            | select(
                (.spec.podSelector | has("matchLabels") or has("matchExpressions"))
                and
                ((.spec.ingress | length == 0) or (.spec.ingress == null))
              )
            | "\(.metadata.namespace)/\(.metadata.name)"' \
          || echo "  None detected."

        echo
        echo "Default-deny egress NetworkPolicies:"
        kubectl get networkpolicies --all-namespaces -o json \
          | jq -r '
            .items[]
            | select(
                (.spec.podSelector | has("matchLabels") or has("matchExpressions"))
                and
                ((.spec.egress | length == 0) or (.spec.egress == null))
                and
                (.spec.policyTypes[]? | ascii_downcase == "egress")
              )
            | "\(.metadata.namespace)/\(.metadata.name)"' \
          || echo "  None detected."

        echo
        echo "=== 5) Summary of potential issues to review manually ==="
        echo "1) If no CNI DaemonSet or plugin could be identified above, manually check:"
        echo "   - Which CNI is installed on each node (e.g., /etc/cni/net.d on the node)."
        echo "   - Whether that CNI's documentation states explicit support for Kubernetes NetworkPolicy."
        echo
        echo "2) If the identified CNI is known NOT to support NetworkPolicies (e.g., vanilla Flannel),"
        echo "   this is a finding: NetworkPolicies defined in the cluster will NOT be enforced."
        echo
        echo "3) If NetworkPolicy objects exist but the CNI plugin does not support them, this is a finding."
        echo "   Compare the CNIs detected in section (2) against vendor docs."
        echo
        echo "4) If no NetworkPolicy objects exist at all, this script cannot tell whether the CNI"
        echo "   would enforce them; you must still confirm the plugin's capabilities from its docs."
        echo
        echo "This check is MANUAL: use the above data + the CNI vendor documentation to decide whether"
        echo "the CNI in use truly supports Kubernetes NetworkPolicies."
        ```

        **How to interpret output (what indicates a problem):**

        * No CNI DaemonSet or plugin is detected, or only a plugin known not to support NetworkPolicies is present (for example, basic Flannel without policy extensions).
        * NetworkPolicy objects exist (`kubectl get networkpolicies --all-namespaces` shows entries), but the detected CNI plugin’s documentation does not explicitly state support for Kubernetes NetworkPolicy.
        * Operators cannot identify any CNI plugin at all or cannot confirm from documentation that it enforces NetworkPolicies.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
