Skip to main content

Ensure All Namespaces Have Network Policies Defined

More Info:

Without NetworkPolicy objects, all pods can communicate freely, enabling lateral movement. Install a NetworkPolicy-capable provider such as Calico and define policies for every namespace.

Risk Level

High

Address

Security

Compliance Standards

  • CIS OKE

Triage and Remediation

Remediation

Manual Steps
  1. Confirm current CNI and NetworkPolicy support

    • On any machine with kubectl access:
      kubectl -n kube-system get pods -o wide
      kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}' ; echo
    • Review CNI pods (e.g., flannel, calico-node, cilium-...). If only flannel (or another non–NetworkPolicy-capable CNI) is present, plan to deploy a NetworkPolicy-capable provider (for example, Calico in “Calico + flannel” mode) following its official documentation before proceeding with policy design.
  2. Inventory namespaces and existing NetworkPolicies

    • On any machine with kubectl access:
      kubectl get ns
      kubectl get networkpolicy --all-namespaces
    • Identify namespaces without any NetworkPolicy:
      kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{" "}{end}' | tr ' ' '\n' | while read ns; do
      [ -z "$ns" ] && continue
      count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l | tr -d ' ')
      echo "$ns: $count"
      done
    • List all namespaces where the count is 0; these are in scope for remediation.
  3. Classify each namespace’s intended traffic model

    • For each namespace (especially those with 0 policies), gather workload info:
      kubectl get deploy,sts,ds,svc,po -n <namespace>
    • With the application owners, decide for each namespace:
      • Which external CIDRs or namespaces may reach its pods (ingress).
      • Which destinations (namespaces, services, or CIDRs) its pods must contact (egress).
      • Whether intra-namespace pod-to-pod traffic should be allowed by default or restricted.
  4. Design and apply baseline NetworkPolicies per namespace

    • For each namespace lacking policies, create at least a minimal, reviewed policy manifest. Examples to adapt (save and edit before applying):
      • Default deny all ingress/egress (tightest posture):
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
        name: default-deny-all
        namespace: <namespace>
        spec:
        podSelector: {}
        policyTypes:
        - Ingress
        - Egress
      • Allow intra-namespace traffic but deny cross-namespace by default:
        apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
        name: allow-same-namespace
        namespace: <namespace>
        spec:
        podSelector: {}
        policyTypes:
        - Ingress
        - Egress
        ingress:
        - from:
        - podSelector: {}
        egress:
        - to:
        - podSelector: {}
    • Apply with kubectl from any machine with kubectl access:
      kubectl apply -f <policy-file>.yaml
    • Add additional, narrower policies (per app labels) as needed to explicitly permit required ingress/egress.
  5. Functionally validate impact with test pods

    • In at least one hardened namespace, run a temporary debug pod:
      kubectl run netpol-test -n <namespace> --image=busybox:1.36 --restart=Never --command -- sleep 3600
    • From that pod, test expected/blocked connectivity (adjust hostnames/IPs):
      kubectl exec -n <namespace> netpol-test -- wget -qO- http://<service-or-ip> || echo "blocked or error"
    • Confirm results align with the designed policy (required paths work, disallowed paths fail). Adjust NetworkPolicies iteratively if necessary.
  6. Re-verify cluster-wide compliance

    • After policies are in place and validated, re-run evidence collection from any kubectl-capable machine:
      kubectl get networkpolicy --all-namespaces
      kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{" "}{end}' | tr ' ' '\n' | while read ns; do
      [ -z "$ns" ] && continue
      count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l | tr -d ' ')
      echo "$ns: $count"
      done
    • Confirm every non-system namespace has at least one intentional, documented NetworkPolicy and that a NetworkPolicy-capable CNI is deployed and healthy.
Using kubectl

Using kubectl

Run these commands from any machine with kubectl access.

  1. List all namespaces and see which have zero NetworkPolicies:
kubectl get ns --no-headers | awk '{print $1}' | while read ns; do
count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l | tr -d ' ')
echo "$ns $count"
done

