Lab: Default Deny and Controlled Traffic Allowlist
Goal
Build namespace isolation in develop:
- deny all ingress/egress by default
- allow DNS egress
- allow ingress only from ingress controller namespace
- validate blocked and allowed traffic paths
Prerequisites
- cluster CNI supports
NetworkPolicy - access to namespace
develop - ingress controller namespace identified (commonly
ingress-nginx)
Quick checks:
kubectl get ns
kubectl api-resources | rg -i networkpolicies
kubectl -n flux-system get kustomization network-policies-develop network-policies-staging network-policies-production
Set namespace variables:
export TARGET_NS=develop
export INGRESS_NS=ingress-nginx
Step 0: Verify GitOps-Applied Baseline Policies
kubectl -n $TARGET_NS get networkpolicy
Expected (from Flux baseline):
default-deny-allallow-dns-egressallow-frontend-egress-backendallow-backend-ingressallow-frontend-ingress
Step 1: Baseline Connectivity Snapshot
kubectl -n $TARGET_NS get pods,svc
kubectl -n $TARGET_NS run np-debug --image=busybox:1.36 --restart=Never -- sleep 3600
kubectl -n $TARGET_NS exec np-debug -- nslookup kubernetes.default.svc.cluster.local
Expected:
- DNS lookup works before deny policy
Step 2: Apply Default Deny
cat <<'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: develop
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
EOF
Validation:
kubectl -n $TARGET_NS get networkpolicy
kubectl -n $TARGET_NS exec np-debug -- nslookup kubernetes.default.svc.cluster.local
Expected:
- DNS now fails (egress blocked)
Step 3: Allow DNS Egress Only
cat <<'EOF' | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: develop
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
EOF
Validation:
kubectl -n $TARGET_NS exec np-debug -- nslookup kubernetes.default.svc.cluster.local
Expected:
- DNS works again
Step 4: Allow Ingress from Ingress Controller
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-from-controller
namespace: ${TARGET_NS}
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ${INGRESS_NS}
EOF
Validation:
kubectl -n $TARGET_NS get networkpolicy
Expected:
- traffic from ingress controller namespace is permitted
- non-allowed namespaces remain blocked
Step 5: Blocked Traffic Debug Drill
- Launch debug pod in another namespace (for example
staging). - Attempt to reach service in
develop. - Confirm request is blocked and document which policy enforces it.
Example:
kubectl -n staging run np-debug-staging --image=busybox:1.36 --restart=Never -- sleep 3600
kubectl -n staging exec np-debug-staging -- wget -qO- --timeout=2 http://backend.develop.svc.cluster.local:8080/version
Rollback
kubectl -n $TARGET_NS delete networkpolicy default-deny-all allow-dns-egress allow-ingress-from-controller
kubectl -n $TARGET_NS delete pod np-debug --ignore-not-found=true
kubectl -n staging delete pod np-debug-staging --ignore-not-found=true
Hard Stop Conditions
- applying deny policy in wrong namespace/environment
- combining app rollout and network policy changes in one PR
- no rollback manifest/commands prepared
Done When
- learner demonstrates
deny -> allow DNS -> allow ingress-controllerflow - learner can reproduce and explain one blocked traffic case
- learner can rollback policies safely