What is Terraform audit evidence?
Terraform audit evidence means the records that demonstrate Terraform-defined infrastructure satisfied a control requirement, including pinned module sources, plan output, scan reports, pipeline logs and configuration history after deployment.
Three layers of evidence
| Layer | What it shows | Examples |
|---|---|---|
| Prevention | The control sat in the code path | Module source and version in Git, plan output, .terraform/modules/modules.json |
| Pre-apply | The change was verified before release | Checkov or Trivy JSON or SARIF output, commit SHA, pipeline logs |
| Post-apply | The deployed resource matches | AWS Config, AWS Audit Manager, Security Hub, Powerpipe, Prowler |
Post-apply evidence reports what landed in the account, while prevention records the intent and enforcement carried in code.
Evidence over time
A point-in-time audit checks whether a control was in place. A period audit, such as SOC 2 Type II, checks whether it remained in place across the interval. Four records back that up:
- Immutable module versions. With a framework endpoint, one version number always points to identical code; with an organization endpoint, save the config snapshot used for the download too, since that snapshot is not part of the version number.
- Explicit version pins in Git, together with
.terraform/modules/modules.jsonfor every run. - Archived plan JSON for each change. Handle it as sensitive material, since plans may include secrets.
- Repeated scans of the deployed account on a schedule.
How compliance.tf applies it
Each layer gets a record from a different part of compliance.tf:
- Prevention. A module served from a framework endpoint carries the controls for that framework, and the pinned source and version in Git say which. Hand-written
aws_*resources can be checked by the compliance.tf provider for AWS before Terraform calls AWS: by default it warns (soft_fail), and inhard_failmode a violated control fails the plan, naming the control. - Pre-apply. ctfkit by compliance.tf runs the same checks in CI and writes findings as SARIF or JSON next to the commit SHA and pipeline log.
- Exceptions. A control override on a framework endpoint sits in the module source URL, so Git history and
modules.jsonboth show it. On a project environment host an exception is a waiver, approved separately and recorded in the platform audit trail. Either way, the organization still writes down the reason and any compensating control. - Who changed the posture. The platform audit trail records who published, approved and promoted each config snapshot, and when.
Where it ends
- Compliance.tf does not self-attest. Your code, your plans and your AWS account are the evidence.
- Settle with your auditor or assessor which records they will accept for each requirement. Scanner reports and AWS-native records such as AWS Config history can each play a part; acceptance depends on the requirement and on the way those records are maintained.
- Console and CLI changes bypass Terraform, so neither the modules nor the provider see them. Importing an existing resource does not show it met a control before the import, and a resource moved out of a compliance.tf module keeps only what the provider checks, if the provider is in use.
- A version pin does not establish that every deployment went through compliance.tf modules or the provider.
- Operational Rules are standards for operations. Do not describe them to an auditor as regulatory controls.