What indicates a problem: Any namespace that shows 0 means there is no NetworkPolicy at all in that namespace, so pod-to-pod traffic there is completely unrestricted at the Kubernetes layer.

  1. View namespaces with and without NetworkPolicies in a more visual way:
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
echo "Namespace: $ns"
kubectl get networkpolicy -n "$ns"
echo "----"
done

What indicates a problem:

  • No resources found in <namespace> namespace. → that namespace has no NetworkPolicies.
  • Namespaces that only have very permissive policies (for example, a policy that selects all pods and allows all ingress and egress from/to all namespaces/CIDRs) may be effectively equivalent to having no policy and should be reviewed by a human.
  1. Check which CNI plugin is running on the nodes (to confirm NetworkPolicy support):
kubectl get pods -n kube-system -o wide | egrep -i 'calico|flannel|cilium|weave|ovn|antrea'

What indicates a problem:

  • If you only see flannel-related pods (for example, kube-flannel-ds-*) and no NetworkPolicy-capable CNI such as calico, cilium, antrea, weave-net, etc., then NetworkPolicy objects will not be enforced even if they exist.
  1. Inspect the details of existing NetworkPolicies in a specific namespace (replace NAMESPACE as needed):
kubectl get networkpolicy -n NAMESPACE -o yaml

What indicates a problem:

  • Policies that have podSelector: {} and allow all ingress/egress from everywhere (e.g., from: [] or to: [] or broad ipBlock ranges) can indicate a configuration that does not meaningfully restrict traffic and should be assessed manually.
Automation
#!/usr/bin/env bash
# Report namespaces without any NetworkPolicy objects
# Run on: any machine with kubectl access and KUBECONFIG set

set -euo pipefail

echo "== Cluster NetworkPolicy capability check =="

# 1) Check if NetworkPolicy CRD is usable (some CNIs ignore it even if API exists)
echo
echo "-> Verifying that the NetworkPolicy API is available..."
if ! kubectl api-resources --api-group=networking.k8s.io | grep -q "^networkpolicies"; then
echo "WARNING: networking.k8s.io/v1 NetworkPolicy API not available."
echo "This usually means no NetworkPolicy-capable CNI is installed."
echo "Namespaces cannot be protected with NetworkPolicy until this is addressed."
else
echo "OK: networking.k8s.io/v1 NetworkPolicy API is available."
fi

# 2) List all namespaces and count NetworkPolicy objects in each
echo
echo "== Per-namespace NetworkPolicy counts =="
echo "NAMESPACE,NETWORKPOLICY_COUNT"

kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
| while read -r ns; do
count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l | tr -d ' ')
echo "${ns},${count}"
done

# 3) Highlight namespaces with zero NetworkPolicies
echo
echo "== Namespaces with ZERO NetworkPolicies (attention required) =="
zero_ns_found=false
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
| while read -r ns; do
count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l | tr -d ' ')
if [ "$count" -eq 0 ]; then
zero_ns_found=true
echo "$ns"
fi
done

echo
echo "== Detail: NetworkPolicies per namespace =="
kubectl get networkpolicy --all-namespaces

cat <<'EOF'

How to interpret this output
----------------------------
1) "NetworkPolicy API not available" warning:
- Indicates the cluster is likely using a CNI (such as plain flannel) that
does NOT enforce NetworkPolicy. In this case, adding NetworkPolicy
objects will NOT provide isolation until a NetworkPolicy-capable CNI
(e.g., Calico with flannel) is installed and configured.

2) Per-namespace counts:
- Any namespace listed with NETWORKPOLICY_COUNT=0 has no NetworkPolicy
objects defined. Those namespaces allow unrestricted pod-to-pod traffic
(subject only to node/network-level controls), which is the condition
this CIS control flags.

3) "Namespaces with ZERO NetworkPolicies":
- This is the primary problem list. Each namespace shown here needs a
design decision:
* either define one or more NetworkPolicy objects to restrict traffic,
* or explicitly accept the risk and document the exception.

4) "NetworkPolicies per namespace" detailed list:
- Use this to review existing policies for correctness and coverage. Having
at least one NetworkPolicy in a namespace does not guarantee that all
traffic is restricted; it only indicates that some policy exists and the
namespace is not fully open by default.
EOF