Hari 37: Network Policies — Default Deny + Whitelist
4 min read

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.

devsecops
kubernetes
network policies
zero trust
cluster security
Share

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.

Enjoyed this article? Share it!

Share

Diskusi & Komentar

Artikel Terkait