Sign in
Menu
Sign up
Docs
Prove it to your auditor

Audit evidence

This page answers the auditor's question: which AWS settings does compliance.tf enforce, at which point, and how can I check they were in effect across the audit period? It is written for the auditor or assessor reading the evidence, the head of GRC deciding what to rely on, and the platform lead who assembles the package. By the end you will know what each artifact shows, how to produce it, and where its coverage stops.

  • Scope comes first. Compliance.tf enforces controls on resources built from its modules, and its provider checks hand-written aws_* resources before Terraform calls AWS. Changes made outside Terraform are out of scope.
  • Three layers of evidence: prevention (what the modules and the provider enforce), pre-apply verification (scans of the plan), and post-apply verification (AWS-native findings about deployed resources).
  • Exceptions are explicit. On a framework endpoint a disabled control is named in the module source; on a project environment it is a waiver, recorded in the platform's audit trail.
  • Compliance.tf does not self-attest. The verification evidence comes from tools independent of compliance.tf, and whether it satisfies a requirement is the auditor's call.

What the evidence shows

Scope

In scopeHow it is enforced
Resources built from compliance.tf modulesThe module is served with the framework's controls already set in its source, at terraform init. A module consumer cannot override an enforced value.
Hand-written aws_* resources, when the compliance.tf provider for AWS is in useThe provider checks the resource before Terraform calls AWS. In its default soft_fail mode it warns; in hard_fail mode a violated control fails the plan, naming the control and its framework references.
Operational rules your organization setsApplied to the module at download; see Rules overview.
Out of scopeWhere to look instead
Changes made in the AWS console, CLI, SDKs or CloudFormationPost-apply verification (layer 3) and drift detection
Hand-written resources when the provider is not in use, and modules compliance.tf does not servePre-apply scans (layer 2), CI checks on module sources
Resources brought in with terraform import, or moved out of a module with a moved blockPost-apply verification; an import does not show a resource was configured correctly before it was imported
Framework requirements that are mapped but not enforced by any controlThe generated framework pages, which keep enforced and mapped-only apart
Organizational, HR, physical, incident-response, vendor and identity controlsYour own policies and tooling; see What it does not cover

Each in-scope statement is about configuration at plan time on the path it protects. It is not a statement that every resource in an account meets a framework.

The three layers

Three layers of compliance evidence Layer stack: compliance.tf modules prevent violations at terraform plan, IaC scanners such as Checkov and Trivy verify before apply in CI, and AWS Config, Powerpipe and Audit Manager verify after apply; each layer lists its artifacts and trust tier. Later Plan passes Scan passes L1PreventionTrust tier: preventive, enforced before deployModule-level enforcement at terraform planArtifacts: module source · plan output · registry URL L2Pre-apply verificationTrust tier: supporting evidenceIaC scanning (Checkov, Trivy) · CI gate before deploymentArtifacts: CI scan reports (SARIF/JSON) · commit SHA L3Post-apply verificationTrust tier: primary evidence (AWS-native)Infra scan: AWS Config · Powerpipe · Audit ManagerArtifacts: AWS Config findings · Powerpipe reports LegendWhere compliance.tf actsVerification layers

Layer 1: prevention. The modules and the provider stop a misconfiguration on the path they protect, before the resource exists.

  • Artifacts: the module source lines in version control, naming the framework endpoint and the pinned version; .terraform/modules/modules.json, which records each module's full source URL at init time; saved plan JSON showing the enforced values; provider output when it runs in hard_fail.
  • What it supports: "Infrastructure changes built through these modules are configured with the framework's controls at plan time, and the provider checks the hand-written resources it covers."

Layer 2: pre-apply verification. Static analysis of the plan before terraform apply, with tools such as Checkov and Trivy, or ctfkit by compliance.tf (preview).

  • Artifacts: dated scan reports per pipeline run in JSON or SARIF, the commit SHA they ran against, and the pipeline log.
  • What it supports: "Every infrastructure change is scanned in CI before deployment, and a failed scan blocks the merge or the apply." That holds only if your pipeline is configured to block.

