Compliance as Code — automated compliance checks

Manual compliance checks consume weeks, and the quarterly audit still catches you off guard. We automate compliance as code: checks live in the pipeline and trigger on every change. This reduces audit preparation from weeks to hours and leaves evidence in the repository.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1359
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1113

Why compliance as code breaks on manual checks

Manual compliance checks rest on two supports: a requirements table and the memory of the engineer who knows "how it should be done". While there are two environments and a dozen rules, this works.

Beyond that, the table diverges from reality, because it is updated separately from the configurations, and no one verifies the actual state — the rule was changed, the environment was left untouched, and the divergence made it into a release.

Configuration drift accumulates unnoticed and quite legally: someone opened access for debugging and forgot to close it, someone disabled a check on the staging environment, someone granted a role with broad permissions "temporarily".

Formally it is the same environment, in practice it is a set of exceptions known only to the authors of the edits.

This usually surfaces during audit preparation, when compliance evidence starts being collected retroactively: exports, screenshots, emails saying "please confirm that it was exactly like this".

As the review date approaches, the crunch begins.

Engineers spend a week reconstructing the history of changes, and some of the evidence can no longer be recovered: logs are not retained for the required period, edits are not signed, the person responsible for the area has changed.

The auditor sees not a working process but a one-off campaign, and their next question is predictable — how do you confirm compliance between reviews.

In such a scheme, a deviation is discovered after release: the configuration diverged from policy, the manual check missed it, and the release went to production.

Let's break down how this gets closed — by moving rules into versioned descriptions that are checked automatically on every change.

What changes: pipeline checks instead of quarterly audits

Compliance rules are described declaratively — as a set of verifiable conditions in the repository next to the infrastructure configuration. After that, every change passes them automatically: before it is applied, not after.

Manual approval remains only where a human decision is needed, rather than a comparison of formal attributes.

Speed of change delivery

Control during change delivery stops being a separate stage. The check runs on every change and responds within seconds to minutes, rather than days of waiting for an approval window.

The share of deviations found before release grows multiple times over — typical violations are caught at the check stage, not in the production environment. Engineers stop keeping a checklist in their heads: it is executed identically for everyone.

The reduction in manual operations here is measurable: configuration comparison, evidence collection, and correspondence with the reviewer go into an automatic run. The freed-up time goes into changes, not into confirming that they are safe.

Time to prepare reporting

The results of every check are stored as an artifact with a timestamp and the version of the change. The report is assembled from these records in minutes, not weeks of sifting through tables.

The question "who changed the rule and when" is closed by the repository history, not by polling the team.

In effect, this moves compliance from a mode of quarterly campaigns into a continuous background. A deviation is visible the moment it appears, not three months later — and the cost of fixing it differs by an order of magnitude.

Compliance standards: what is checked automatically and what is not

Automated control covers compliance requirements that are confirmed by machine-readable attributes: the state of a system or an event over a period.

Anything that depends on the interpretation of a requirement or on the actual way work is done will not be seen by a code-based check — it will either miss a violation or flag it as false.

That is why any comparison of control approaches starts with the question of what exactly confirms the requirement.

Boundaries of automation

Control option When it fits Limitations
Declarative policies for configuration Infrastructure and services are described as code Sees only what is described; changes made outside the code remain out of scope
Continuous evidence collection from systems You need evidence for a period, not a snapshot at a date Depends on the completeness of logs; cannot distinguish a formal event from a violation
Artifact and vulnerability scanning Builds run regularly, the composition of components changes Many findings; prioritization stays manual
Scheduled regulatory checks You need baseline control without reworking processes Changes remain unnoticed between runs

The density of checks grows: control runs on every change, not once per period. Coverage, however, does not expand — anything that is not expressed in a machine-readable way remains outside the boundary of automation.

What stays with humans

The process owner retains the interpretation of the requirement: a single provision can be covered by different measures, and choosing the measure is not a technical decision.

Manual audit verifies what is not confirmed by the state of a system: interviews with the people responsible, whether the actual way of working matches what is described, and the justification of exceptions.

This separation is needed so that the machine covers the routine and does not create the feeling of full coverage; then manual audit is planned in advance, as part of control, rather than as emergency evidence gathering.

How we implement checks: from inventory to handover

We structure the work so that compliance checks live in the same repository as the infrastructure description: then a rule goes through review, is versioned, and is rolled back together with changes. Below is the sequence in which checks are implemented.

Inventory and rule description

  1. We build an inventory of the infrastructure: cloud accounts, clusters, databases, storages, external services — with the owner and criticality of each resource. Without this list, any rule hangs in the air.
  2. We convert requirements into machine-readable rules: encryption enabled, port not exposed to the internet, owner labels filled in, backups no older than a day. Each rule references a clause of a regulation or an industry standard.
  3. We connect the checks to the build and deployment pipeline: first a warning in the change request, then a hard block until it is fixed.

Tuning triggers and exceptions

  • We run the rules against the real state: some of the triggers turn out to be false — the cause is incomplete data or inherited resources.
  • We configure exceptions explicitly: a temporary rule with an expiration date and an owner, rather than disabling the check forever.
  • We route the flow of triggers by owner: each resource is assigned a team that receives a notification and a deadline to fix it.
  • We hand over to operations: a rule update procedure, an escalation scheme, and a report on the share of compliant state by snapshot.

What stays in the repository: policies, roles and evidence

Everything that describes requirements and confirms their fulfillment lives in the same repository as the infrastructure code. This is the key property of the approach: compliance checks live next to the changes, not in a separate folder of reports that no one opens.

Access policies and roles

  • Declarative access policies: which services and segments are open to whom, under what conditions, and from which side.
  • Roles and permissions: a description of roles, binding to groups, and the boundaries of authority for service accounts.
  • Network rules and segmentation between environments — development, test, and production.
  • Key lifetimes and the rotation procedure, specified by a rule rather than by a verbal agreement.
  • The exception procedure: who loosens a rule, for how long, what compensates for it, and when the exception is reviewed.

Reports and change history

  • Reports on checks for every change: what was checked, what passed, what was blocked until it was fixed.
  • The history of policy edits: who changed an access rule, when, and for which task.
  • A log of triggered exceptions with review dates and the person responsible for the decision.
  • An export of evidence for the required period — a single set of artifacts instead of manual collection across systems.

Such a set closes the question "how do you confirm this" when an auditor or the security service asks it. The answer is a link to a change in the repository and a report on it, not an email promising to look into it.

Implementation case study: manual reports replaced by pipeline checks

The client ran several dozen services, and the infrastructure and configurations lived in a single repository.

Compliance with requirements was confirmed manually: an engineer went through a checklist, collected exports from access control systems, and put the report into a table.

Preparing a single report took about two business days, and a third of the deviations were discovered already in the production environment — after release.

We moved the checks into the pipeline and connected Open Policy Agent as a single decision point for configurations and manifests. Every change passes a set of rules before merging: storage encryption, owner labels, network access, secret rotation periods.

A violation blocks the build and is returned to the author with the rule and the specific place in the configuration indicated.

What before-and-after measurements showed

Report preparation time dropped from two business days to a few minutes — the export is assembled from the results of the runs, not by hand.

The share of deviations found before release grew from a third to 92%; the remainder are exceptions that the responsible person consciously approves.

The number of manual operations per release fell by roughly six times: the engineer confirms disputed cases rather than checking every item.

The rules are versioned together with the infrastructure, so a check can be replayed on any change and it can be explained why the configuration was considered correct at a specific moment.

Audit stopped being a separate campaign once a quarter — it runs continuously and does not stop the team's work.

What to do if the infrastructure is already deployed and lives manually?

