Implementing Compliance Scanning for Infrastructure (InSpec/ServerSpec)

Manual compliance checks lag behind infrastructure changes—control depends on engineers' memory. We implement compliance scanning turnkey: define check profiles, run regular scans, and provide reporting. Configuration drift is detected before it becomes an outage or audit finding.

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

Compliance scanning of infrastructure: where control breaks

Configuration in the repository is described carefully: base images, kernel parameters, storage access rules. In production the picture is different — manual fixes for an incident, ports temporarily opened "for two hours", audit disabled for debugging.

Each such change survives until the node is recreated, but it is exactly what diverges from regulatory requirements, and we learn about it during an external review or after an incident postmortem.

Configuration drift accumulates unnoticed. One node out of a hundred, one cloud account, one credential with excessive privileges — individually a minor thing, together they are a list of audit findings.

Manual infrastructure compliance checks take days, and no one will repeat them before every release.

The problem is also that control is not where changes happen.

While a check lives as a spreadsheet filled in by hand, weeks pass between a change in production and its detection, and rollback to the reference state is done blindly: it is unclear which change was intentional and which was a workaround.

Compliance scanning works only if rules are described declaratively and sit next to the configuration. We break down how this is covered: from requirements translated into testable conditions to a report for each resource that the auditor accepts.

Measurable effects: time, automation share, failure class

Compliance checks stop being a manual sample. The reference configuration description sits in the repository next to the infrastructure code, and InSpec compares the actual state of servers against it and produces a machine-readable report.

Previously such a report was assembled from logs, screenshots, and interviews with service owners — several days before every audit; now it is rebuilt on request in minutes, and it can be compared with the previous run to see exactly what changed.

The share of check automation is the second measurable indicator. After moving rules into code, the typical set is covered without human involvement: a regular run across all nodes, analysis of deviations, and marking remediation.

Only organizational artifacts remain manual — orders, access logs, signatures of responsible persons; their list is fixed and does not grow with the machine fleet. This is the key scaling effect: adding a hundred nodes does not add a single day of work to report preparation.

The third effect is an eliminated class of failures. A discrepancy between actual configuration and the reference (a rule left after an incident postmortem, debug mode enabled, a change made "on the fly") previously surfaced at the moment of an outage.

Now it appears in the report during a scheduled run, before rollout, and is fixed as a routine task.

Downtime is measured not by the fix but by recovery time. When the state is described by a reference rather than reproduced from the on-call engineer's memory, returning to a working configuration takes minutes instead of hours.

In addition, the share of incidents caused by an unplanned change decreases: they are visible in advance.

Compliance check modes: comparison of approaches

The check mode is determined not by the tool, but by how quickly a deviation becomes known.

A single compliance scanning profile is run manually, on a timer, in the background across the machine fleet, or as a blocking step during release — and the cost of an error differs in each case.

Mode How it works When it fits Limitations
One-time audit manual launch of a profile against selected nodes project onboarding, preparation for an external review point-in-time snapshot, later changes are not visible
Scheduled run scheduled jobs, reports in storage regular reporting, stable environments window between runs — a day or more
Continuous control polling nodes with results sent to a central service critical systems, constant status requires collection, storage, and noise triage
Checks in the release pipeline blocking step before rollout everything delivered through the pipeline manual changes in the live environment are out of scope

A one-time audit and a scheduled run provide a point-in-time report and satisfy external review requirements, but between runs the environment goes its own way: a manual configuration change will surface only during the next run.

Continuous control reduces this window to minutes, but it requires result storage and noise suppression rules — otherwise reports stop being read.

Checks in the release pipeline do not measure but prohibit: a non-compliant artifact does not reach the environment, but only the path through the pipeline is covered.

We write InSpec profiles once — only the launch point changes, so results from different modes are comparable and deviation analysis does not have to start over.

How we implement compliance scanning: stages of work

The engineering sequence here matters more than the chosen tool: without clear inventory, even carefully written profiles produce false positives and lose the team's trust.

So we go from facts — what actually exists in the infrastructure — to a regulation that lives in the repository and survives personnel changes.

  1. Audit and inventory. We go through environments, reconcile hosts with inventory systems, mark roles — web, DB, load balancers — and owners. The set of checks depends on this map: a universal list either fails production or misses real deviations.
  2. Check scheme. We decide where and how to run: a local agent on the host, a remote run, or a check of the machine image before rollout. Each option has its own access level, schedule, and execution time tolerances.
  3. Check profile configuration. We describe requirements declaratively: passwords, file permissions, open ports, package composition. Profiles live in the repository and go through review — a rule is changed via merge, not manually on a server, and it is always clear who changed it and when.
  4. Access rights. We create a separate service account only for reading and running checks, and store keys in a secret store. The checker does not get access to production data.
  5. Trial run. We run it on one environment in report mode, without blocking. We analyze false positives, adjust thresholds, and look at the share of covered hosts and run time.
  6. Acceptance and handover. We reconcile reports with the source requirements, verify that critical deviations are reproducible, and fix the regulation. Then we show the team how to add a rule, read a report, and remove a host from checks — with documentation and profile templates.

Check profiles, reports, and operations regulations

A check profile is not a wiki document but an executable specification: rules traverse servers and cloud resources and issue a verdict for each item with the node and reason indicated.