Layer 3: post-apply verification. Evaluation of the deployed AWS resources, with AWS Config, AWS Audit Manager, AWS Security Hub, Powerpipe or Prowler.

  • Artifacts: AWS Config compliance summaries, Audit Manager assessment reports, dated scan outputs.
  • What it supports: "Here are the results of scheduled scans of the deployed resources for the period, with the findings and how each was handled." This layer also sees resources the first two never touched.

The governance record

When an organization serves its modules from its own host, another question applies: who decided which posture each environment receives? The platform's audit trail records each publish, approval, promotion, rollback, and waiver decision, with the person and the time. The modules show what your infrastructure enforced; the audit trail shows who decided it should.

How it is produced

  • Controls live in the module source. They can be read in the downloaded module under .terraform/modules/, and they do not depend on a separate policy engine running at apply time.
  • On a framework endpoint, a pinned version selects a fixed set of controls. The same source string and the same pinned version are built with the same enforced controls. Your organization's operational rules also apply there, and a rule edit changes the downloaded module without changing its version; see Rulesets in the console. On your organization's own host the version does not identify the posture at all: the snapshot bound to the environment decides it, and the audit trail records which snapshot was bound when.
  • Consumers cannot switch a control off from an input. Setting versioning = false in a module call does not override an enforced value.
  • The provider runs the official hashicorp/aws provider unmodified and adds its check before each call to AWS. In its default soft_fail mode a violation is a warning, so evidence that relies on the provider should show hard_fail in use.

How exceptions are recorded

There are two paths. An auditor should expect to see whichever one your organization uses.

On a framework endpoint (soc2.compliance.tf and the others), a control is turned off by naming it in the module source:

module "s3_bucket" {
  source = "https://soc2.compliance.tf/terraform-aws-modules/s3-bucket/aws?version=5.0.0&disable=s3_bucket_object_lock_enabled"
}

The disabled control, s3_bucket_object_lock_enabled, is visible in the Terraform source with its commit history and in .terraform/modules/modules.json. That gives you the what, who and when; the business justification, compensating controls and approval record are yours to keep. How the parameters work is on Turn controls on and off.

On your organization's own host (<alias>.compliance.tf), ?disable= is refused with a 400 on both address forms, the project environment (<alias>.compliance.tf/<project>/<env>/<module>) and the organization's own module path, so no parameter in a source line can subtract from the posture. Pointing a source at another host is a code change your review and CI checks on module sources should catch. On a project environment, an exception is a waiver: proposed and approved as separate acts by people with the approver capability, carrying a stated expiry and a justification, and frozen into the environment's binding when a snapshot is promoted. The decisions are recorded in the audit trail. A permanent change goes into the config itself and reaches the environment as a new, approved snapshot. See Waivers.

Separation of duties between the person who publishes a posture and the person who approves or promotes it is off by default and enabled with our help; until then it holds by role assignment rather than by refusal. See Access control.

Retrieve or export it

ArtifactWhere it comes fromKeep it
Module source lines and pinned versionsYour version controlFor the life of the audit period
.terraform/modules/modules.jsonWritten by terraform init in each runWith the run's artifacts
Saved plan JSONterraform show -json in CIEncrypted, access-controlled storage: plans contain resource values in plaintext
Scan reports (JSON, SARIF)Your CI pipelineAs agreed with your auditor
AWS Config and Audit Manager reportsYour AWS accountsAs agreed with your auditor
Platform audit trailRead back by someone with audit:readYour own copy beyond the platform's retention window

Saving the plan and the scan reports from each pipeline run is covered once, for every CI platform, in Audit artifacts from CI. Retrieving the audit trail is on The audit trail.

For layer 3, AWS Config needs to be enabled in every region you deploy to, with the managed conformance pack for your framework (AWS publishes operational best practices for SOC 2, PCI DSS and HIPAA). Export the findings for the package:

aws configservice get-compliance-summary-by-config-rule
aws configservice get-compliance-details-by-config-rule \
  --config-rule-name s3-bucket-server-side-encryption-enabled

A Powerpipe run of the AWS Compliance mod produces a dated report per framework:

powerpipe benchmark run aws_compliance.benchmark.soc_2 \
  --output json > evidence/powerpipe-soc2-$(date +%Y-%m-%d).json

Store scheduled results in versioned storage, with S3 Object Lock if your auditor expects immutability.

GRC platforms. Vanta, Drata, Sprinto and similar platforms read your AWS account through their own integrations, and accept scan reports and plan JSON as uploaded evidence. No compliance.tf integration or extra credential is involved; the registry token is unrelated to this flow.

What it does not cover

Compliance.tf is an infrastructure enforcement layer with a bounded scope. These need separate controls, tools, and processes:

  • Organizational controls: policies, procedures, training, governance.
  • HR controls: background checks, onboarding and offboarding.
  • Physical security: AWS covers its data centers under the shared responsibility model; your offices and endpoints are yours.
  • Incident response: detection, triage, communication and recovery. Compliance.tf prevents misconfigurations; it does not monitor for active threats.
  • Vendor management: third-party risk assessments and due diligence.
  • Change management for your infrastructure: approval workflows and change advisory processes outside compliance.tf. The platform's audit trail covers changes to compliance posture only.
  • Identity and access management: SSO, MFA, privileged access, access reviews.
  • Runtime detection: suspicious activity, exfiltration and anomalies need SIEM and runtime monitoring.
  • Changes outside Terraform, imports, and moved blocks, as in the scope table above.

What this is, and is not, as evidence

  • Preventive evidence is a design argument plus a record. The module source and the pinned version show what was configured on the path they protect. They do not show that no resource reached AWS another way; layer 3 is what covers that.
  • Open-source scanner output is usually supporting evidence. Many auditors weight first-party AWS sources (AWS Config, Audit Manager, Security Hub) above Checkov, Trivy or Powerpipe output. AWS's own attestations cover the operation of those services, not your conclusions from them.
  • Continuous operation needs a series of results. For an observation-period audit, pair pinned framework-endpoint sources (or, on an organization's host, the promotion history from the audit trail) with layer 3 scans on a cadence agreed with your auditor, stored with timestamps. Weekly is a common starting point.
  • Nothing here is a compliance conclusion. Compliance.tf does not attest that your environment meets a framework. Whether an artifact satisfies a requirement is the auditor's determination.

Per-framework notes

Which controls compliance.tf enforces for each requirement, and which requirements are mapped but not enforced, is on the generated framework pages. Read the requirement IDs there, not from a copy. The catalog gets updated there first.

SOC 2. The infrastructure evidence above maps mostly to the Common Criteria and the Availability criterion. For Type II, the observation window is agreed with your auditor, commonly 3 to 12 months, and the continuity argument is the pinned sources, or the promotion history on an organization's host, plus the scan series. Waiver and approval records from the audit trail help where your auditor asks how exceptions are authorized. See the SOC 2 framework page.

PCI DSS v4.0. Assessors tend to be stricter about provenance: expect AWS-native reports as primary evidence and scanner output as supporting. Testing procedures are defined per requirement, so map your package to them. Scoping is yours: every Cardholder Data Environment resource must be built on a path compliance.tf protects, or be covered by other controls; CI checks that require compliance.tf module sources, and the provider for hand-written resources, help show that. See the PCI DSS v4.0 framework page.

HIPAA. Compliance.tf addresses technical safeguards in infrastructure configuration only; administrative and physical safeguards are your organization's. Compliance.tf does not process, store or transmit PHI and does not hold a Business Associate Agreement; your BAA is with AWS and the other parties that handle PHI for you. See the HIPAA Security Rule framework page and the HIPAA Omnibus Rule page.

Control mappings for every framework: SOC 2 · PCI DSS v4.0 · HIPAA · All frameworks

On this page

Ask AI about this

Help improve this page