Hari 36: OPA Policy Testing — Deny vs Allow
4 min read

Hari 36: OPA Policy Testing — Deny vs Allow

Test Gatekeeper policy: Pod tanpa resources ditolak (4 violations), Pod dengan resources diterima. Surprise: K8s auto-fill requests dari limits sebelum webhook dipanggil.

devsecops
kubernetes
opa gatekeeper
policy testing
admission control
Share

Hari 35 kemarin tulis Rego policy — 4 violation rules, enforcementAction: deny, 0 violations. Tapi apakah policy-nya beneran bekerja? Hari ini test dengan 3 skenario: Pod tanpa resources, Pod dengan full resources, dan Pod dengan partial resources.

Test 1: Pod Tanpa Resources — DENIED

Deploy Pod sederhana tanpa resources block di namespace securebank:

# Before: Pod tanpa resources
apiVersion: v1
kind: Pod
metadata:
  name: test-no-limits
  namespace: securebank
spec:
  containers:
    - name: nginx
      image: nginx:latest
      # NO resources defined
$ kubectl apply -f test-no-limits.yaml
Error from server (Forbidden): error when creating "test-no-limits.yaml":
admission webhook "validation.gatekeeper.sh" denied the request:
[require-resource-limits] Container 'nginx' has no CPU limit
[require-resource-limits] Container 'nginx' has no CPU request
[require-resource-limits] Container 'nginx' has no memory limit
[require-resource-limits] Container 'nginx' has no memory request

DITOLAK. 4 violation messages — sesuai dengan 4 violation rules di Rego policy. Gatekeeper mengevaluasi semua rules dan mengumpulkan semua violations dalam satu response. Developer bisa lihat semua masalah sekaligus, bukan fix satu-satu.

Test 2: Pod Dengan Full Resources — ACCEPTED

Tambahkan resources block lengkap (limits + requests):

# After: Pod dengan full resources
resources:
  requests:
    cpu: 50m
    memory: 64Mi
  limits:
    cpu: 200m
    memory: 128Mi
$ kubectl apply -f test-with-limits.yaml
pod/test-with-limits created  # DITERIMA

Policy pass. Pod dengan full resources diterima tanpa masalah.

Test 3: Pod Dengan Partial Resources — ACCEPTED (Surprise!)

Hanya defini limits, tanpa requests:

resources:
  limits:
    cpu: 200m
    memory: 128Mi
  # NO requests defined — expect DITOLAK?
$ kubectl apply -f test-partial-limits.yaml
pod/test-partial-limits created  # DITERIMA!

Kenapa diterima? Kubernetes otomatis mengisi requests = limits jika requests tidak ditentukan. Setelah Pod dibuat, kubectl get pod -o yaml menunjukkan:

# Before (YAML original):
resources:
  limits:
    cpu: 200m
    memory: 128Mi
  # NO requests

# After (K8s auto-fill):
resources:
  limits:
    cpu: 200m
    memory: 128Mi
  requests:
    cpu: 200m      # K8s auto-fill dari limits
    memory: 128Mi   # K8s auto-fill dari limits

Gatekeeper mengevaluasi admission request dari API Server — dan API Server sudah auto-fill requests sebelum webhook dipanggil. Jadi dari POV Gatekeeper, requests sudah ada. Bukan bug di policy, ini Kubernetes default behavior.

Test Results: Before vs After

# Test Resources Expected Actual Result
1 test-no-limits none DENIED DENIED ✅ Match
2 test-with-limits full (limits + requests) ACCEPTED ACCEPTED ✅ Match
3 test-partial-limits limits only DENIED ACCEPTED ⚠️ K8s auto-fill
4 deployment.yaml full (Day 33) ACCEPTED ACCEPTED ✅ Match

Gatekeeper Evaluation Flow

Test 1: kubectl apply (no resources)
  → API Server → K8s defaulting (nothing to fill) → Gatekeeper webhook
  → 4 violations → DENY ✅

Test 2: kubectl apply (full resources)
  → API Server → K8s defaulting (nothing to fill) → Gatekeeper webhook
  → 0 violations → ALLOW ✅

Test 3: kubectl apply (limits only)
  → API Server → K8s defaulting (auto-fill requests = limits) → Gatekeeper webhook
  → 0 violations (requests already filled) → ALLOW ✅ (surprise but correct)

Pelajaran Hari Ini

Gatekeeper webhook dipanggil SETELAH K8s defaulting. Kubernetes auto-fill requests = limits kalau requests tidak ditentukan. Gatekeeper melihat Pod yang sudah di-default, bukan YAML original. Untuk mencegah auto-fill, perlu ValidatingAdmissionPolicy (K8s 1.30+) yang dipanggil sebelum defaulting.

4 violation messages dalam satu response. Gatekeeper mengumpulkan semua violations dari semua rules, bukan stop di rule pertama. Developer dapat lihat semua masalah sekaligus — lebih efficient.

Testing = discovery. Kalau tidak test skenario partial resources, kita tidak akan tahu K8s auto-fill behavior. Testing membuktikan assumption — dan kadang assumption salah.

Policy enforcement works. Pod tanpa resources = ditolak sebelum masuk cluster. Scanner (Checkov/Trivy) melaporkan, Gatekeeper mencegah.

Repo

Semua code dan dokumentasi ada di: https://github.com/stayrelevantid/chalange-devsecops

Kesimpulan

Gatekeeper policy confirmed working. Pod tanpa resources = ditolak dengan 4 violation messages. Pod dengan resources = diterima. Discovery menarik: K8s auto-fill requests = limits sebelum webhook dipanggil — bukan bug, itu default behavior. Besok Day 37 — Network Policies, default deny all + whitelist traffic.

Enjoyed this article? Share it!

Share

Diskusi & Komentar

Artikel Terkait