The customer is left with a set of artifacts that works without us and survives a change of contractor.

  • Check profiles as code: requirements for the kernel, services, and configuration parameters are described by executable profiles, stored in version control, and reviewed like ordinary code.
  • Access policies: a matrix of roles and service accounts, checks for excessive privileges, stale keys, and open ports — a discrepancy surfaces at build time, not during an audit.
  • Separation by environment: dedicated rule sets for production, test environments, and isolated segments so that strict checks do not slow down development.
  • Compliance reports: a machine-readable result for the build pipeline and a summary by rules, nodes, and dates for management and external audit.
  • Exceptions with an expiration date: each deviation with a reason, owner, and review date; otherwise the exception list eventually overrides the regulation itself.
  • Response regulation: what is considered critical, who receives a notification and within what timeframe, when rollout is blocked, and when risk is consciously accepted.
  • Operations manual: how to add a new rule, update a profile, run a check manually, and analyze a false positive.
  • Reference deviation map: what has already diverged, on which nodes, and with what priority — the team works with this list from day one.

Case study: how configuration drift was eliminated across a server fleet

Before the project, no one saw the fleet of 140 servers across three environments as a whole: there was no single configuration reference, and the security checklist lived as a document and was checked selectively — 10–15 machines once a quarter, with the rest covered by interviewing the operations team.

The cost of such a scheme is predictable: a configuration deviation was discovered after 3–6 weeks, already after an incident or an audit remark, and some changes were made manually on one server and never reached the others.

We moved checks into code: every checklist item became an executable InSpec check with an unambiguous result, and selective walkthroughs were replaced by continuous compliance scanning.

The reference is described declaratively — the check does not depend on who configured the machine or how: it compares fact with the description and returns discrepancies with the specific parameter indicated.

Runs happen on schedule across the entire fleet and before deploying changes, and results are stored in one place with history — you can see not only the current state but also when a deviation appeared.

After a month of operation, the metrics looked like this: 100% of systems under automated checking instead of a sample of about 10%, configuration drift detection time — 4 hours instead of 3–6 weeks, and no open discrepancies with the checklist by the end of the project.

A separate exception registry was created: 27 justified deviations are documented, substantiated, and have a review date — they are not disguised as the norm and do not resurface at every audit.

The main effect is not a one-time cleanup, but that the state returns to the reference on its own: a new machine joins the fleet already checked, and configuration drift stops accumulating between audits.

How does continuous control differ from a one-time audit?

A penetration test and a checklist audit answer different questions, and confusing them is costly. The first shows whether the system can be broken today: exploitation chains, weak credentials, excessive privileges.

The second confirms that the configuration matched requirements on the audit date. Both provide a snapshot, not the current state.

Each method has its own boundaries of applicability. A penetration test will not notice that someone disabled volume encryption at night or opened a debug port in the test environment — that is not exploitation, but a configuration deviation.

A checklist audit goes by sample and captures a moment: a week after the report, some nodes again fall out of compliance, and no one finds out.

Configuration drift is the reason a six-month-old report guarantees nothing. Nodes are recreated, parameters are edited manually "to make it work", and an image update brings changed default values. Each such change is a potential deviation, and it is invisible between checks.

Continuous control closes exactly this gap. Check profiles are described as code, versioned together with the infrastructure, and run on schedule and in the pipeline: a deviation from the reference is a build failure or a remediation task, not a line in a report six months later.

The methods do not replace each other. A checklist audit is needed for reporting and regulator requirements, a penetration test — for application logic and human error, and continuous control — for the state of the fleet between them.

Combining all three answers both "are we compliant" and "are we compliant right now".

Technical concerns: how checks work in practice

Concerns about compliance scanning are usually the same: what exactly will be in the report, whether production services will be affected, what to do with agentless systems, and who is responsible for keeping rules up to date. Below are direct answers, without generalities.

Inventory is incomplete — does that mean the report will be incomplete too?

Inventory is assembled from several independent sources: configuration management systems, virtual machine catalogs, and network range scanning.

Discrepancies between sources are output as a separate list — a host that exists in one registry and is absent from another is itself a finding. A system that did not respond also appears in the report marked "no data", rather than dissolving into silence.

Can checks harm the production environment?

A check profile only reads the system state and makes no changes — this is built into the rules themselves. Runs happen outside peak windows, with limited concurrency, so as not to consume node resources.

Before a production run, the same set is executed in the test environment: if a rule behaves unstably or produces false positives, it is fixed before going to production.

There are agentless systems — can they not be checked?

They can be checked: connection goes through the standard management channel, and installing additional software is not required. For closed segments, the check runs locally, and the result is transmitted to the common registry.

If a node is fundamentally unreachable, it remains in the report as manually declared — with an explicit data source marker.

Who maintains profiles when requirements change?

Profiles are stored in the repository next to the infrastructure description and versioned together with it. A new requirement is created as a separate rules branch without affecting the rest — the update does not turn into rewriting the entire set.

Once a quarter a review is held: outdated checks are removed, and disputed ones are clarified on the reference environment.

Other objections — about access, rollback, and migration — are covered below.

Let's discuss the task: where implementation begins

At the input, it is enough to describe what exists now: fleet composition — servers, container platforms, cloud accounts — which requirements we cover (an industry standard or an internal regulation), and how checks are performed today. The more specific the input, the fewer assumptions in the assessment.

  • Input analysis — inventory of nodes and requirements; we record which checks are already automated and which rely on manual checklists.
  • Work estimate — how many profiles to describe, the volume of exceptions, labor effort, and timelines by stage; the figures are based on inventory, not on guesswork.
  • Implementation plan — a pilot on one group of systems, debugging profiles on real discrepancies, then rollout to the rest of the fleet.
  • Scope boundaries of the first iteration — the list of controls, node types, report format; what we consciously move to the second wave so as not to stretch out the first result.
  • First iteration — we run InSpec checks on schedule, connect reporting to the continuous integration pipeline, and deliver a discrepancy report with priorities.
  • Handover — documentation on profiles, a regulation for updating them, and training for your team so that support does not constantly depend on us.

Describe the task — we will come back with an estimate, a stage plan, and the boundaries of the first iteration.