Skip to main content

Ensure That The Cni In Use 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 GKE

Triage and Remediation

Remediation

Manual Steps
  1. From any machine with kubectl access, confirm whether GKE Network Policy is enabled on each cluster (GKE-managed CNI):

    gcloud container clusters list --format="table(name,location,networkPolicy.enabled,networkConfig.datapathProvider)"

    For a specific cluster:

    gcloud container clusters describe CLUSTER_NAME --region=REGION \
    --format="flattened(networkPolicy,networkConfig.datapathProvider)"
  2. If networkPolicy.enabled is false for the cluster, decide whether you can enable it based on your environment (some settings like specific datapath providers or add‑ons may be incompatible). Review Google’s constraints for enabling Network Policy and plan a maintenance window, as enabling it causes nodes to be recreated.

  3. To enable Network Policy on an existing cluster (triggers node recreation; run from any machine with gcloud access):

    gcloud container clusters update CLUSTER_NAME --region=REGION \
    --update-addons=NetworkPolicy=ENABLED \
    --enable-network-policy

    For a new cluster, include Network Policy at creation:

    gcloud container clusters create CLUSTER_NAME --region=REGION \
    --enable-network-policy \
    --addons=NetworkPolicy
  4. After Network Policy is enabled and the cluster has stabilized, verify that NetworkPolicy resources are accepted by the API (any machine with kubectl):

    kubectl api-resources | grep -i networkpolicy
    kubectl explain networkpolicy.spec
  5. Optionally validate that Network Policies are actually enforced by deploying a simple test in a non‑production namespace (any machine with kubectl):

    kubectl create ns netpol-test
    kubectl run allowed --image=busybox -n netpol-test --restart=Never --command -- sleep 3600
    kubectl run blocked --image=busybox -n netpol-test --restart=Never --command -- sleep 3600
    kubectl expose pod allowed -n netpol-test --port=80 --name=allowed-svc --target-port=80
    kubectl apply -n netpol-test -f - <<'EOF'
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
    name: deny-from-blocked
    spec:
    podSelector:
    matchLabels:
    run: allowed
    policyTypes:
    - Ingress
    ingress:
    - from:
    - podSelector:
    matchLabels:
    run: allowed
    EOF
  6. Verify behavior of the test policy (any machine with kubectl):

    kubectl exec -n netpol-test blocked -- wget -qO- http://allowed-svc:80 || echo "blocked: cannot connect (expected)"
    kubectl exec -n netpol-test allowed -- wget -qO- http://allowed-svc:80 || echo "allowed: can connect (expected)"

    If Network Policy is enabled and enforced, the first command should fail to connect while the second should succeed. Clean up when finished:

    kubectl delete ns netpol-test
Using kubectl
# 1) Confirm clusters have Network Policy enabled (GKE)
# Run on any machine with kubectl access
kubectl get nodes -o jsonpath='{.items[0].metadata.labels}' | jq

Review the labels for a networking.gke.io or network-policy-related label that reflects Network Policy being enabled on the cluster.
If you see nothing related to network policy at all, that is a red flag and you must confirm via gcloud container clusters describe or the GKE console whether Network Policy is enabled.

# 2) Check that at least one NetworkPolicy object exists
kubectl get networkpolicy --all-namespaces
  • If this returns No resources found across all namespaces, Network Policies are not currently used.
    This by itself does not prove the CNI is incompatible, but it means your cluster is not actually enforcing any pod-level network restrictions yet.
# 3) Inspect an existing NetworkPolicy to confirm it is recognized
# Replace <namespace> and <name> with any policy from the previous command
kubectl describe networkpolicy -n <namespace> <name>
  • If the object is present and kubectl describe shows no warnings or errors, the API server accepts NetworkPolicy objects.
  • If you see repeated Events or warnings about not being able to enforce the policy, or controller errors referring to network policy, this may indicate CNI/plugin or cluster configuration issues.
# 4) Check whether any pods are explicitly labeled as network-policy related (implementation hint)
kubectl get pods -n kube-system -o wide

Look for pods with names suggesting network policy enforcement (e.g. calico-*, cilium-*, kube-router-*, or a GKE-specific network policy agent).

  • If there are no such pods or DaemonSets and you know Network Policy is supposed to be enabled, verify via GKE settings that the cluster was created with Network Policy enabled so that GKE can install the appropriate components.
# 5) Optional: check for any NetworkPolicy-related errors in events
kubectl get events -A --sort-by=.lastTimestamp | grep -i networkpolicy
  • Repeated errors that mention inability to program rules, unsupported features, or CNI issues indicate that the current CNI or configuration may not correctly support Network Policies and should be reviewed manually.

These kubectl checks surface whether:

  • NetworkPolicy resources are in use and understood by the API, and
  • There is an obvious absence or malfunction of network-policy-related components.

