Ensure That All Namespaces Network Policies Defined
More Info:
Use network policies to isolate traffic in your cluster network.
Risk Level
Low
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS AKS
- CIS Critical Security Controls v8
- CMMC 2.0
- CSA Cloud Controls Matrix v4
- DPDPA
- Digital Operational Resilience Act (EU)
- Essential 8
- ISO/IEC 27017
- ISO/IEC 27018
- ISO/IEC 27701
- KSA PDPL
- MAS Technology Risk Management (Singapore)
- MITRE ATT&CK (Cloud)
- NIS2 Directive
- NIST SP 800-171
- NYDFS 23 NYCRR 500
- SWIFT Customer Security Controls Framework
- Sarbanes-Oxley IT General Controls
- UK NCSC Cyber Assessment Framework
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
List namespaces that currently have no NetworkPolicy (run on any machine with kubectl access):
ns_without_np=$(comm -23 \<(kubectl get ns -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | sort) \<(kubectl get networkpolicy --all-namespaces -o jsonpath='{.items[*].metadata.namespace}' | tr ' ' '\n' | sort))printf '%s\n' "$ns_without_np" -
For each namespace without a NetworkPolicy, create a default deny-all policy (run on any machine with kubectl access). Substitute the namespace name in place of
<namespace>:kubectl apply -n <namespace> -f - <<EOFapiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:name: default-deny-allspec:podSelector: {}policyTypes:- Ingress- EgressEOF -
(Optional but recommended) For each affected namespace, list the applied NetworkPolicies to confirm they exist and review their names:
kubectl get networkpolicy -n <namespace> -
(Optional) For each namespace, define additional, more specific NetworkPolicies as needed to explicitly allow required traffic, using separate manifest files or inline
kubectl apply -f -commands, and apply them with:kubectl apply -n <namespace> -f <your-networkpolicy-manifest.yaml> -
(Optional) If you have system or kube-system namespaces where a full default-deny could disrupt cluster operations, review with:
kubectl get nsand decide whether to:
- Keep the default-deny and add explicit allow rules, or
- Replace it with a more permissive NetworkPolicy tailored to that namespace’s needs.
-
Verify that all namespaces now have at least one NetworkPolicy (run on any machine with kubectl access):
ns_without_np=$(comm -23 \<(kubectl get ns -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | sort) \<(kubectl get networkpolicy --all-namespaces -o jsonpath='{.items[*].metadata.namespace}' | tr ' ' '\n' | sort))if [ -z "$ns_without_np" ]; then echo "ALL_NAMESPACES_HAVE_NETWORKPOLICIES"; else echo "MISSING_NETWORKPOLICIES"; printf '%s\n' "$ns_without_np"; fi
Using kubectl
On any machine with kubectl access:
- List namespaces missing NetworkPolicies (same logic as audit, but show them):
ns_without_np=$(comm -23 \
<(kubectl get ns -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | sort) \
<(kubectl get networkpolicy --all-namespaces -o jsonpath='{.items[*].metadata.namespace}' | tr ' ' '\n' | sort))
printf '%s\n' "$ns_without_np"
- For each namespace in
ns_without_np, create a default deny-all NetworkPolicy:
for ns in $ns_without_np; do
kubectl apply -n "$ns" -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
EOF
done
Adjust or add additional NetworkPolicies per namespace as required for your applications to function.
- Verification (run again from any machine with kubectl access):
ns_without_np=$(comm -23 \
<(kubectl get ns -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | sort) \
<(kubectl get networkpolicy --all-namespaces -o jsonpath='{.items[*].metadata.namespace}' | tr ' ' '\n' | sort))
if [ -z "$ns_without_np" ]; then echo "ALL_NAMESPACES_HAVE_NETWORKPOLICIES"; else echo "MISSING_NETWORKPOLICIES: $ns_without_np"; fi
Automation
#!/usr/bin/env bash
set -euo pipefail
# Automation for: CIS AKS 4.4.2 - Ensure that all Namespaces have Network Policies defined
# Runs on: any machine with kubectl access to the cluster
# Requirements: kubectl configured with cluster-admin or equivalent permissions
# Optional: skip system namespaces if desired (set to "true" or "false")
SKIP_SYSTEM_NAMESPACES="${SKIP_SYSTEM_NAMESPACES:-true}"
# Namespaces to always skip (space-separated)
SYSTEM_NAMESPACES="kube-system kube-public kube-node-lease default"
echo "Discovering namespaces without any NetworkPolicy..."
# Build list of namespaces without any NetworkPolicy
ns_without_np=$(comm -23 \
<(kubectl get ns -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | sort) \
<(kubectl get networkpolicy --all-namespaces -o jsonpath='{.items[*].metadata.namespace}' | tr ' ' '\n' | sort))
if [ -z "${ns_without_np}" ]; then
echo "All namespaces already have at least one NetworkPolicy."
else
echo "Namespaces currently without NetworkPolicy:"
echo "${ns_without_np}" | sed 's/^/ - /'
fi
apply_np_to_ns() {
local ns="$1"
echo "Applying default-deny-all NetworkPolicy in namespace: ${ns}"
kubectl apply -n "${ns}" -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
EOF
}
# Apply default-deny-all NetworkPolicy to each namespace lacking any policy
for ns in ${ns_without_np:-}; do
if [ "${SKIP_SYSTEM_NAMESPACES}" = "true" ]; then
for sys_ns in ${SYSTEM_NAMESPACES}; do
if [ "${ns}" = "${sys_ns}" ]; then
echo "Skipping system/known namespace '${ns}' (SKIP_SYSTEM_NAMESPACES=true)."
continue 2
fi
done
fi
apply_np_to_ns "${ns}"
done
echo "Re-checking namespaces for NetworkPolicies..."
# Verification (same logic as audit, but prints the remaining offenders if any)
verify_missing=$(comm -23 \
<(kubectl get ns -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | sort) \
<(kubectl get networkpolicy --all-namespaces -o jsonpath='{.items[*].metadata.namespace}' | tr ' ' '\n' | sort))
if [ -z "${verify_missing}" ]; then
echo "VERIFICATION PASSED: ALL_NAMESPACES_HAVE_NETWORKPOLICIES"
else
echo "VERIFICATION WARNING: The following namespaces still have no NetworkPolicy:"
echo "${verify_missing}" | sed 's/^/ - /'
echo "If this is intentional, document the exception; otherwise, re-run after fixing permissions/connectivity."
fi