Ensure The CNI In Use Supports Network Policies
More Info:โ
Network Policies are only enforced when the clusters CNI plugin supports them. Enabling Network Policy in GKE updates the CNI to a policy-capable plugin.
Risk Levelโ
Medium
Addressโ
Security
Compliance Standardsโ
- CIS GKE
Triage and Remediationโ
- Remediation
Remediationโ
Manual Steps
-
Confirm GKE Network Policy feature status (per cluster)
- On any machine with
gcloudandkubectlaccess, run:gcloud container clusters list --project YOUR_PROJECT_IDgcloud container clusters describe YOUR_CLUSTER_NAME \--project YOUR_PROJECT_ID \--region YOUR_CLUSTER_REGION \--format="value(networkPolicy.enabled,networkPolicy.provider)" - If
networkPolicy.enabledistrueand a provider is shown (e.g.CALICO), the control plane is configured for Network Policyโcapable CNI. Iffalseor empty, Network Policy is not enabled.
- On any machine with
-
Check that NetworkPolicy objects exist and are being used
- On any machine with
kubectlaccess:kubectl get networkpolicies --all-namespaces - If there are no
NetworkPolicyobjects but you expect network isolation, plan to create them; if there are many, note key namespaces/workloads that rely on them.
- On any machine with
-
Validate that policies are enforced as expected (functional test)
- Create a temporary test namespace and pods:
kubectl create namespace netpol-testkubectl run allowed-client -n netpol-test --image=busybox --restart=Never \--command -- sleep 3600kubectl run test-server -n netpol-test --image=nginx --restart=Neverkubectl expose pod test-server -n netpol-test --port=80
- From
allowed-client, verify it can reach the server before any policy:kubectl exec -n netpol-test allowed-client -- wget -qO- http://test-server
- Create a temporary test namespace and pods:
-
Apply a restrictive NetworkPolicy and observe behavior
- Apply a policy that should block the above traffic:
cat << 'EOF' | kubectl apply -f -apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: deny-all-ingressnamespace: netpol-testspec:podSelector: {}policyTypes:- IngressEOF
- Test connectivity again; it should now fail:
kubectl exec -n netpol-test allowed-client -- wget -qO- http://test-server
- If traffic still succeeds, your CNI is not enforcing NetworkPolicies (or another plugin/feature is overriding behavior).
- Apply a policy that should block the above traffic:
-
If Network Policy is not enabled or not enforced, update cluster configuration
- Decide cluster-by-cluster whether you require NetworkPolicy enforcement. For clusters where you do:
- Use GKE Console: Edit the cluster โ enable โNetwork Policyโ โ save (this may trigger node pool recreation/rolling updates).
- Or via CLI on any machine with
gcloud:gcloud container clusters update YOUR_CLUSTER_NAME \--project YOUR_PROJECT_ID \--region YOUR_CLUSTER_REGION \--enable-network-policy
- Plan maintenance windows as this can recreate nodes and briefly disrupt workloads.
- Decide cluster-by-cluster whether you require NetworkPolicy enforcement. For clusters where you do:
-
Re-verify after changes
- After the update completes, repeat steps 1โ4 to confirm:
networkPolicy.enabledistruewith a supported provider.- The functional test shows traffic is allowed without policy and blocked with policy.
- Clean up the test namespace when done:
kubectl delete namespace netpol-test
- After the update completes, repeat steps 1โ4 to confirm:
Using kubectl
# 1) List all NetworkPolicy objects in all namespaces
# Run on: any machine with kubectl access
kubectl get networkpolicy --all-namespaces -o wide
Review points:
- If you expect NetworkPolicies to be used and this returns no resources found, then NetworkPolicy is not being used; this may indicate a gap in your design, not in the CNI itself.
# 2) Inspect a sample NetworkPolicy (replace with a real name/namespace)
kubectl get networkpolicy -n default -o yaml
kubectl describe networkpolicy -n default <networkpolicy-name>
Review points:
- Ensure policies target pods that actually exist (selectors match current pod labels).
- Check
kubectl describefor any events or warnings suggesting policies are not applied as expected.
# 3) Confirm NetworkPolicy is recognized as an API resource
kubectl api-resources | grep -i networkpolicy
Expected:
- You should see an entry like:
networkpolicies networking.k8s.io/v1 true NetworkPolicy
- If there is no line for
networkpolicies, the cluster is misconfigured or very old; NetworkPolicy cannot work regardless of CNI.
# 4) Verify GKE cluster Network Policy feature status (GKE only)
# Run from: any machine with gcloud + kubectl configured and same project
gcloud container clusters list \
--format="table(name,location,networkPolicy.networkPolicyConfig.disabled,networkConfig.datapathProvider)"
# For a specific cluster (replace with actual cluster name and location)
gcloud container clusters describe <cluster-name> \
--zone <zone> \
--format="flattened(networkPolicy,networkConfig.datapathProvider)"
Review points:
- For
gcloud container clusters list, look at:networkPolicy.networkPolicyConfig.disabledfalseโ Network Policy is enabled at the GKE control-plane level.trueor empty โ Network Policy is not enabled; even if NetworkPolicy objects exist, they will not be enforced by the CNI.
networkConfig.datapathProvider:ADVANCED_DATAPATHor an equivalent policy-capable provider is expected when Network Policy is enabled.- If Network Policy is disabled and you rely on it for isolation, this is a problem.
# 5) (Optional) Simple runtime check using a temporary test pod
# Create two test pods with labels (in a non-critical namespace)
kubectl create ns netpol-test
kubectl run client --image=busybox -n netpol-test --restart=Never --command -- sleep 3600
kubectl run server --image=busybox -n netpol-test --restart=Never --command -- sh -c "nc -lk -p 80"
# Wait until both are Running, then:
kubectl get pods -n netpol-test -o wide
# 6) Apply a restrictive NetworkPolicy and test connectivity
cat <<'EOF' | kubectl apply -n netpol-test -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-egress
spec:
podSelector:
matchLabels: {}
policyTypes:
- Egress
EOF
# From client pod: attempt to connect to server and to the internet
kubectl exec -n netpol-test client -- sh -c "nc -vz server 80 || echo 'connect to server failed'"
kubectl exec -n netpol-test client -- sh -c "wget -qO- http://example.com || echo 'connect to internet failed'"
Review points:
- If NetworkPolicy is supported and enforced, you should see:
- Connections that were previously succeeding now failing after the policy is applied, consistent with the policy rules.
- If connections continue to succeed despite a clearly restrictive policy, that strongly suggests:
- The CNI in use is not enforcing NetworkPolicies, or
- Network Policy is not enabled at the GKE cluster level.
# 7) Cleanup of test namespace when finished
kubectl delete ns netpol-test
Finding interpretation:
- Problem indicated when:
- GKE cluster Network Policy is disabled, yet you rely on NetworkPolicies for pod isolation, or
- Runtime tests show NetworkPolicies have no effect on traffic, despite being created and recognized by the API.
Automation
#!/usr/bin/env bash
# Purpose: Report whether the cluster's CNI and nodes support Kubernetes NetworkPolicies.
# Run on: any machine with kubectl access and 'kubectl' configured for the target cluster.
set -euo pipefail
echo "=== 1) Detect cluster type (looking for GKE) ==="
kubectl config current-context || {
echo "ERROR: No current kubectl context" >&2
exit 1
}
CONTEXT="$(kubectl config current-context)"
echo "Current context: ${CONTEXT}"
# Heuristic: GKE contexts typically look like gke_PROJECT_ZONE_CLUSTER
if [[ "${CONTEXT}" == gke_* ]]; then
echo "Cluster appears to be GKE (context name starts with 'gke_')."
else
echo "Cluster does not look like a standard GKE context."
echo "This CISGKE control is intended for GKE, but results below may still be informative."
fi
echo
echo "=== 2) Inspect CNI-related DaemonSets in kube-system ==="
kubectl -n kube-system get ds \
-o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,IMAGES:.spec.template.spec.containers[*].image' \
| sed '1!{/cni\|calico\|weave\|cilium\|flannel\|canal/!d}'
echo
echo "Details for suspected CNI DaemonSets (kube-system) ==="
for ds in $(kubectl -n kube-system get ds -o name | sed -n '/cni\|calico\|weave\|cilium\|flannel\|canal/p'); do
echo "--- ${ds} ---"
kubectl -n kube-system get "${ds}" -o yaml | awk '
/kind: DaemonSet/ {print "# DaemonSet metadata:"}
/name: / && /DaemonSet/ {print " " $0}
/image: / {print " " $0}
' || true
done
echo
echo "=== 3) Show CNI configuration files on each node (via hostPath mounts) ==="
echo "Looking for known CNI config directories mounted into pods in kube-system..."
kubectl -n kube-system get pods -o wide
echo
echo "Pods in kube-system with hostPath mounts under /etc/cni or /opt/cni: "
kubectl -n kube-system get pods -o json \
| jq -r '
.items[]
| {name: .metadata.name, ns: .metadata.namespace, volumes: .spec.volumes}
| select(.volumes != null)
| . as $pod
| $pod.volumes[]
| select(.hostPath != null)
| select(.hostPath.path | test("^/etc/cni|^/opt/cni"))
| "Pod: \($pod.ns)/\($pod.name) hostPath: \(.hostPath.path)"
'
echo
echo "NOTE: The above shows where CNI configs live on nodes (via hostPath mounts)."
echo "You must manually log into nodes to inspect exact CNI config if needed."
echo
echo "=== 4) Check if any NetworkPolicy objects exist in the cluster ==="
kubectl get networkpolicy --all-namespaces || true
echo
echo "Interpretation:"
echo "- If you have NO NetworkPolicy objects, this control is low-risk right now,"
echo " but you still must ensure the CNI supports NetworkPolicy BEFORE creating any."
echo
echo "=== 5) Check for typical GKE Network Policy signals ==="
echo "Checking for GKE-specific annotations/labels that often indicate Network Policy enablement..."
echo
echo "-- Cluster-wide hint from kube-system namespace (not authoritative) --"
kubectl get ns kube-system -o yaml \
| sed -n '/annotations:/,/labels:/p' || true
echo
echo "-- GKE-managed network policy controller (if present) --"
kubectl -n kube-system get deploy \
-o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name' \
| sed -n '/netpol\|network-policy\|calico\|cilium/p' || true
echo
echo "=== 6) Summary / what indicates a potential PROBLEM ==="
cat <<'EOF'
You must manually decide whether the CNI in use supports Kubernetes NetworkPolicy.
Use the data above and the guidance below:
POTENTIAL PROBLEM indicators:
- The only visible CNI-related DaemonSets/images are known NON-policy CNIs (e.g. plain 'k8s.gcr.io/pause'
does not count; common non-policy CNIs include plain 'flannel' without policy add-ons).
- You see NetworkPolicy objects in the cluster (step 4 lists them), BUT:
* There is no known policy-capable CNI DaemonSet (e.g. no Calico, Cilium, GKE Network Policy add-on),
OR
* You know from GKE console that "Network Policy" is DISABLED for this cluster.
- On GKE specifically:
* GKE console shows Network Policy is disabled for the cluster (you must check this manually),
OR
* Your CNI images look like the older non-policy CNI used by GKE before Network Policy was enabled.
LIKELY OK indicators (but still require human confirmation):
- On GKE:
* GKE console shows Network Policy ENABLED for the cluster, AND
* You see CNI/Network Policy components consistent with the enabled add-on.
- On non-GKE clusters:
* You clearly identify a CNI with documented NetworkPolicy support (e.g. Calico, Cilium, Weave Net
with policy, Canal, etc.) from the DaemonSet/images and node CNI configs.
Because this is a MANUAL control, there is no automated pass/fail:
- Use this script to inventory:
* Which CNI DaemonSets and images are present
* Whether NetworkPolicy resources are being used
- Then:
* For GKE: verify in the GKE console/CLI that Network Policy is enabled for the cluster.
* For other environments: consult the CNI plugin's official documentation to confirm it
supports Kubernetes NetworkPolicy semantics.
If you discover:
- NetworkPolicies in use AND a CNI that does NOT support them:
-> This is a finding. You must plan a migration to a policy-capable CNI
(on GKE, by enabling Network Policy for the cluster).
EOF