Determining definitively whether the CNI in use supports Network Policies still requires manual review of your GKE cluster configuration (Network Policy feature flag) and the corresponding CNI documentation.

Automation
#!/usr/bin/env bash
#
# cisgke-4.3.1-network-policy-support-check.sh
#
# Run on: any machine with kubectl access and current context set
# Purpose: Report NetworkPolicy support and usage across the cluster
# for manual review of CIS GKE 4.3.1.

set -euo pipefail

echo "=== CIS GKE 4.3.1: NetworkPolicy / CNI Support Review ==="
echo "Kubeconfig context: $(kubectl config current-context)"
echo

echo "1) Cluster-wide NetworkPolicy features (if available)"
echo "-----------------------------------------------------"
if kubectl get --raw /apis/networking.k8s.io/v1 >/dev/null 2>&1; then
echo "networking.k8s.io/v1 API is available (NetworkPolicy objects are supported by the apiserver)."
else
echo "WARNING: networking.k8s.io/v1 API not available. NetworkPolicy CRD/API missing or misconfigured."
fi
echo

echo "2) GKE NetworkPolicy status (GKE-specific, if API present)"
echo "----------------------------------------------------------"
if kubectl get clusternetworkpolicies.networking.gke.io >/dev/null 2>&1; then
echo "GKE ClusterNetworkPolicy CRD detected (GKE Network Policy features enabled)."
else
echo "NOTE: GKE ClusterNetworkPolicy CRD not detected. This may mean:"
echo " - GKE Network Policy is not enabled for this cluster, or"
echo " - This is not a GKE cluster, or"
echo " - Different network policy implementation is used."
fi
echo

echo "3) Node-level CNI information (for context only)"
echo "-----------------------------------------------"
echo "Listing node labels that may indicate CNI / networking setup:"
kubectl get nodes -o custom-columns=NAME:.metadata.name,NETWORK-LABELS:.metadata.labels."beta\.kubernetes\.io\/instance-type",CNI:.metadata.labels."k8s\.ovn\.org\/gateway"
echo
echo "You may need to correlate node pool configuration in GCP console/IaC to confirm:"
echo " - Whether 'Network Policy for GKE' is enabled"
echo " - Which CNI is in use (GKE native, Calico, etc.)"
echo

echo "4) Namespaces and presence of NetworkPolicy resources"
echo "-----------------------------------------------------"
echo "Namespaces WITHOUT any NetworkPolicy:"
kubectl get ns -o json \
| jq -r '
.items[]
| .metadata.name as $ns
| $ns,
(../*? | select(.kind == "NetworkPolicy") | .metadata.namespace) as $npns
' >/dev/null 2>&1 || true

# Simpler, more robust approach:
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l | tr -d ' ')
if [ "$count" -eq 0 ]; then
echo " - $ns"
fi
done
echo
echo "Namespaces WITH NetworkPolicy and their policies:"
kubectl get networkpolicy --all-namespaces -o wide || echo "No NetworkPolicy objects found in any namespace."
echo

echo "5) Effective coverage summary"
echo "-----------------------------"
total_ns=$(kubectl get ns --no-headers 2>/dev/null | wc -l | tr -d ' ')
np_ns=$(kubectl get networkpolicy --all-namespaces -o json 2>/dev/null \
| jq -r '.items[].metadata.namespace' 2>/dev/null \
| sort -u | wc -l | tr -d ' ' || echo 0)

echo "Total namespaces: $total_ns"
echo "Namespaces with policy: $np_ns"
if [ "$total_ns" -gt 0 ]; then
pct=$(( 100 * np_ns / total_ns ))
echo "Coverage (by namespace): ~${pct}%"
fi
echo

echo "6) Interpretation guidance"
echo "--------------------------"
cat <<'GUIDE'
Review the output manually:

Potential problems indicating non-compliance with CIS GKE 4.3.1:
- GKE Network Policy is not enabled at the cluster level:
* No indication of GKE NetworkPolicy / CNP CRDs
* Cluster configuration (check in GCP console/IaC) shows Network Policy disabled
- The cluster uses a CNI that does NOT enforce Kubernetes NetworkPolicy objects:
* You see NetworkPolicy API objects, but provider docs say the CNI ignores them.
* (Must be confirmed outside of kubectl, in GKE configuration / documentation.)
- No NetworkPolicy objects defined in security-sensitive namespaces:
* Many or all namespaces listed under "Namespaces WITHOUT any NetworkPolicy"
* Especially concerning for namespaces running internet-exposed or multi-tenant workloads.

This script does NOT:
- Confirm that the underlying CNI enforces NetworkPolicies (must be verified in GKE config/docs).
- Validate correctness of policy rules; it only reports presence/absence and coverage.

To remediate:
- In GKE, enable Network Policy for the cluster/node pools and use a CNI that supports it.
- Then create appropriate NetworkPolicy/ClusterNetworkPolicy objects for your namespaces.

GUIDE

Additional Reading: