Ensure Latest Cni Version Is Used
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
Low
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS Critical Security Controls v8
- CIS OKE
- CMMC 2.0
- CSA Cloud Controls Matrix v4
- DPDPA
- Digital Operational Resilience Act (EU)
- Essential 8
- 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
- Remediation
Remediation
Manual Steps
-
Identify the CNI plugin and version in use
- On any machine with kubectl access:
kubectl get pods -n kube-system -o wide | egrep 'calico|cilium|weave|flannel|cni|antrea'kubectl get ds -n kube-system -o wide | egrep 'calico|cilium|weave|flannel|cni|antrea'
- For each identified CNI DaemonSet, get its image(s):
kubectl get ds -n kube-system <CNI_DAEMONSET_NAME> -o jsonpath='{.spec.template.spec.containers[*].image}{"\n"}'
- Compare the image tags/digests to the vendor’s official release page to determine if they are current and supported.
- On any machine with kubectl access:
-
Verify the CNI supports NetworkPolicies
- On any machine with kubectl access, check if
networkpoliciesare recognized:kubectl api-resources | grep -i networkpolicy - Confirm in the CNI’s official documentation that it fully implements Kubernetes
NetworkPolicysemantics (ingress and, if applicable, egress). If the current CNI does not support NetworkPolicies, plan a migration to a CNI that does (for example, Calico, Cilium, Antrea), following that vendor’s migration guide.
- On any machine with kubectl access, check if
-
Check for presence and scope of NetworkPolicies
- List all namespaces and whether they have any NetworkPolicies:
kubectl get nskubectl get networkpolicy --all-namespaces
- Identify critical namespaces without NetworkPolicies:
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); doecho "Namespace: $ns"kubectl get networkpolicy -n "$ns"echodone
- List all namespaces and whether they have any NetworkPolicies:
-
Assess default traffic posture and gaps
- For each critical namespace without a “default deny” style policy, inspect pod labels and traffic needs:
kubectl get pods -n <NAMESPACE> --show-labels -o widekubectl get svc -n <NAMESPACE> -o wide
- Determine which workloads should be reachable from where (ingress) and which outbound destinations are required (egress). Document any namespaces where current behavior is “allow all” but should be restricted.
- For each critical namespace without a “default deny” style policy, inspect pod labels and traffic needs:
-
Design and apply least-privilege NetworkPolicies (including deny-all)
- For each selected namespace, create a baseline deny-all policy (example template to adapt before applying):
cat <<'EOF' > deny-all.yamlapiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: default-deny-allnamespace: <NAMESPACE>spec:podSelector: {}policyTypes:- Ingress- EgressEOFkubectl apply -f deny-all.yaml
- Then create additional, narrow NetworkPolicies to explicitly allow only required ingress/egress per application (using labels identified earlier). Apply them with
kubectl apply -f <file>.yamlon any machine with kubectl access.
- For each selected namespace, create a baseline deny-all policy (example template to adapt before applying):
-
Verify behavior and CNI health after changes
- Confirm NetworkPolicies are in place:
kubectl get networkpolicy -A
- Optionally, perform connectivity tests between pods that should be allowed vs. denied (for example, using
kubectl execandcurl/ping) to ensure the deny-all and allow rules behave as intended:kubectl exec -n <NAMESPACE> -it <POD_NAME> -- sh -c "curl -m 5 http://<TARGET_IP_OR_SERVICE> || echo 'blocked or unreachable'"
- Confirm NetworkPolicies are in place:
Using kubectl
# 1) Identify which CNI plugin is in use
# Run on: any machine with kubectl access
kubectl get pods -n kube-system -o wide \
| egrep -i 'calico|cilium|weave|flannel|canal|antrea|ovn|aws-node|azure-cni|gke|cni'
kubectl get daemonsets -n kube-system -o wide \
| egrep -i 'calico|cilium|weave|flannel|canal|antrea|ovn|aws-node|azure-cni|gke|cni'
# Problem indication:
# - No CNI-related pods or DaemonSets found (cluster networking may be misconfigured).
# - A CNI is present but is known NOT to support Kubernetes NetworkPolicy (e.g. basic flannel without policy add‑ons).
# 2) Inspect CNI DaemonSet details (image and version)
# Replace <cni-daemonset-name> with the name found above, for example: calico-node, cilium, weave-net, antrea-agent, aws-node, azure-cni, etc.
kubectl get daemonset <cni-daemonset-name> -n kube-system -o yaml
# Problem indication:
# - Image tag is very old (e.g., pinned to a years‑old version).
# - Image tag is "latest" (no explicit version -> hard to track compliance and vulnerabilities).
# - Vendor/project documentation says this version lacks NetworkPolicy support or is end‑of‑life.
# 3) Check if any NetworkPolicy objects exist cluster‑wide
kubectl get networkpolicy --all-namespaces
# Problem indication:
# - No NetworkPolicy resources at all -> likely no actual traffic restriction is enforced, even if the CNI supports it.
# 4) Examine effective policies in a critical namespace (e.g. production)
# Replace <namespace> with a sensitive namespace such as "default", "prod", etc.
kubectl get networkpolicy -n <namespace> -o yaml
# Problem indication:
# - No policies or only very permissive policies (e.g., allow all ingress/egress).
# - No "default deny" style policy (either via policy or via a global CNI construct like Calico GlobalNetworkPolicy).
# 5) Identify namespaces with no NetworkPolicy at all
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
| while read ns; do
echo "Namespace: $ns"
kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null || echo " <no NetworkPolicy>"
echo
done
# Problem indication:
# - Important namespaces (production, staging, system, etc.) show "<no NetworkPolicy>" and your CNI does not provide a global default deny.
# 6) (Calico-specific) Check for Calico global default policies, if Calico is detected
# Only meaningful if Calico is in use.
kubectl get globalnetworkpolicy,networkpolicy -A 2>/dev/null
# Problem indication:
# - With Calico, neither GlobalNetworkPolicy nor namespace NetworkPolicy objects implement a default deny,
# and there are broad allow-all style policies instead.
Automation
#!/usr/bin/env bash
#
# Automation: Report CNI plugin and NetworkPolicy support across the cluster
#
# Run on: any machine with kubectl access and cluster-admin privileges
#
# Usage:
# ./cni-networkpolicy-report.sh
#
# This script DOES NOT fix anything. It summarizes:
# - CNI plugin(s) in use on each node
# - Whether NetworkPolicy CRD is available
# - Which namespaces have NetworkPolicies
# - Whether any namespace is effectively "wide open" (no policies)
#
set -euo pipefail
echo "=== 1) Cluster CNI detection ==="
echo
# Try to infer CNI from node annotations (works for many managed offerings)
echo "# Node-level CNI-related annotations:"
kubectl get nodes -o json | jq -r '
.items[]
| [.metadata.name,
(.metadata.annotations // {} | to_entries[]
| select(.key | test("cni|calico|weave|flannel|amazonaws.com/networking|azure\\.com/network|k8s\\.ovn\\.org"; "i"))
| "\(.key)=\(.value)")]
| select(.[1] != null)
| @tsv' 2>/dev/null || echo "jq not installed or no matching annotations found."
echo
echo "# Kube-system pods that look like CNI components:"
kubectl get pods -n kube-system -o wide | \
egrep -i 'calico|weave|flannel|cilium|cni|antrea|ovn|aws-node|azure|gke|cni-metrics' || \
echo "No obvious CNI-related pods detected in kube-system."
echo
echo "=== 2) Check if NetworkPolicy is supported by the API server ==="
echo
if kubectl api-resources --api-group=networking.k8s.io | grep -q "^networkpolicies"; then
echo "NetworkPolicy CRD is PRESENT in this cluster."
else
echo "WARNING: NetworkPolicy CRD NOT present: CNI or control-plane may not support NetworkPolicy."
echo "This is a PROBLEM: you cannot enforce Kubernetes NetworkPolicies without this resource."
fi
echo
echo "=== 3) Namespaces and their NetworkPolicies ==="
echo
# List all namespaces with count of NetworkPolicies
printf "%-30s %-10s\n" "NAMESPACE" "NP_COUNT"
echo "-----------------------------------------------"
kubectl get ns -o json | jq -r '
.items[].metadata.name' | while read -r ns; do
count=$(kubectl get networkpolicies.networking.k8s.io -n "$ns" --ignore-not-found -o name | wc -l | tr -d ' ')
printf "%-30s %-10s\n" "$ns" "$count"
done
echo
echo "=== 4) Namespaces with ZERO NetworkPolicies (potentially wide open) ==="
echo
no_np_ns=$(kubectl get ns -o json | jq -r '.items[].metadata.name' | while read -r ns; do
count=$(kubectl get networkpolicies.networking.k8s.io -n "$ns" --ignore-not-found -o name | wc -l | tr -d ' ')
if [ "$count" -eq 0 ]; then
echo "$ns"
fi
done)
if [ -z "$no_np_ns" ]; then
echo "All namespaces have at least one NetworkPolicy object."
else
echo "$no_np_ns"
echo
echo "INTERPRETATION:"
echo "- Each namespace listed above has NO NetworkPolicy defined."
echo "- This often indicates a PROBLEM relative to least-privilege:"
echo " * Traffic to/from pods in these namespaces is likely unrestricted by NetworkPolicies."
echo " * You should consider adding a baseline 'default-deny' policy and then explicitly allow required flows."
fi
echo
echo "=== 5) Sample view of existing NetworkPolicies (for review) ==="
echo
# Show basic info about existing NetworkPolicies
kubectl get networkpolicies.networking.k8s.io --all-namespaces -o wide || \
echo "No NetworkPolicies found in the cluster."
echo
echo "=== 6) CNI plugins discovered on nodes (host-level view, informational) ==="
echo
echo "NOTE: This part requires privileged access on nodes and is for reference only."
echo " It CANNOT be run via kubectl; use SSH/daemonset or another mechanism if needed."
echo
cat <<'EOF'
# Example (run on each node via SSH or privileged DaemonSet):
sudo ls -R /etc/cni/net.d /opt/cni/bin 2>/dev/null
# PROBLEM indicators:
# - Only very old CNI plugins present or unknown/unsupported vendor builds.
# - Documentation for the detected plugin indicates it does NOT support NetworkPolicies.
# - Multiple conflicting CNI plugins on the same node without clear configuration (misconfiguration risk).
EOF
echo
echo "=== How to interpret results ==="
echo
cat <<'EOF'
POTENTIAL PROBLEMS TO INVESTIGATE MANUALLY:
1) No NetworkPolicy CRD:
- Output: "WARNING: NetworkPolicy CRD NOT present"
- Meaning: The cluster/CNI combination likely does not support NetworkPolicies.
- Risk: You cannot implement least-privilege network access with standard Kubernetes NetworkPolicies.
2) Namespaces with NP_COUNT = 0:
- Namespaces listed under "Namespaces with ZERO NetworkPolicies" are likely over-permissive.
- Risk: Pods in these namespaces can usually talk to anything else allowed by the underlying network.
3) CNI implementation without NetworkPolicy support:
- If kube-system CNI pods (calico, cilium, antrea, etc.) are NOT present,
or you recognize a plugin that does not implement NetworkPolicies,
there is a design gap.
- You must confirm from the plugin documentation whether NetworkPolicies are enforced.
This script only REPORTS the current state. Use these findings to:
- Decide if you must migrate to or enable a CNI that supports NetworkPolicies.
- Plan and implement a default-deny NetworkPolicy per namespace (or a global one, e.g., with Calico)
and then add explicit allow rules for necessary traffic.
EOF