Policy-as-code (OPA/Rego, Checkov custom policies, Kyverno) is how platforms catch misconfigurations mechanically — including, increasingly, the misconfigurations AI assistants generate. The irony is deliberate: AI is also very good at writing the policies, and even better at generating the adversarial test cases that prove a policy actually catches what it claims to.
Tier: Core · Workflow area: CI/CD & release engineering
Rego in particular is a language most engineers touch twice a year; AI assistance plus a strong test discipline turns it from a specialist skill into a routine one.
Skip custom policies when a built-in Checkov/tfsec rule already covers it — search first, write second.
terraform plan JSON or K8s manifests from your repos, both compliant and violating.State the policy in English first, precisely. "S3 buckets must be encrypted" is underspecified: SSE-S3 or KMS-only? Do exceptions exist? What about buckets created via modules? Ambiguity in, unenforceable policy out.
Generate policy plus tests in one prompt — tests are non-negotiable.
Write an OPA/Rego policy for Conftest evaluating terraform plan JSON:
Rule: every aws_s3_bucket must have server-side encryption with a customer
managed KMS key (not AES256/SSE-S3). Exception: buckets tagged
"public-assets" may use SSE-S3.
Also produce:
1. Six test inputs as plan-JSON fragments: KMS-encrypted (pass),
SSE-S3 (fail), no encryption (fail), tagged exception with SSE-S3
(pass), tagged exception unencrypted (fail), bucket created inside a
module (must still be caught).
2. A conftest exec command to run them.
Deny messages must name the offending resource address and say how to fix.
Run the tests and watch them fail correctly.
opa test policy/ -v
conftest test tfplan.json --policy policy/
A policy whose violating cases do not fail is worse than no policy — it produces green checkmarks and false confidence.
Ask for adversarial bypasses — this is the step most teams skip.
Now act as an engineer trying to sneak a non-compliant bucket past this
policy. List 5 realistic bypasses (module indirection, count/for_each,
dynamic values unknown at plan time, aliased providers, resource renamed
via moved block). For each: a plan-JSON fragment, and whether the current
policy catches it. Fix the policy for the ones it misses.
Common real gaps: policies that only match top-level resources and miss module-nested ones; values that are known after apply; conditionally-created resources.
Wire into CI as a distinct, blocking gate — policy gates (unlike AI review, pb-04) are deterministic and have earned blocking status:
- run: terraform plan -out=tfplan && terraform show -json tfplan > tfplan.json
- run: conftest test tfplan.json --policy policy/ --fail-on-warn
Document each policy in-file: the English rule, the exception process, and an owner. Policies without owners become archaeology.
The test suite is the policy's specification. A Rego rule with no failing test cases proves nothing — being able to say why is what distinguishes policy engineering from policy copying.
kyverno test fixtures exactly as above.The policy is itself a gate in the validate→plan→policy→cost chain, so verify it like infrastructure:
opa test green, including all violating cases failing; opa fmt and conftest verify clean.resource_changes[].change.after structure incorrectly. Only opa test against real plan JSON proves the input shape.known after apply. Values unresolved at plan time need explicit handling (warn, or check at apply) — otherwise you get flaky gates and angry teams.Plan JSON contains account IDs, ARNs, and CIDRs. For client estates: generate the policy from the English rule plus synthetic fixtures (never real plan output) using any approved assistant, then test against real plan JSON only inside the client environment. Rego and Conftest are OSS and run air-gapped; local models handle Rego drafting less reliably than large hosted ones, so budget an extra iteration loop offline.