Skip to content

Repository files navigation

Lab 07: IaC Security Gate for Privileged Infrastructure

Gate self-test: three scanners, bad fails, good passes

Security Gate

An automatic bouncer that rejects a pull request the moment it adds a committed secret, an open security group, or an unencrypted bucket. Plus a self test that proves the bouncer actually works.

Domains AWS, Azure, Linux, security
Built on pre-commit-terraform (Anton Babenko), checkov, trivy, gitleaks
Cost $0 (runs in CI). Runtime ~2 hours
Status Working. Verified with all three scanners: bad rejected by gitleaks, trivy and checkov, good accepted by all three (output in findings/)

Situation

A PAM engineer's instinct is that a credential must never reach the repo in the first place. Anton Babenko's pre-commit-terraform ships hooks for Trivy and Checkov but no secrets scanner. That gap is the value add.

Task

Chain a secrets scanner in front of the config scanners so a leaked credential fails first, and then prove the gate actually blocks what it claims to.

Action

The gate runs gitleaks first (secrets are the highest severity failure and should stop everything else), then the config scanners.

Most "we have a security gate" setups never test the gate. This one ships two fixtures and a self test. tests/bad/main.tf has a committed AWS key, a wide open security group, and an unencrypted bucket, and the gate must reject it. tests/good/main.tf is clean, and the gate must pass it. scripts/gate-selftest.sh fails if bad passes or good fails.

Result

Verified locally: bad fails on 5 checks, good passes with 0. Those numbers came from Checkov, and the self test asserts them on every push.

Two things the build surfaced, both in the history. The good fixture originally failed the gate on a missing description and no encryption. Rather than hide it by narrowing the checks, I fixed the fixture, because a clean example that is not clean teaches the wrong thing. And the repo's own CI would have failed on its own bad fixture. Fixed two ways: the real gate skips the tests folder, and a gitleaks config allowlists the fixture's example key (it is AWS's documented example, not a real credential).

The gate blocks on a curated set (tests/gate-checks.txt), not all 1000 Checkov policies, because demanding zero findings on everything blocks every PR forever on nice to haves. Choosing that line is the judgement a gate expresses, and it is stated out loud here.

Decisions

Chose Over Because
gitleaks first, config scanners second running all scanners in parallel A committed credential is the highest severity failure in the set. It should stop the pipeline before anyone spends time reading Checkov output, and ordering encodes that priority where a parallel run does not.
A curated block list (tests/gate-checks.txt) failing on all ~1000 Checkov policies Demanding zero findings on everything blocks every PR forever on nice-to-haves, and a gate people route around is worse than no gate. Where that line sits is the judgement a gate expresses, so it is written down rather than implied.
Fixed the good fixture narrowed the checks until it passed The clean example failed on a missing description and no encryption. Narrowing the rules would have made the gate pass by teaching the wrong thing.
Allowlist the fixture key in a scoped gitleaks config deleting the bad fixture The repo's own CI failed on its own test data. The fixture has to stay for the self test to mean anything, so the real gate skips tests/ and the example key is allowlisted — it is AWS's documented example, not a credential.
A self test that asserts both directions trusting the badge Most "we have a security gate" setups never test the gate. Asserting only that bad fails would pass a gate that rejects everything.

What I did not build

The scanners are upstream. The gate design, the curated check set, the fixtures, and the self test are mine.

Run it

pre-commit install                 # local hooks, secrets first
bash scripts/gate-selftest.sh      # prove the gate works
pre-commit run --all-files

Needs pre-commit, checkov, and for local hooks Terraform, gitleaks, and trivy.

License

Lab code: MIT (LICENSE). Upstream tools keep their own licenses, credited above.

About

IaC security gate — pre-commit + CI blocking secrets and misconfig before merge

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages