Traditional compliance is periodic and manual: an auditor asks for evidence, a team spends three weeks assembling screenshots and spreadsheets, and everyone learns whether a control was working last quarter. Compliance as code transforms that into a continuous property of the system, with evidence produced automatically as a by-product of normal operation.

From control statement to executable check

Every control in a framework is a statement about how the system should behave. Most of them can be expressed as an assertion that a machine can evaluate.

Control statementExecutable formEvidence produced
“Data at rest is encrypted”Query every storage resource for encryption configurationTimestamped, signed inventory with per-resource status
“Access is reviewed periodically”Compare granted permissions against the approved entitlement sourceDiff report plus revocation records
“Changes are reviewed before production”Every production deployment traces to a merged, approved pull requestChange record linked to commit, reviewer, and pipeline run
“Systems are patched within N days”Compare deployed component versions against advisory datesAge distribution of outstanding vulnerabilities
“Backups are tested”Automated restore drill with verificationRestore log with integrity check results
“Least privilege is enforced”Compare granted against used permissions over a windowOver-permission report per identity
“Logs are retained for N days”Verify retention configuration and sample availabilityConfiguration snapshot plus retrieval proof

Not every control automates — physical security and training records do not. But in a cloud-native estate, the large majority of technical controls do, and the remainder shrink to a manageable manual set.

The continuous compliance loop

flowchart TD
    A[Control catalogue<br/>frameworks mapped to internal controls] --> B[Each control implemented<br/>as an automated check]
    B --> C[Checks run continuously<br/>against the live estate]
    C --> D[(Evidence store<br/>timestamped, immutable)]
    D --> E[Compliance dashboard<br/>current posture per control]
    C --> F{Check fails?}
    F -->|Yes| G[Ticket routed to the owning team<br/>with the specific finding]
    G --> H[Remediation]
    H --> C
    D --> I[Audit request:<br/>export evidence for a period]

Two properties make this materially better than the periodic model. Drift is caught in hours, not at the next audit — which is the actual security benefit, independent of any auditor. And evidence is contemporaneous: it records that the control was working continuously, which is a stronger claim than a snapshot taken on the day the auditor visited.

Designing the evidence store

Evidence is only useful if an auditor accepts it. That imposes requirements the engineering instinct tends to skip:

  • Immutable and timestamped. Write-once storage, or at minimum version-locked with access logging. Evidence that could have been edited is not evidence.
  • Attributable. Which check produced it, running as what identity, against which resources.
  • Complete for the period. Gaps are the first thing an auditor asks about. A missing week reads as “the control was off”, so the collection job needs its own dead-man’s-switch alert.
  • Exportable in a human-readable form. Auditors do not query your database. A generated report per control per period, with the raw data attached, is the deliverable.
  • Retained for the required period, which is often longer than your default log retention.

Mapping frameworks without duplicating work

Organizations subject to several frameworks discover the controls overlap heavily. Encryption at rest appears in almost every one.

flowchart LR
    subgraph "Internal controls — implemented once"
    C1[Encryption at rest]
    C2[Change approval]
    C3[Access review]
    C4[Vulnerability SLA]
    end
    subgraph "Framework A"
    A1[Control 3.4] --- C1
    A2[Control 8.2] --- C2
    end
    subgraph "Framework B"
    B1[CC6.1] --- C1
    B2[CC8.1] --- C2
    B3[CC6.3] --- C3
    end
    subgraph "Framework C"
    D1[Art. 32] --- C1
    D2[A.9.2.5] --- C3
    end

Implement each internal control once, then maintain a mapping table from framework requirements to internal controls. Adding a new framework becomes a mapping exercise plus a gap analysis, rather than a new implementation programme.

Change management as evidence

The control auditors probe hardest is usually change management: can you show that every production change was authorised, reviewed, and traceable?

In a mature pipeline this is nearly free, because the pipeline already records it:

  Change record CR-2026-08-4471
  Artifact:      payments-api@sha256:9f2c…
  Source:        github.com/example/payments-api, commit abc123def
  Author:        (developer identity)
  Reviewers:     (approver identities), approved 2026-08-19T08:41Z
  Checks passed: unit, integration, SAST, SCA, IaC policy, image scan
  Approval:      release-managers, 2026-08-19T09:02Z
  Deployed:      2026-08-19T09:07Z by pipeline run #8842
  Verification:  canary analysis passed, SLIs within bounds for 30 min
  Rollback:      available — previous artifact sha256:7a1b…
  

Generated automatically from pipeline metadata, this is a stronger change record than any manually maintained ticket, and it costs nothing per change. Teams that maintain a separate change-management ticket alongside a pipeline that already records all of this are paying twice for one control — and the manual record is the less reliable of the two.

Where automation stops

Be explicit about the boundary, because overclaiming damages credibility with auditors:

  • Automation proves configuration, not intent. A check confirms encryption is enabled; it does not confirm the classification decision that said this data needed it.
  • Some controls are inherently human — training, vendor due diligence, physical access, incident communication decisions.
  • Evidence of a check running is not evidence the check is correct. The checks themselves need review, and their test cases are part of the audit scope.

A good programme automates what it can, tracks the manual remainder explicitly as a much shorter list, and is honest about which is which.

Adoption checklist

  • Controls are catalogued internally and mapped to each applicable framework.
  • Each automatable control is implemented as a continuous check.
  • Evidence is immutable, timestamped, attributable, and gap-free.
  • Evidence collection jobs have dead-man’s-switch alerts.
  • Failures generate tickets routed to owning teams, not reports nobody reads.
  • Change records are generated from pipeline metadata, not maintained by hand.
  • Checks have their own tests, and those tests are in audit scope.
  • The manual control remainder is explicitly listed and tracked.

Last updated 19 Aug 2026, 00:00 UTC. history