Skip to content
All posts
COMPLIANCEDEVOPSCLOUD

Compliance as Code: turning ISO 27001 controls into CI checks

· 2 min read

Compliance as Code: turning ISO 27001 controls into CI checks

Most teams treat compliance as a thing that happens to them once a year: a spreadsheet appears, screenshots get collected, and everyone loses a week proving the system was configured the way it was always supposed to be. That ritual is expensive, and worse, it tells you nothing between audits.

The fix isn't more documentation. It's moving the controls that can be machine-checked into the pipeline, where they run on every change and produce evidence as a side effect.

What "as code" actually means here

Not every control is automatable — an access-review policy still needs a human. But a surprising share of an ISO 27001 Annex A control set maps cleanly onto checks you already have the tools for:

  • A.8 (asset / config management) → infrastructure-as-code scanning (tfsec, checkov).
  • A.8.28 (secure coding) → SAST + dependency audit in CI.
  • A.8.24 (cryptography) → policy tests asserting TLS versions, KMS usage, no plaintext secrets.
  • A.5.23 (cloud services) → cloud posture checks (CSPM) gating the merge.

The goal is a one-to-one trace: a control ID, the check that enforces it, and the run that proves it passed.

A control as a pipeline gate

Here's the shape I aim for — a policy check wired to a control, failing the build when the control is violated:

# .github/workflows/compliance.yml
name: compliance
on: [pull_request]
jobs:
  iac-controls:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: A.8 — IaC misconfig scan (control-gated)
        run: checkov -d ./infra --compact --quiet
      - name: A.8.28 — dependency audit
        run: pnpm audit --audit-level high

The win isn't the tool — it's that the control ID lives next to the check. When an auditor asks "show me A.8 is enforced," the answer is a green run on every merge, not a screenshot from March.

The part people get wrong

Compliance-as-code fails when it's bolted on as a blocking gate nobody understands. Two rules keep it from becoming the new paperwork:

  1. Every gate maps to a control, and every control maps to a real risk. If you can't name the risk, delete the check — it's just noise that teaches engineers to ignore red.
  2. Evidence is automatic or it doesn't count. Pipe each run's result to wherever your control register lives. If proving the control still takes manual effort, you've moved the work, not removed it.

Where the humans stay

The point of automating the mechanical controls is to buy attention for the ones that matter — threat modelling, access reviews, supplier risk, incident response. Those are judgement calls, and pretending a linter covers them is how you get a certificate that means nothing.

Done well, the auditor's questions stop being "can you prove it?" and become "why did you decide it that way?" — which is the conversation worth having.