Ensure All Namespaces Network Policies Defined
More Info:
Use network policies to isolate traffic in your cluster network.
Risk Level
Low
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
List all namespaces and identify those without any NetworkPolicy
- Run on: any machine with kubectl access
kubectl get nskubectl get networkpolicy --all-namespaces- Compare the namespace list to the NetworkPolicy list. Note any namespaces that do not appear in the
kubectl get networkpolicy --all-namespacesoutput; these currently have no NetworkPolicy.
-
Decide which namespaces must be isolated and what traffic is allowed
For each namespace without NetworkPolicies (especially those running workloads, not system namespaces likekube-system), determine:- Which pods/services must be reachable (from where, and on which ports).
- Whether the default stance should be “deny all” then allow only specific flows, or “allow most” with a few specific denials.
Document these decisions per namespace.
-
Create a baseline “default deny” NetworkPolicy where appropriate
- For each application namespace that should not be wide open, start with a default deny-all ingress policy (and optionally egress):
kubectl apply -n <namespace> -f - <<'EOF'apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: default-deny-allspec:podSelector: {}policyTypes:- Ingress- Egressingress: []egress: []EOF- Replace
<namespace>with the target namespace name. - Be aware this immediately blocks traffic not explicitly allowed by other NetworkPolicies in that namespace.
-
Add allow-list NetworkPolicies for required traffic
Based on step 2, add policies that explicitly allow necessary flows. Example patterns (adapt and apply per namespace):- Allow intra-namespace traffic:
kubectl apply -n <namespace> -f - <<'EOF'apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: allow-same-namespacespec:podSelector: {}policyTypes:- Ingressingress:- from:- podSelector: {}EOF
- Allow traffic from a specific namespace:
kubectl apply -n <namespace> -f - <<'EOF'apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: allow-from-namespace-frontendspec:podSelector: {}policyTypes:- Ingressingress:- from:- namespaceSelector:matchLabels:name: frontendEOF
Adjust selectors, ports, and namespaces to match your design.
- Allow intra-namespace traffic:
-
Review impact and refine policies
- Monitor application behavior and logs for connection failures after changes.
- Iterate on NetworkPolicies by further restricting selectors or adding necessary exceptions using updated manifests and:
kubectl apply -f <policy-file.yaml>- Keep policies in version control and update them via your normal deployment process.
-
Verify that all intended namespaces now have NetworkPolicies
- Run on: any machine with kubectl access
kubectl get nskubectl get networkpolicy --all-namespaces- Confirm every namespace that you intended to protect has at least one NetworkPolicy listed.
- For a detailed check on a specific namespace:
kubectl get networkpolicy -n <namespace> -o wide
Using kubectl
# 1) List all namespaces
# Run on: any machine with kubectl access
kubectl get namespaces
Review the list and decide which namespaces are in scope (typically all non-terminated namespaces, including kube-system unless you have a documented exception policy).
# 2) See which namespaces have at least one NetworkPolicy
# Run on: any machine with kubectl access
kubectl get networkpolicies --all-namespaces
If some namespaces from the first command do not appear in the NAMESPACE column here, they currently have no NetworkPolicy defined. Those namespaces are candidates for review and likely indicate a problem, unless you have explicitly decided they should be fully open.
# 3) Quickly identify namespaces with zero NetworkPolicies
# Run on: any machine with kubectl access
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 | xargs)
echo "$ns: $count"
done
Any line showing namespace: 0 indicates that namespace has no NetworkPolicy and therefore all pod-to-pod traffic in and out of that namespace is unrestricted by NetworkPolicy. Each such namespace needs human review to decide whether to introduce NetworkPolicies and, if so, with what rules.
# 4) Inspect NetworkPolicies in a specific namespace
# Replace <namespace> with a name from the previous output
# Run on: any machine with kubectl access
kubectl get networkpolicy -n <namespace> -o wide
# For detailed spec of a particular NetworkPolicy:
kubectl get networkpolicy -n <namespace> <policy-name> -o yaml
Use this to assess whether existing policies are meaningful (e.g., not just a single allow-all policy) and consistent with your isolation objectives. An “allow all ingress and egress” policy does not provide isolation and should be treated as a potential issue during review.
Automation
#!/usr/bin/env bash
# Report namespaces without any NetworkPolicy and pods not selected by any NetworkPolicy
set -euo pipefail
echo "=== Summary of NetworkPolicy coverage by namespace ==="
echo
# List all namespaces and whether they have at least one NetworkPolicy
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' |
while read -r ns; do
np_count=$(kubectl get networkpolicy -n "${ns}" --no-headers 2>/dev/null | wc -l | tr -d ' ')
if [ "${np_count}" -eq 0 ]; then
echo "NAMESPACE: ${ns} -> NO NetworkPolicy DEFINED"
else
echo "NAMESPACE: ${ns} -> ${np_count} NetworkPolicy object(s)"
fi
done
echo
echo "=== Pods not selected by any NetworkPolicy (potentially unrestricted) ==="
echo "(Format: <namespace>/<pod-name>)"
echo
# For each namespace, find pods not matched by any NetworkPolicy podSelector
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' |
while read -r ns; do
# Skip namespaces with no pods to reduce noise
pod_count=$(kubectl get pods -n "${ns}" --no-headers 2>/dev/null | wc -l | tr -d ' ')
if [ "${pod_count}" -eq 0 ]; then
continue
fi
# Collect all NetworkPolicies in this namespace
nps_json=$(kubectl get networkpolicy -n "${ns}" -o json 2>/dev/null || echo "")
if [ -z "${nps_json}" ] || [ "$(echo "${nps_json}" | jq '.items | length')" -eq 0 ]; then
# No NetworkPolicies: all pods are potentially unrestricted
kubectl get pods -n "${ns}" -o jsonpath='{range .items[*]}{"'"${ns}"'/"}{.metadata.name}{"\n"}{end}'
continue
fi
# For each pod, check if any NetworkPolicy podSelector matches it
kubectl get pods -n "${ns}" -o json |
jq -r '.items[] | .metadata.name' |
while read -r pod; do
pod_json=$(kubectl get pod "${pod}" -n "${ns}" -o json)
# Build a label set for jq matching
# (jq will test all NetworkPolicies' podSelector.matchLabels against this pod)
matched=$(
jq \
--argjson pod "${pod_json}" \
'
.items[]
| .spec.podSelector
| .matchLabels // {}
| to_entries as $sel
| ($pod.metadata.labels // {}) as $pl
| if ($sel | length) == 0 then
# Empty podSelector selects all pods
1
else
(all($sel[]; ($pl[.key] // "") == .value)) as $ok
| if $ok then 1 else 0 end
end
' <<< "${nps_json}" | paste -sd+ - | bc
)
# matched>0 means at least one NetworkPolicy selects this pod
if [ "${matched}" -eq 0 ]; then
echo "${ns}/${pod}"
fi
done
done
Run this script on any machine with kubectl access and jq installed.
Problematic output indicates:
- In the summary section: any line containing
-> NO NetworkPolicy DEFINEDshows a namespace with zero NetworkPolicy objects and should be reviewed. - In the second section: any listed
<namespace>/<pod-name>is a pod not selected by any NetworkPolicy in its namespace and is potentially receiving/sending unrestricted traffic; these pods and their namespaces should be reviewed and appropriate NetworkPolicies designed and applied.