What is module version pinning?
Module version pinning means declaring which release of a Terraform module a configuration should run, either through one exact version number or a bounded range; only an exact version determines what terraform init installs.
How it works
A registry module accepts a version argument that holds a constraint:
| Constraint | Matches | Use |
|---|---|---|
"5.0.0" | Only 5.0.0 | Strict reproducibility, for instance production |
"~> 5.0" | 5.0 plus any later 5.x release | Patch and minor updates inside one major version |
">= 5.0, < 6.0" | The same range spelled out | Stated upper and lower bounds |
">= 5.0" | Every newer release, even future majors | Avoid: the next init -upgrade may pull in a breaking release |
A range caps how far an update may travel, yet a clean install or init -upgrade can still select a newer release within it. The dependency lock file, .terraform.lock.hcl, tracks provider versions alone; modules are not locked there, so the version argument serves as the actual module pin.
Why it matters for compliance
Pinning gives an auditor a fixed reference that can be traced from Git history to the exact code that executed. Changes also stay reviewable: when a module moves to a new version, any new behavior it carries shows up in a pull request rather than surfacing during an unrelated init.
How compliance.tf applies it
- Sources with a registry address take constraints like
~> 5.0. HTTPS sources rely on?version=; omit it and the newest version gets served, so always pin it. - Version numbers in compliance.tf mirror the upstream terraform-aws-modules numbering. Listings may also include versions carrying a build suffix, for instance
5.1.0-98ddc498fa. Terraform reads anything after a hyphen as a pre-release, and range constraints like~> 5.0skip pre-releases, so pick one through an exact version. - Once published, versions never change. With a framework endpoint, controls ship versioned alongside the module, meaning an exact pin locks the controls too. With an organization endpoint, controls and rules also reflect the organization's published configuration, which sits outside the version number.
- For organization endpoints, any shift in the organization's posture lands in a workspace the next time the module is downloaded fresh. Running
terraform init -upgradepulls it in. - ctfkit flags version constraints that have no upper bound.