> ## 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 Latest CNI Version Is Used

### More Info:

The CNI plugin should support and enforce NetworkPolicy following least-privilege access. Start with a deny-all policy for inbound and outbound traffic and add exceptions as needed.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* CIS OKE

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Identify namespaces and current NetworkPolicies**
           * Run on any machine with `kubectl` access:
             ```bash theme={null}
             kubectl get ns
             kubectl get networkpolicy --all-namespaces
             ```
           * Review which namespaces lack any `NetworkPolicy`, as they are effectively “allow all” for ingress/egress.

        2. **Inspect existing NetworkPolicies for least-privilege design**
           * For each namespace with policies, inspect details:
             ```bash theme={null}
             kubectl get networkpolicy -n <namespace> -o yaml
             ```
           * Check that:
             * Policies are scoped to specific `podSelector`s (not missing or overly broad where that would violate least privilege).
             * `ingress`/`egress` rules are as narrow as possible (namespaces, pods, IPBlocks, ports).
             * There is no “catch-all allow” (e.g., empty `ingress`/`egress` arrays interpreted as allow depending on CNI, or rules that match all peers and all ports).

        3. **Determine default behavior (deny vs allow) per namespace**
           * Confirm whether there is an explicit “default deny” for both ingress and egress in each namespace where least privilege is required. Typical examples (for review, not necessarily verbatim for your CNI):
             ```bash theme={null}
             # Example default deny ingress
             kubectl get networkpolicy -n <namespace> default-deny-ingress -o yaml || true

             # Example default deny egress
             kubectl get networkpolicy -n <namespace> default-deny-egress -o yaml || true
             ```
           * If such policies do not exist, note that this namespace is likely in an “allow all” state unless your CNI enforces a different default.

        4. **Review CNI capabilities and NetworkPolicy support**
           * Check which CNI is installed and whether it fully supports Kubernetes `NetworkPolicy` and, if applicable, global policies:
             ```bash theme={null}
             kubectl get pods -n kube-system -o wide | grep -iE 'calico|cilium|weave|flannel|ovn|antrea'
             kubectl get ds -n kube-system -o yaml | grep -i 'cni' -A5 -B5
             ```
           * Use the CNI documentation (outside this procedure) to confirm:
             * Support for `NetworkPolicy` (ingress and egress).
             * Support for “global” policies (e.g., Calico GlobalNetworkPolicy) if you plan to use cluster-wide default denies.

        5. **Design and apply least-privilege default-deny policies**
           * For each target namespace, decide whether to use:
             * A namespace-scoped default deny (`NetworkPolicy` with empty `ingress` and/or `egress` lists and `podSelector: {}`) plus explicit allow policies, or
             * A global/default policy mechanism provided by your CNI (e.g., Calico global policy), if appropriate.
           * Create or update manifests locally, then apply:
             ```bash theme={null}
             kubectl apply -f /absolute/path/to/your-reviewed-networkpolicies.yaml
             ```
           * Ensure that for every namespace where you introduce default deny, you also define the minimal set of allow rules needed for application functionality.

        6. **Verify effective behavior and refine**
           * Confirm policies are in place:
             ```bash theme={null}
             kubectl get networkpolicy --all-namespaces
             ```
           * Optionally test connectivity (from test pods) to verify that:
             * Traffic is blocked by default where intended.
             * Only approved communications succeed.
           * Iterate by adjusting manifests and reapplying with `kubectl apply -f ...` until the balance between least privilege and application requirements is acceptable.
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) List all NetworkPolicies in all namespaces
        # Run on: any machine with kubectl access
        kubectl get networkpolicy --all-namespaces -o wide
        ```

        **What to look for (problem indicators)**

        * No `NetworkPolicy` objects at all, or critical namespaces (e.g. `default`, application namespaces) with **0** policies.
        * Namespaces where **every** policy has `policyTypes` only containing `Ingress` (no `Egress`) or vice versa, implying one direction is completely unrestricted.
        * Namespaces that are security‑sensitive but lack any “default deny” style policies.

        ***

        ```bash theme={null}
        # 2) Inspect all NetworkPolicies, including their spec
        kubectl get networkpolicy --all-namespaces -o yaml
        ```

        **What to look for (problem indicators)**

        * Namespaces with **no policy** that:
          * Explicitly denies all ingress (no `ingress` rules, `policyTypes` includes `Ingress`), and
          * Explicitly denies all egress (no `egress` rules, `policyTypes` includes `Egress`).
        * Policies that are clearly overly permissive, for example:
          * `podSelector: {}` combined with `ingress: []` but **no** corresponding `egress` default deny (or vice versa).
          * Allow rules using `ipBlock: 0.0.0.0/0` or very broad CIDRs.
          * Policies that select all pods in the namespace (`podSelector: {}`) and allow all traffic (empty `ingress` / `egress` sections with missing `policyTypes` so they default to Ingress only).

        ***

        ```bash theme={null}
        # 3) Check which CNI plugin is in use and its version (helps judge capabilities)
        kubectl get pods -n kube-system -o wide \
          | grep -iE 'calico|cilium|weave|flannel|cni|antrea'
        ```

        Then inspect the CNI daemonset or pods:

        ```bash theme={null}
        # Example: describe a suspected CNI DaemonSet
        kubectl get daemonset -n kube-system
        kubectl describe daemonset <cni-daemonset-name> -n kube-system
        ```

        **What to look for (problem indicators)**

        * A CNI plugin known **not** to support Kubernetes `NetworkPolicy`, or configured in a mode that disables policy enforcement.
        * Very old image tags (e.g. obvious legacy versions) suggesting the plugin may lack current NetworkPolicy features or bug fixes.

        ***

        ```bash theme={null}
        # 4) For a specific namespace, review effective policy coverage
        # Replace NAMESPACE with the namespace you care about
        kubectl get networkpolicy -n NAMESPACE -o yaml
        ```

        **What to look for (problem indicators)**

        * No “baseline” policies that:
          * Deny all ingress (`policyTypes: ["Ingress"]` with empty `ingress: []`), and
          * Deny all egress (`policyTypes: ["Egress"]` with empty `egress: []` or combined `["Ingress","Egress"]` with both empty).
        * Policies that only **add allows** without any default deny in that namespace, meaning pods with no matching policy remain fully open.

        ***

        ```bash theme={null}
        # 5) (Optional) For Calico-only clusters, check for any GlobalNetworkPolicies
        kubectl get globalnetworkpolicies.crd.projectcalico.org -A -o yaml 2>/dev/null
        ```

        **What to look for (problem indicators)**

        * Absence of any global “default deny” style `GlobalNetworkPolicy` when you expect cluster‑wide least‑privilege enforcement.
        * Global policies that broadly allow all ingress/egress without fine‑grained selectors.

        ***

        **How to interpret the findings**

        * If you find namespaces (especially `default` or production app namespaces) with **no default deny** for ingress and egress and only permissive or no policies, the cluster is **not** following least‑privilege.
        * If the CNI plugin is old or lacks NetworkPolicy support, then even well‑written policies may not be enforced as intended.

        Deciding *what* policies to add or adjust depends on application requirements and risk appetite and must be done manually based on this evidence.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Purpose:
        #   Cluster-wide review of CNI and NetworkPolicy posture for CIS OKE 4.3.1
        #
        # Run on:
        #   Any machine with kubectl access and current-context pointing at the target cluster.
        #
        # Requirements:
        #   - kubectl in PATH
        #   - jq in PATH (optional but recommended; script degrades gracefully without it)

        set -euo pipefail

        echo "=== 1) Detect CNI implementation and version (cluster-wide) ==="
        echo

        # Try common CNI DaemonSets and custom-resources to infer CNI and versions.
        # This is heuristic only; you must review results manually.

        echo "- Searching for common CNI DaemonSets in kube-system..."
        kubectl get ds -n kube-system 2>/dev/null | sed '1!{/calico\|cilium\|weave\|flannel\|aws-node\|azure-cni\|antrea\|ovn\|kube-router/!d}'
        echo

        echo "- Detailed images for likely CNI DaemonSets:"
        for ds in calico-node cilium aws-node azure-cni antrea-agent kube-flannel-ds weave-net kube-router ovnkube-node; do
          if kubectl get ds "$ds" -n kube-system >/dev/null 2>&1; then
            echo "  * kube-system/DaemonSet/${ds}:"
            kubectl get ds "$ds" -n kube-system -o jsonpath='{.spec.template.spec.containers[*].image}' 2>/dev/null
            echo
          fi
        done
        echo

        echo "- Checking for common CNI CRDs (if present, also imply CNI type):"
        kubectl get crd 2>/dev/null | sed '1!{/calico\|cilium\|antrea\|networkpolicies.crd.projectcalico.org/!d}' || true
        echo

        cat <<'EOF'

        INTERPRETATION (possible problems):
        - If no known CNI DaemonSet is found, determine manually which CNI you run and its version.
        - Compare the listed CNI images/tags with vendor documentation to see if they are:
          - Out of date or unsupported
          - Missing NetworkPolicy support (some basic CNIs ignore NetworkPolicy).
        - A problem for this control is:
          - Using a CNI that does NOT implement Kubernetes NetworkPolicy, or
          - Running obviously obsolete or deprecated CNI versions.
        EOF

        echo
        echo "=== 2) List namespaces lacking any NetworkPolicy (no isolation defined) ==="
        echo

        # Namespaces with zero NetworkPolicy resources
        all_ns=$(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')
        ns_with_np=$(kubectl get networkpolicy --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{"\n"}{end}' | sort -u)
        problem_ns=()

        for ns in $all_ns; do
          if ! printf '%s\n' "$ns_with_np" | grep -qx "$ns"; then
            problem_ns+=("$ns")
          fi
        done

        echo "Namespaces with NO NetworkPolicy objects defined:"
        if [ ${#problem_ns[@]} -eq 0 ]; then
          echo "  (none)"
        else
          for ns in "${problem_ns[@]}"; do
            echo "  - $ns"
          done
        fi
        echo

        cat <<'EOF'
        INTERPRETATION (possible problems):
        - Namespaces listed above have no NetworkPolicy at all.
        - Under CIS guidance, you typically want at least a baseline deny policy
          (or equivalent global policy) so unrestricted traffic is not allowed by default.
        EOF

        echo
        echo "=== 3) Inspect baseline isolation: does each namespace have a 'default deny' policy? ==="
        echo

        # Heuristic check for default-deny-like policies per namespace.

        default_deny_report() {
          local ns="$1"
          echo "Namespace: ${ns}"

          # Get all NPs in namespace as JSON
          if ! np_json=$(kubectl get networkpolicy -n "$ns" -o json 2>/dev/null); then
            echo "  Error: could not fetch NetworkPolicy in namespace."
            return
          fi

          if command -v jq >/dev/null 2>&1; then
            total=$(echo "$np_json" | jq '.items | length')
            echo "  NetworkPolicies: $total"

            # Default deny ingress: spec.podSelector={} and no ingress or empty list
            dd_ingress=$(echo "$np_json" | jq '[.items[]
              | select(.spec.podSelector == {} and (.spec.ingress == null or .spec.ingress == []))
            ] | length')

            # Default deny egress: spec.podSelector={} and no egress or empty list
            dd_egress=$(echo "$np_json" | jq '[.items[]
              | select(.spec.podSelector == {} and (.spec.egress == null or .spec.egress == []))
            ] | length')

            echo "  Default-deny-like ingress policies: $dd_ingress"
            echo "  Default-deny-like egress policies:  $dd_egress"
          else
            echo "  (jq not installed: printing raw policies for manual review)"
            kubectl get networkpolicy -n "$ns" -o yaml
          fi
          echo
        }

        for ns in $all_ns; do
          # Skip namespaces with no NPs (already flagged above)
          if printf '%s\n' "$ns_with_np" | grep -qx "$ns"; then
            default_deny_report "$ns"
          fi
        done

        cat <<'EOF'
        INTERPRETATION (possible problems):
        - For each namespace:
          - If "NetworkPolicies: 0", that namespace has NO isolation.
          - If "Default-deny-like ingress policies: 0", inbound traffic is not globally denied by default.
          - If "Default-deny-like egress policies: 0", outbound traffic is not globally denied by default.
        - CIS guidance prefers:
          - A starting point of deny-all for ingress AND egress at namespace level (or via CNI global policy),
            with explicit allow rules layered on as needed.
        - Note: Some CNIs (e.g., Calico) can enforce global policies outside NetworkPolicy;
          review your CNI’s own policy objects in addition to this output.
        EOF

        echo
        echo "=== 4) Quick summary of potential issues ==="
        echo

        echo "1) CNI / NetworkPolicy support:"
        echo "   - If no capable CNI is detected above or CNI version is very old, investigate and upgrade."
        echo
        echo "2) Namespaces with no NetworkPolicy:"
        if [ ${#problem_ns[@]} -eq 0 ]; then
          echo "   - All namespaces have at least one NetworkPolicy."
        else
          for ns in "${problem_ns[@]}"; do
            echo "   - $ns"
          done
        fi
        echo
        echo "3) Default deny posture:"
        echo "   - Review per-namespace section above."
        echo "   - A problem exists where default-deny-like policies are missing AND no equivalent CNI-global policy exists."
        echo
        echo "This script is assessment-only. Apply fixes by:"
        echo "- Validating/Upgrading the CNI to a NetworkPolicy-aware and supported version, and"
        echo "- Designing and applying explicit deny-all + allow-exception NetworkPolicies (or CNI global policies) per your risk profile."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
