identity-policy-as-code — OPA/Rego IAM Gate over Terraform Plans
What it is
Compliance findings are history; gates are
prevention. Wildcard actions ("actions": ["*"]),
unbounded resources, and bolted-on inline policies survive every review
cycle because reviewers end and permissions stay. This repo makes them
merge-blocking: three fixtures prove the gate in all
directions (vulnerable denied, clean allowed, malformed input denied) on
every push and pull request.
How it works
Same Rego source enforces both the CI gate (offline,
gate.sh) and request-time checks via
service/server.clj (OPA as PDP, this service as PEP) —
one policy, two enforcement points, no drift
possible.
Input contract (normalized Terraform-plan / access-review output):
{
"role_permissions": [ { "role": "...", "actions": ["s3:GetObject"], "resources": ["arn:..."] } ],
"inline_policies": [ { "principal": "...", "attached": false } ]
}
Three rules, no exceptions:
| Rule | Denies |
|---|---|
| wildcard action | "*" in any role’s action list |
| wildcard resource | bare "*" bound to any role |
| inline policy | attached: true on any principal |
Plus missing-section deny: absent role_permissions or
inline_policies is denied, not skipped.
Run locally (1 command)
git clone https://github.com/nurazhardotcom/identity-policy-as-code
cd identity-policy-as-code
./scripts/gate.sh # needs opa on PATH — runs the full gate
gate.sh runs, in order: strict syntax check + format
check + unit tests + fixture gates (vulnerable and malformed inputs must
be denied, clean input must be
allowed). Exit 0 = merge allowed, exit 1 = blocked.
Automated testing:
opa check --strict policy/ # syntax check
opa fmt --fail policy/ # format check (non-zero on drift)
opa test policy/ -v # Rego unit suite (policy/iam_guard_test.rego)
CI
Two jobs on every push/PR: opa-gate
(the script above) and pdpa-secret-scan
(pdpa-sg-clj scans the repo for Singapore PII
and secrets; any finding fails the build).
The bigger story
This is the public slice of a working compliance-automation practice: zero-dependency CLI scanners, deterministic scoring, evidence over assertions. Tooling: pdpa-sg-clj · idira-audit-clj · identity-control-plane.
Labs
When it gets messy — a wildcard pull request meets the gate, loses, and gets fixed:
Lab 1 — feel the deny. Feed the vulnerable fixture
through gate.sh, read the deny reason, then the clean
fixture — confirm allow.
Lab 2 — malformed input. Drop one section from the input JSON, confirm deny (not skip).
Lab 3 — add a denial. Write one new Rego rule (e.g. deny a specific action prefix), add a fixture + test, watch the gate enforce it.