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 scope | How it is enforced |
|---|---|
| Resources built from compliance.tf modules | The 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 use | The 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 sets | Applied to the module at download; see Rules overview. |
| Out of scope | Where to look instead |
|---|---|
| Changes made in the AWS console, CLI, SDKs or CloudFormation | Post-apply verification (layer 3) and drift detection |
| Hand-written resources when the provider is not in use, and modules compliance.tf does not serve | Pre-apply scans (layer 2), CI checks on module sources |
Resources brought in with terraform import, or moved out of a module with a moved block | Post-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 control | The generated framework pages, which keep enforced and mapped-only apart |
| Organizational, HR, physical, incident-response, vendor and identity controls | Your 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
Layer 1: prevention. The modules and the provider stop a misconfiguration on the path they protect, before the resource exists.
- Artifacts: the module
sourcelines 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 inhard_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
sourcestring 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 = falsein a module call does not override an enforced value. - The provider runs the official
hashicorp/awsprovider unmodified and adds its check before each call to AWS. In its defaultsoft_failmode a violation is a warning, so evidence that relies on the provider should showhard_failin 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
| Artifact | Where it comes from | Keep it |
|---|---|---|
| Module source lines and pinned versions | Your version control | For the life of the audit period |
.terraform/modules/modules.json | Written by terraform init in each run | With the run's artifacts |
| Saved plan JSON | terraform show -json in CI | Encrypted, access-controlled storage: plans contain resource values in plaintext |
| Scan reports (JSON, SARIF) | Your CI pipeline | As agreed with your auditor |
| AWS Config and Audit Manager reports | Your AWS accounts | As agreed with your auditor |
| Platform audit trail | Read back by someone with audit:read | Your 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-enabledA 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).jsonStore 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
movedblocks, 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
Related
- The audit trail: the platform's record of who changed which posture, and when
- Promotion and gates: how a posture and its waivers reach production
- Turn controls on and off: the
?enable=and?disable=parameters - What is Terraform audit evidence?
- Make the case: the governance summary for leadership and vendor due diligence