There is no need to change everything at once, and it is usually harmful: while the new environment is not verified, the old one must keep working.

Legacy infrastructure is connected to compliance checks "from the side" — the rules read the actual state but do not switch anything. That is why the first step is not rewriting configurations, but describing what already exists.

The inventory gathers the facts: which nodes and services are running, who the owner is, which access rights are open, and where manual exceptions have been set up.

The result is a description of the current state in the repository next to the configurations: a single point of truth instead of "ask the person who set it up". Systems that are not described as code go into an exception registry with an owner and a review date.

After that, the rules are enabled in monitoring mode: they generate a report and do not block releases. Backward compatibility is preserved — existing pipelines and manual procedures work as before.

Within a few weeks, a list of real divergences by criticality accumulates: you can see what gets closed quickly and what requires reworking.

The phased rollout proceeds by domain, not across the entire environment: first access rights and network boundaries, then encryption, logging, updates. Blocking is enabled only where no violations remain.

Baseline levels are taken from CIS Benchmarks and adapted to your architecture — someone else's requirements, without adjustment, break working services.

Each stage ends with a report: how many rules are connected, which exceptions have been removed, and what remains under observation. This way, compliance is implemented without stopping releases and without a single "big switch".

Doubts and limitations: what matters to understand before starting work

Automated checks remove the manual comparison of configurations, but the method has boundaries: some triggers fall on legitimate configurations, and some requirements are described not by technical attributes but by agreements between people.

That is why, before starting, we fix who owns the rules, how they change, and what counts as evidence during a check.

Below are the questions that engineers and managers most often ask before work begins.

How do you deal with false positives?

We formulate a rule according to the meaning of the requirement, not a formal attribute — we check the resulting state, not the way it was achieved. The first runs go in warning mode: we gather statistics and refine the conditions. A rule that is regularly wrong is rewritten, not disabled.

Can a specific resource be excluded from a rule?

Yes, but an exception is a narrowing of scope with an owner and a review date, not a disabling of the check. It is stored next to the rules, appears in the report, and reminds you of itself. This way exceptions do not turn into accumulated debt that is invisible to reviewers.

Who maintains the rules after launch?

An edit to the configuration and an edit to the rule go in a single change and go through shared approval — otherwise the set of checks quickly diverges from reality. We hand over the repository with templates and instructions for adding checks: the team expands the set itself. Maintenance can be left to us — once a quarter we review the rules for relevance.

Will external reviewers accept such reports?

They do not replace an audit, but they provide an evidence base: a history of runs, statuses, the composition of exceptions, and an export of reports for the required period. Organizational and process requirements are covered separately by the reviewer. In practice, infrastructure reporting stops being manual work before a review.

Let's discuss the task: where to start checks in your infrastructure

A quick assessment comes together when the first conversation makes it clear which environments we are checking, where the rules currently live, and who has the authority to change them.

Without this, the work plan is built on guesswork, and automated checks start getting in the way of releases instead of insuring them. Describe your task — we will discuss it concretely and come back with an estimate and a work plan.

The input data for the assessment, which we clarify during the first meeting:

  • Which environments are in scope: development, test, production, isolated segments — and whether the requirements for them are the same.
  • Who is responsible for the rules: security, the platform team, or product teams for their own services — and who signs off on changes.
  • Where the rules are currently stored: pages of internal documentation, tables, check scripts in repositories, audit checklists — and how much this diverges from the actual state.
  • The requirements of the reviewers: industry standards, internal regulations, obligations to clients and partners.
  • How changes are set up: who ships the infrastructure, whether there are mandatory checks before rollout, and how long approval takes.
  • Access and constraints: where it is acceptable to put checks automatically, and where there is a mode with restrictions on external connections.
  • What incidents have already occurred: excessive permissions, outdated images, open ports, missing encryption — what is found most often during checks.

Based on the conversation, we will suggest which environment to start with and which rules to move into code first.