> ## 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 CNI Supports Network Policies

### More Info:

There are a variety of CNI plugins available for Kubernetes. If the CNI in use does not support Network Policies it may not be possible to effectively restrict traffic in the cluster.

### 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. **Identify the current CNI plugin**
           * Run on: any machine with kubectl access
           * Command:
             ```bash theme={null}
             kubectl get pods -n kube-system -o wide | grep -iE 'calico|cilium|weave|flannel|canal|antrea|ovn|aws-node|azure-cni|gke|kube-router'
             kubectl get daemonset -n kube-system
             kubectl get pods -n kube-system -o yaml > /tmp/kube-system-pods.yaml
             ```
           * Review: Look for CNI-related DaemonSets/Pods (e.g., calico-node, cilium, weave-net, aws-node, azure-cni, antrea, kube-router) to determine which CNI is installed.

        2. **Determine whether the CNI supports NetworkPolicies**
           * Using the CNI name from step 1, consult its official documentation to confirm:
             * Whether it supports Kubernetes `networking.k8s.io/v1` NetworkPolicy.
             * Any feature flags or modes required to enable policy enforcement.
           * Evidence:
             * Save a short note in your ops documentation (e.g., `/tmp/cni-networkpolicy-support.txt`) recording:
               * CNI name and version (from Pod image tag).
               * URL or doc section stating NetworkPolicy support and any prerequisites.

        3. **Verify NetworkPolicy CRD and usage in the cluster**
           * Run on: any machine with kubectl access
           * Commands:
             ```bash theme={null}
             kubectl api-resources | grep -i networkpolicy
             kubectl get networkpolicy --all-namespaces
             ```
           * Review:
             * Confirm `networkpolicies` (group `networking.k8s.io`) are available.
             * Note whether any NetworkPolicies are currently defined and in which namespaces.

        4. **Test effective policy enforcement (non-disruptive check)**
           * Run on: any machine with kubectl access
           * Apply a temporary restrictive policy in a non-critical namespace (e.g., `default`), then test connectivity:
             ```bash theme={null}
             # Create a simple deny-all-ingress policy
             cat <<'EOF' | kubectl apply -f -
             apiVersion: networking.k8s.io/v1
             kind: NetworkPolicy
             metadata:
               name: deny-all-ingress
               namespace: default
             spec:
               podSelector: {}
               policyTypes:
               - Ingress
             EOF

             # Launch two test pods
             kubectl run np-test-server -n default --image=nginx:1.25 --port=80 --restart=Never
             kubectl run np-test-client -n default --image=busybox:1.36 --restart=Never -- sleep 3600

             # After pods are Running, try to connect
             SERVER_IP=$(kubectl get pod np-test-server -n default -o jsonpath='{.status.podIP}')
             kubectl exec -n default np-test-client -- wget -qO- "http://$SERVER_IP:80" || echo "connect failed"
             ```
           * Review:
             * If the CNI enforces policies, the wget should fail (connection refused/timed out).
             * If the wget succeeds, NetworkPolicies are not being enforced by the current CNI or are misconfigured.
           * Cleanup:
             ```bash theme={null}
             kubectl delete networkpolicy deny-all-ingress -n default
             kubectl delete pod np-test-server np-test-client -n default --ignore-not-found
             ```

        5. **Decide remediation approach if NetworkPolicies are unsupported or ineffective**
           * If documentation or the test indicates no or ineffective NetworkPolicy support:
             * Decide whether to:
               * Migrate to a CNI that supports NetworkPolicies (e.g., Calico, Cilium, Antrea, etc.), or
               * Implement an alternate traffic restriction mechanism (e.g., cloud-provider security groups, service mesh policy, host firewall rules).
           * Gather current state to inform migration planning:
             ```bash theme={null}
             kubectl get nodes -o wide
             kubectl get pods -A -o wide
             kubectl cluster-info dump > /tmp/cluster-info-dump.json
             ```
           * Plan for:
             * Maintenance window and rollback.
             * CNI-specific migration guide (from vendor docs).
             * Impact on existing Pods and IP addressing.

        6. **Verify post-remediation behavior**
           * After migrating CNI or enabling NetworkPolicy features, repeat step 4’s test exactly:
             ```bash theme={null}
             # Re-apply the deny-all policy and test connectivity as in step 4
             # (re-run the same commands)
             ```
           * Confirm:
             * NetworkPolicy API is present (step 3).
             * Connectivity test fails as expected under a deny-all policy.
           * Record results and updated CNI details in your cluster security documentation as proof of remediation.
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) Identify the current cluster network plugin
        # Run on: any machine with kubectl access
        kubectl -n kube-system get pods -o wide \
          -l k8s-app=calico-node,app=calico,app=flannel,k8s-app=flannel, \
             k8s-app=weave-net,app=weave-net,k8s-app=cilium,app=cilium, \
             app=canal,k8s-app=canal,app=kube-router,k8s-app=kube-router

        # If nothing obvious is returned, list all Pods in kube-system for manual inspection:
        kubectl -n kube-system get pods -o wide
        ```

        **Problem indication:**\
        You cannot clearly identify a well-known CNI plugin from `kube-system` (e.g., no Calico, Cilium, Weave Net, Antrea, Kube-router, Canal, etc.), or you see a vendor-specific/“custom” CNI that must be checked against its documentation to confirm NetworkPolicy support.

        ***

        ```bash theme={null}
        # 2) Check if any NetworkPolicy objects exist in the cluster
        # Run on: any machine with kubectl access
        kubectl get networkpolicies --all-namespaces
        ```

        **Problem indication:**

        * Output is: `No resources found` for all namespaces, **and** you believe there should be traffic restrictions; or
        * Only a few test namespaces use NetworkPolicies while critical namespaces (e.g., `default`, `kube-system`, app namespaces) have none, suggesting network policy is not actually used for isolation.

        ***

        ```bash theme={null}
        # 3) Test basic NetworkPolicy behavior in a non-critical namespace
        #    (this does NOT enforce policy cluster‑wide; it is a safe, temporary check)
        # Run on: any machine with kubectl access

        # 3.1 Create an isolated test namespace
        kubectl create namespace netpol-test

        # 3.2 Create two test pods: one "backend" (with a label) and one "client"
        kubectl -n netpol-test apply -f - << 'EOF'
        apiVersion: v1
        kind: Pod
        metadata:
          name: backend
          labels:
            app: backend
        spec:
          containers:
          - name: backend
            image: docker.io/library/nginx:stable
            ports:
            - containerPort: 80
        ---
        apiVersion: v1
        kind: Pod
        metadata:
          name: client
        spec:
          containers:
          - name: client
            image: docker.io/library/busybox:1.36
            command: ["sh", "-c", "sleep 3600"]
        EOF

        # Wait for pods to be Ready
        kubectl -n netpol-test wait --for=condition=Ready pod/backend --timeout=120s
        kubectl -n netpol-test wait --for=condition=Ready pod/client --timeout=120s

        # Get backend Pod IP
        BACKEND_IP=$(kubectl -n netpol-test get pod backend -o jsonpath='{.status.podIP}')
        echo "$BACKEND_IP"

        # 3.3 Confirm client can reach backend BEFORE any NetworkPolicy
        kubectl -n netpol-test exec client -- wget -qO- "http://$BACKEND_IP" || echo "connect failed"

        # 3.4 Apply a DENY-ALL ingress NetworkPolicy to backend
        kubectl -n netpol-test apply -f - << 'EOF'
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: deny-backend-ingress
        spec:
          podSelector:
            matchLabels:
              app: backend
          policyTypes:
          - Ingress
          ingress: []
        EOF

        # 3.5 Test again AFTER applying NetworkPolicy
        kubectl -n netpol-test exec client -- wget -qO- "http://$BACKEND_IP" || echo "connect failed"
        ```

        **Problem indication (NetworkPolicy behavior test):**

        * If the request from `client` to `backend` **still succeeds** after the `deny-backend-ingress` policy is applied (i.e., `wget` returns the Nginx HTML response instead of failing/timeouts), this strongly suggests:
          * The current CNI does **not** implement Kubernetes `NetworkPolicy`, or
          * It is misconfigured/disabled.

        If `wget` fails/blocks after the policy is applied, the CNI is at least enforcing basic ingress NetworkPolicies.

        ***

        ```bash theme={null}
        # 4) Cleanup test resources after review
        # Run on: any machine with kubectl access
        kubectl delete namespace netpol-test
        ```

        You must now manually decide, based on:

        * Which CNI you discovered in step 1 and its documentation, and
        * Whether NetworkPolicy behavior in step 3 matched expectations,

        whether to keep the current CNI, replace it with one that supports NetworkPolicies, or implement an alternate traffic restriction mechanism. kubectl cannot make that decision automatically.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Purpose: Report whether the current CNI appears to support Kubernetes NetworkPolicies

        set -euo pipefail

        echo "=== 1) Detect CNI plugin(s) in use (from node annotations) ==="
        kubectl get nodes -o custom-columns=NAME:.metadata.name,CNI:.metadata.annotations['k8s\.ovn\.org/node-chassis-id','vpc\.amazonaws\.com/eni-id','cni\.projectcalico\.org/IPv4IPIPTunnelAddr','weave\.works/agent','flannel\.alpha\.coreos\.com/backend-type'] --no-headers || true

        echo
        echo "=== 2) List CNI-related DaemonSets in kube-system (common CNIs) ==="
        kubectl get ds -n kube-system \
          -o custom-columns=NAME:.metadata.name,IMAGES:.spec.template.spec.containers[*].image \
          --no-headers | grep -Ei 'calico|cilium|weave|flannel|canal|cni|ovn|antrea|multus' || \
          echo "No common CNI DaemonSets detected in kube-system."

        echo
        echo "=== 3) List CNI directories on each node (from Node status) ==="
        kubectl get nodes -o custom-columns=NAME:.metadata.name,CNI_DIRS:.status.nodeInfo.containerRuntimeVersion --no-headers

        echo
        echo "=== 4) Try creating a test NetworkPolicy (non-disruptive) ==="
        TEST_NS="cni-networkpolicy-check"
        TEST_NP="np-cni-support-check"

        # Create an isolated namespace for the test policy
        kubectl get ns "${TEST_NS}" >/dev/null 2>&1 || kubectl create ns "${TEST_NS}" >/dev/null

        # Apply a minimal NetworkPolicy that selects no pods (no traffic impact)
        cat <<'EOF' | kubectl apply -f -
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: np-cni-support-check
          namespace: cni-networkpolicy-check
        spec:
          podSelector: {}
          policyTypes:
          - Ingress
          - Egress
        EOF

        echo
        echo "NetworkPolicy object created. Current status:"
        kubectl get networkpolicy -n "${TEST_NS}" "${TEST_NP}" -o yaml | sed -n '1,40p'

        echo
        echo "=== 5) Summary guidance ==="
        cat <<'EOM'
        Review results:

        1) CNI plugin identification:
           - From step (1) and (2), identify which CNI you are running (e.g. calico, cilium, antrea, weave, flannel, canal, ovn-kubernetes, etc.).
           - Cross-check that plugin's documentation to confirm it supports Kubernetes NetworkPolicies.

        2) NetworkPolicy object behavior:
           - If the NetworkPolicy resource in step (4) was ACCEPTED by the API server (it appears in kubectl get output),
             that only confirms the API supports NetworkPolicies, NOT that the CNI enforces them.
           - You must still verify in a follow-up manual test that traffic is actually restricted when NetworkPolicies are applied.

        Indicators of a potential problem:
           - Step (2) does not show a known NetworkPolicy-capable CNI (e.g. only "flannel" with no policy controller).
           - You are using a custom or cloud-vendor CNI whose docs do not explicitly state NetworkPolicy support.
           - NetworkPolicy objects exist but connectivity tests show they are not enforced.

        This script cannot determine with certainty that your CNI enforces NetworkPolicies; it only surfaces
        the likely CNI implementation and confirms that NetworkPolicy objects can be created for manual review.
        EOM
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)
