
Hari 37: Network Policies — Default Deny + Whitelist
3 NetworkPolicy: default deny all ingress+egress, whitelist API dari kube-system, DNS egress. k3s flannel enforce! Cross-namespace access blocked, Checkov CKV2_K8S_6 PASS.
Day 32 scan Checkov nemuin CKV2_K8S_6 (no NetworkPolicy) — di-skip karena "dedicated day". Hari ini hari itu. Buat 3 NetworkPolicy: default deny all, whitelist API ingress, allow DNS egress. Dan surprise besar: k3s flannel ternyata enforce NetworkPolicy!
Default Deny + Whitelist Pattern
Pola terbaik untuk NetworkPolicy: mulai dengan block everything, kemudian allow hanya yang dibutuhkan. Lebih aman daripada "allow all + deny specific". Kalau lupa deny sesuatu, tidak ada celah — karena default-nya sudah deny.
3 NetworkPolicy dalam 1 File
1. default-deny-all — block ALL ingress + egress ke semua Pod di namespace securebank:
# Before: no NetworkPolicy — semua Pod bisa saling akses
# After: default deny all
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: securebank
spec:
podSelector: {} # semua Pod
policyTypes:
- Ingress # block incoming
- Egress # block outgoing
podSelector: {} = semua Pod. policyTypes: [Ingress, Egress] = blok kedua arah. Ini baseline — semua traffic diblokir kecuali yang di-whitelist.
2. allow-api-ingress — allow ingress ke API hanya dari kube-system (traefik ingress controller):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-ingress
namespace: securebank
spec:
podSelector:
matchLabels:
app: securebank-api
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: TCP
port: 8080
Hanya Pod di namespace kube-system yang bisa akses port 8080. Pod dari default atau namespace lain = diblokir.
3. allow-dns-egress — allow DNS untuk semua Pod (service discovery butuh DNS):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: securebank
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
DNS (port 53 UDP+TCP) ke semua namespace. Tanpa ini, Pod tidak bisa resolve securebank-api.securebank.svc.
Surprise: k3s Flannel ENFORCE NetworkPolicy
Awalnya expect flannel (k3d default CNI) tidak enforce NetworkPolicy — flannel standalone tidak support enforcement. Tapi ternyata k3s flannel SUPPORT NetworkPolicy. k3s menyertakan NetworkPolicy controller yang bekerja dengan flannel. Test membuktikan: traffic benar-benar diblokir!
Test Results: Before vs After
| Test | Before (no NetworkPolicy) | After (3 policies) |
|---|---|---|
| Cross-namespace (default → securebank) | HTTP 200 (access granted) | HTTP 000 (BLOCKED) |
| Same-namespace (securebank → securebank) | HTTP 200 (access granted) | HTTP 000 (BLOCKED) |
| API pods health | Running 1/1 | Running 1/1 (kubelet bypass) |
| Port-forward access | Works | Works (API Server bypass) |
| Checkov CKV2_K8S_6 | SKIP | PASS |
Cross-namespace access BLOCKED — Pod di default namespace tidak bisa akses API. Same-namespace juga BLOCKED — karena allow-api-ingress hanya whitelist kube-system, bukan securebank sendiri. Design choice: Pod API tidak perlu saling bicara (independent replicas).
Yang Tetap Works
kubelet probes bypass NetworkPolicy. Liveness dan readiness probe diakses kubelet langsung via node, bukan CNI network. Pods tetap Running 1/1 meski default-deny-all.
Port-forward bypass NetworkPolicy. Traffic dari kubectl port-forward masuk melalui API Server (SSH tunnel), bukan CNI network. Berguna untuk debugging tanpa bikin hole di NetworkPolicy.
Checkov: CKV2_K8S_6 SKIP → PASS
# Before (Day 33): 4 skip flags including CKV2_K8S_6
$ checkov -d k8s/ --framework kubernetes --skip-check CKV_K8S_15,CKV_K8S_35,CKV_K8S_43,CKV2_K8S_6
Summary: 85 passed, 0 failed
# After (Day 37): 3 skip flags — CKV2_K8S_6 removed
$ checkov -d k8s/ --framework kubernetes --skip-check CKV_K8S_15,CKV_K8S_35,CKV_K8S_43
Summary: 88 passed, 0 failed
CKV2_K8S_6: PASSED
CKV2_K8S_6 skip dihapus. Sisa 3 skip: imagePullPolicy (local k3d), secret as env (Day 43), image digest (production).
Pelajaran Hari Ini
Default deny + whitelist = pola terbaik. Mulai dengan "block everything", kemudian allow hanya yang dibutuhkan. Kalau lupa deny sesuatu, tidak ada celah — default-nya sudah deny.
k3s flannel SUPPORT NetworkPolicy. Berbeda dari flannel standalone. k3s menyertakan NetworkPolicy controller. Test membuktikan traffic benar-benar diblokir, bukan hanya object ada di cluster.
kubelet probes bypass NetworkPolicy. Pods tetap healthy meski default-deny-all. Probe diakses kubelet via node, bukan CNI network.
NetworkPolicy = namespace-scoped. Policy di securebank hanya memfilter Pod di namespace tersebut. Tapi ingress dari namespace lain bisa diblokir dengan namespaceSelector.
Repo
Semua code dan dokumentasi ada di: https://github.com/stayrelevantid/chalange-devsecops
Kesimpulan
3 NetworkPolicy berhasil di-apply dan di-enforce. Default deny all + whitelist API ingress dari kube-system + DNS egress. Cross-namespace access blocked, same-namespace blocked, API pods tetap healthy. Checkov CKV2_K8S_6: SKIP → PASS (88/0). Surprise: k3s flannel enforce NetworkPolicy. Besok Day 38 — RBAC Auditing, dedicated ServiceAccount with least privilege.
Diskusi & Komentar
Artikel Terkait
Hari 20: Terraform + Checkov, 15 Celah IaC Ketahuan
Bikin infrastructure as code pakai Terraform, lalu scan dengan Checkov. Hasilnya 15 celah keamanan ketahuan — S3 tanpa enkripsi, security group terbuka ke dunia.
Hari 22: Pipeline IaC, Dua Scanner Barengan Gagal
Bikin workflow GitHub Actions khusus infrastructure security. Checkov dan Trivy IaC scan Terraform barengan. Hasilnya pipeline MERAH — security gate bekerja!
Hari 22 Bonus: Perbaikan Pipeline Gitleaks yang Merah Diam-diam
Pipeline Gitleaks merah sejak Day 14 karena flag --no-gitignore tidak pernah ada. Gitleaks detect scan git history, bukan working directory. Fix: hapus flag.