Cloventa Blog
26.08.2026
What "Compliance as Code" actually means (with a working example)
"Compliance as Code" gets thrown around a lot, usually as a slide bullet next to "AI-powered" and "cloud-native," and usually without anyone showing what it actually looks like end to end. I'd rather just show it.
The core idea isn't complicated: instead of a compliance requirement living only as a sentence in a PDF that a human interprets once a year, you express it as something a machine can evaluate — repeatedly, automatically, against the real state of your infrastructure. The hard part was never the idea. It's doing the translation correctly, and keeping it correct as everything around it changes. Let's walk through a real one.

Starting point: a sentence in a framework

Take a requirement that shows up, in some form, in nearly every security framework:
"Production data at rest must be encrypted."
That's a perfectly reasonable sentence for a human auditor. It's useless to a computer as written — "production," "data at rest," and "encrypted" are all doing unstated interpretive work. Turning this into something checkable means making a series of concrete decisions:
  • What counts as "production"? A tag? An account boundary? A naming convention?
  • What counts as "data at rest" in your specific stack — object storage, block storage, database volumes, all three?
  • What counts as "encrypted" — encryption enabled at all, a specific algorithm, customer-managed keys versus provider-managed keys?
None of those decisions are in the original sentence. They're judgment calls someone has to make explicitly, write down, and be willing to defend — because a bad decision here means the "compliant" checkmark is confidently wrong.

Turning it into a rule

Once those decisions are made, the rule itself is almost anticlimactically simple:
safeguard: storage-encryption-at-rest
applies_to:
resource_type: object_storage
scope: tag:environment=production
check:
operation: get_encryption_configuration
pass_if: encryption_enabled == true
metric: encryption_status
evidence:
capture: [resource_id, encryption_status, checked_at]

And the evaluation logic behind it is just as unglamorous:
def evaluate_storage_encryption(resources):
results = []
for bucket in resources.filter(tag="environment:production"):
status = bucket.get_encryption_configuration()
results.append({
"resource_id": bucket.id,
"compliant": status.encryption_enabled,
"checked_at": now(),
})
return results
Run this against your real cloud environment, on a schedule (or in response to a change event), and you get something categorically different from a manual annual check: a continuously current answer to "is this actually true right now," with a timestamped record of when it was last verified. That record — not a screenshot someone took in March — is the evidence.

A harder example: the same idea with dependencies

Encryption-at-rest is a clean example because it's close to binary. Most real controls aren't. Take:
"MFA must be enabled for all privileged users."
This looks similarly simple until you ask: what's a "privileged user"? That's not a property of an individual account — it depends on role assignments, group memberships, and possibly resources the account can reach, which means this check has a dependency on another check (or another data source) just to define its own scope:
def evaluate_privileged_mfa(identity_provider):
results = []
privileged_users = identity_provider.get_users_with_roles(
roles=PRIVILEGED_ROLE_DEFINITIONS
)
for user in privileged_users:
results.append({
"user_id": user.id,
"role": user.highest_privilege_role,
"compliant": user.mfa_enabled,
"checked_at": now(),
})
return results
PRIVILEGED_ROLE_DEFINITIONS is itself a judgment call that has to be documented and kept current — and it's exactly the kind of decision where an over-broad or under-broad definition silently makes your compliance posture look better or worse than it actually is. This is the unglamorous, unavoidable part of the work: the code is trivial, the specification is where the real engineering effort goes, and it never fully stops needing attention, because roles change, org structures change, and cloud providers periodically redefine what "privileged" even means in their own IAM model.

Mapping the check to the regulation

A passing or failing check, on its own, isn't yet "compliance" — it needs to connect to whatever framework someone is actually being evaluated against. The same technical check often satisfies several regulatory requirements simultaneously, because most frameworks are really describing the same underlying security properties in different words:
safeguard: privileged-mfa-enforcement
maps_to:
- framework: ISO27001
control: A.8.5 (secure authentication)
- framework: SOC2
criterion: CC6.1
- framework: NIS2
article: "Art.21(2)(h) — basic cyber hygiene and access control"
This is the part that makes cross-framework reporting possible without duplicating assessment logic per regulation — evaluate the underlying technical reality once, then project it through however many regulatory lenses actually apply to you. It's also the part most likely to be wrong if done carelessly, because the mapping from "what the check verifies" to "what the regulation requires" is an interpretive act, same as the original translation from English sentence to YAML rule. Bad mappings don't fail loudly. They just quietly overstate or understate what you can actually claim, which is arguably worse than no mapping at all.

The part nobody puts on the slide

Here's what tends to get skipped when "Compliance as Code" shows up as a buzzword rather than a real system:
Specs drift, and drift is invisible until you check for it. A cloud provider changes an API. A framework gets a revision. Someone's internal definition of "privileged" needs updating after an org restructure. None of this announces itself — the rule keeps running, keeps returning results, and those results just quietly stop meaning what they used to mean unless something is actively watching for that.
Every rule change needs to be tested against known-good and known-bad cases before it goes live, the same way you'd never ship application code without tests. A rule that's supposed to catch unencrypted storage but has a typo in its filter logic will confidently report "all clear" while checking nothing. The failure mode of a bad compliance check isn't a crash — it's false confidence, which is much harder to notice and much more dangerous.
Not everything can be code, and pretending otherwise is worse than admitting the limit. "Management demonstrates commitment to information security" is a real requirement in most frameworks, and no amount of engineering cleverness turns it into a query against infrastructure state. Some things genuinely need a human attestation, reviewed by a second human, with an expiry date forcing periodic re-confirmation — because a self-reported "yes" from one person, never revisited, is exactly the kind of stale-checkmark problem this whole approach exists to avoid. The discipline is in being honest about which safeguards belong in that bucket instead of quietly forcing everything into automation and hoping nobody checks too closely.

Why this is worth the effort

None of this is easier than the automation-and-evidence-collection model most compliance tools are built around. It's slower to build, narrower in initial coverage, and requires real ongoing maintenance rather than a one-time integration.
What you get in exchange is a compliance posture that's actually current — a system where "compliant" means "we checked, recently, against the real infrastructure," not "someone attested to this once and nobody's looked since." Given what continuous deployment does to the shelf life of any point-in-time compliance snapshot, that trade genuinely seems worth making. But it only works if the specs are taken as seriously as the code — tested, versioned, reviewed for drift — because a compliance check nobody's validating is just a more convincing-looking version of the same stale checkmark this whole approach was supposed to replace.
Made on
Tilda