Ensure That All Namespaces Have Network Policies Defined
More Info:​
Namespaces without NetworkPolicies allow unrestricted pod-to-pod traffic. Define at least one NetworkPolicy in each namespace to control and restrict traffic.
Risk Level​
High
Address​
Security
Compliance Standards​
- CIS EKS
Triage and Remediation​
- Remediation
Remediation​
Manual Steps
-
List namespaces that currently have no NetworkPolicies (run on any machine with kubectl access):
ns_without_np=$(kubectl get namespaces -o json | jq -r '.items[].metadata.name' | while read ns; docount=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l)if [ "$count" -eq 0 ]; then echo "$ns"; fidone)echo "$ns_without_np" -
For each namespace without a NetworkPolicy, review what should be allowed:
- Ingress: which pods/services (by label, namespace, IPs) may talk to pods in this namespace?
- Egress: which external destinations (namespaces, services, CIDRs, ports) are required? Use these answers to decide labels, ports, and CIDR ranges for your policies.
-
(Optional but recommended) Label workloads in a target namespace so policies can select them. For example, in namespace
example-namespace(run on any machine with kubectl access):kubectl -n example-namespace get pods --no-headers -o custom-columns='NAME:.metadata.name' | while read pod; dokubectl -n example-namespace label pod "$pod" role=app --overwritedone -
Create a default deny-all ingress and egress NetworkPolicy for each selected namespace, adjusting
namespaceand labels as appropriate (run on any machine with kubectl access). Example forexample-namespace:cat << 'EOF' | kubectl apply -f -apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: default-deny-allnamespace: example-namespacespec:podSelector: {} # selects all pods in this namespacepolicyTypes:- Ingress- EgressEOF -
Add specific allow NetworkPolicies where needed so applications continue to function. For example, allow ingress HTTP traffic from same namespace to pods labeled
role=appinexample-namespace(run on any machine with kubectl access):cat << 'EOF' | kubectl apply -f -apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: allow-http-same-namespacenamespace: example-namespacespec:podSelector:matchLabels:role: apppolicyTypes:- Ingressingress:- from:- podSelector: {} # any pod in this namespaceports:- protocol: TCPport: 80EOFRepeat with additional policies for other required ports, sources, or egress as identified in step 2.
-
Verify that every namespace has at least one NetworkPolicy (run on any machine with kubectl access):
ns_without_np=$(kubectl get namespaces -o json | jq -r '.items[].metadata.name' | while read ns; docount=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l)if [ "$count" -eq 0 ]; then echo "$ns"; fidone)if [ -z "$ns_without_np" ]; thenecho "ALL_NAMESPACES_HAVE_NETWORK_POLICIES"elseecho "NAMESPACES_WITHOUT_NETWORK_POLICIES: $ns_without_np"fi
Using kubectl
# 1) Identify namespaces without any NetworkPolicy
# Run on: any machine with kubectl access
ns_without_np=$(kubectl get namespaces -o json | jq -r '.items[].metadata.name' | while read ns; do
count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l)
if [ "$count" -eq 0 ]; then echo "$ns"; fi
done)
echo "$ns_without_np"
# 2) Create a baseline default-deny-all-ingress policy in each namespace that lacks NetworkPolicies
# Adjust/add more specific policies later as needed for your applications.
# Run on: any machine with kubectl access
for ns in $ns_without_np; do
cat <<EOF | kubectl apply -n "$ns" -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: $ns
spec:
podSelector: {}
policyTypes:
- Ingress
EOF
done
# 3) Optional: create a stricter baseline (deny all ingress and egress)
# WARNING: This can break cross-namespace or external connectivity for pods in these namespaces.
# Run on: any machine with kubectl access
for ns in $ns_without_np; do
cat <<EOF | kubectl apply -n "$ns" -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: $ns
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
EOF
done
# 4) Verification: confirm every namespace now has at least one NetworkPolicy
# Run on: any machine with kubectl access
ns_without_np=$(kubectl get namespaces -o json | jq -r '.items[].metadata.name' | while read ns; do
count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l)
if [ "$count" -eq 0 ]; then echo "$ns"; fi
done)
if [ -z "$ns_without_np" ]; then
echo "ALL_NAMESPACES_HAVE_NETWORK_POLICIES"
else
echo "NAMESPACES_WITHOUT_NETWORK_POLICIES: $ns_without_np"
fi
Automation
#!/usr/bin/env bash
set -euo pipefail
# This script:
# - Ensures every namespace has at least one NetworkPolicy
# - Creates a default-deny-all NetworkPolicy in any namespace missing policies
# - Skips kube-system and other core namespaces where you may not want default-deny
# - Is safe to re-run (idempotent)
#
# Run from any machine with kubectl access and a current context pointing at the cluster.
# -------- Configuration --------
# Comma-separated namespaces to SKIP from automatic default-deny policies.
# Adjust as appropriate for your cluster.
SKIP_NAMESPACES="kube-system,kube-public,default,local-path-storage,ingress-nginx"
# Name of the default policy to create (if none exist in a namespace)
DEFAULT_POLICY_NAME="default-deny-all"
# --------------------------------
IFS=',' read -r -a SKIP_ARRAY <<< "$SKIP_NAMESPACES"
ns_in_skip_list() {
local ns="$1"
for s in "${SKIP_ARRAY[@]}"; do
if [[ "$ns" == "$s" ]]; then
return 0
fi
done
return 1
}
echo "Discovering namespaces without any NetworkPolicy..."
ns_without_np=()
# Collect namespaces with zero NetworkPolicies
while read -r ns; do
# Skip terminating namespaces
phase=$(kubectl get ns "$ns" -o jsonpath='{.status.phase}')
if [[ "$phase" != "Active" ]]; then
continue
fi
count=$(kubectl get networkpolicy -n "$ns" --no-headers 2>/dev/null | wc -l | tr -d ' ')
if [[ "$count" -eq 0 ]]; then
ns_without_np+=("$ns")
fi
done < <(kubectl get namespaces -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')
if [[ ${#ns_without_np[@]} -eq 0 ]]; then
echo "All namespaces already have at least one NetworkPolicy."
else
echo "Namespaces with no NetworkPolicy: ${ns_without_np[*]}"
fi
for ns in "${ns_without_np[@]}"; do
if ns_in_skip_list "$ns"; then
echo "Skipping namespace '$ns' (in skip list); please define NetworkPolicies manually if desired."
continue
fi
echo "Creating default-deny-all NetworkPolicy in namespace '$ns'..."
# Apply an idempotent default deny-all policy (ingress and egress)
# Safe to re-run: same name, full manifest.
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ${DEFAULT_POLICY_NAME}
namespace: ${ns}
spec:
podSelector: {} # applies to all pods in this namespace
policyTypes:
- Ingress
- Egress
ingress: [] # deny all ingress
egress: [] # deny all egress
EOF
done
echo
echo "Verifying that all namespaces now have at least one NetworkPolicy..."
verify_ns_without_np=$(kubectl get namespaces -o json | jq -r '.items[].metadata.name' | 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 echo "$ns"; fi
done)
if [ -z "$verify_ns_without_np" ]; then
echo "ALL_NAMESPACES_HAVE_NETWORK_POLICIES"
else
echo "NAMESPACES_WITHOUT_NETWORK_POLICIES (manual review required or skipped by config): $verify_ns_without_np"
echo "Review these namespaces and create appropriate NetworkPolicies as needed."
fi