Repository navigation
chore(iac/federation): align provider version floors in customer onboarding bundles #55
Description
Problem
INF-08 (LeanerCloud/cloud-commitments-cli#1188, PR LeanerCloud/cloud-commitments-cli#1242) aligned the ~> X provider floors across terraform/modules/** and terraform/environments/** to stop module-local lock files from drifting to provider majors no consuming root ever applies.
The same >= X.0 unbounded floor pattern is present in the per-customer federation bundles under iac/federation/**. Each one will resolve to whichever provider major Terraform sees as newest at the customer's terraform init time, which means two customers onboarding a few months apart end up locked to different provider majors with no version policy on our side.
Per iac/federation/*/terraform/main.tf today:
| Bundle | Provider | Current constraint | Risk |
|---|---|---|---|
aws-cross-account |
hashicorp/aws |
>= 5.0 |
resolves to whatever AWS major is current at customer init time |
aws-target |
hashicorp/aws |
>= 5.0 |
same |
gcp-target |
hashicorp/google |
>= 5.0 |
same for google |
gcp-sa-impersonation |
hashicorp/google |
>= 5.0 |
same for google |
azure-target |
hashicorp/azurerm |
~> 4.0 |
already pinned (intentionally on the 4.x line, distinct from the host-side terraform/environments/azure 3.x line) |
The azure-target ~> 4.0 is fine and intentional — it's the cross-major split the cudly-reservation-role module's >= 3.0 constraint accommodates (LeanerCloud/cloud-commitments-cli#1242).
The AWS and GCP bundles are the ones that need a deliberate floor.
Why this matters
These bundles are run by customers on their own AWS/GCP accounts as part of CUDly onboarding. Each customer brings their own state and lock files. Today:
- A customer onboarding now resolves
>= 5.0AWS to whatever 6.x is current; a customer who onboarded 12 months ago landed on 5.x. - Our docs, support tickets, and reproduction steps cover whichever provider the doc author had locally at the time of writing.
- If a future schema break ships in a provider major, customers on the new major silently get a different plan diff for the same .tf source than customers on the old major.
- Our regression-test stories (e.g. role-parity ARM/TF parity guard, federation smoke tests) cover one provider major at a time.
This is the same drift class INF-08 fixed inside terraform/; we just didn't extend it across the boundary into the customer-facing bundles.
Proposal
Pin each AWS and GCP federation bundle to the same major line our internal modules use, so docs and reproduction stay consistent:
iac/federation/aws-cross-account/terraform/main.tf:aws = "~> 5.0"iac/federation/aws-target/terraform/main.tf:aws = "~> 5.0"iac/federation/gcp-target/terraform/main.tf:google = "~> 5.0"iac/federation/gcp-sa-impersonation/terraform/main.tf:google = "~> 5.0"- Leave
azure-targetat~> 4.0(deliberate cross-major split with the host-side~> 3.0).
Optionally also align the http, random, and azuread sub-providers in those same files (currently a mix of >= 3.4, >= 3.0, ~> 3.8, ~> 2.0) so customers see consistent supply-chain pins.
No committed lock files exist under iac/federation/** today (customers generate their own), so there is no lock churn to manage on our side. Pure source-file change plus a docs note in the README of each bundle.
Acceptance
- AWS and GCP federation bundles use
~> 5.0floors matching the internal modules;azurermleft at~> 4.0. terraform init -backend=false && terraform validateclean in each of the five bundle directories.- README for each bundle mentions the pinned major and how a customer should bump when CUDly migrates the host-side line.
Out of scope
- Migrating the host-side azurerm line from
~> 3.0to~> 4.0— that's a much bigger lift (schema migration across every azurerm consumer interraform/). - Adding any new permissions to the bundles. Pure version-pin alignment.
Discovered during the adversarial review of LeanerCloud/cloud-commitments-cli#1242.
Findings from the 2026-09-02 codebase audit
Added by an automated audit of 3c0f8ac94048a2c36fce5ccddee54e6c4849a5cd (tip of origin/main). Each item below was reported by one reviewer and independently confirmed by a second that did not write it. Full report: docs/audits/codebase-audit-2026-09-02.md.
A13-024 (low)
The table here should gain a row. All five bundles also constrain hashicorp/http as >= 3.4 against locks that pin 3.5.0, so the azure-target row marked "already pinned" is only pinned on azuread and azurerm; its http line drifts like the rest. That makes this a five-bundle change rather than four. Two small corrections to the risk framing while the change is being scoped: the committed locks are at aws 6.40.0 and google 7.27.0, so the constraint floors are two majors behind for google and one for aws, and the exposure needs a customer who unpacks into a directory that already has a lock, runs terraform init -upgrade, or is handed only the .tf files. Audit finding A13-024.
Activity
cristim commentedon Jul 28, 2026
Reviewed commit:
be11bdcb5. Note:origin/mainmoved to3e9660d06during the review; the enumeration below was re-run against3e9660d06, but re-verify against currentmainbefore changing code.Verification result from the 2026-07-28 full IaC review. Two reviewers reached opposite conclusions about whether provider version constraints diverge in this repo, so the constraints were enumerated directly against
origin/mainat3e9660d06(git grep -nE 'version = "' origin/main -- '*.tf'). Verdict below, with the full evidence, so a live finding is not dismissed on a wrong negative.Verdict: divergence is real, in two of three claimed places
1. The
iac/federation/**unbounded floors are confirmed still live. Exactly as this issue describes:iac/federation/aws-cross-account/terraform/main.tf:6hashicorp/aws>= 5.0iac/federation/aws-cross-account/terraform/main.tf:10hashicorp/azurerm>= 3.0iac/federation/aws-cross-account/terraform/main.tf:14hashicorp/http>= 3.4iac/federation/aws-target/terraform/main.tf:6hashicorp/aws>= 5.0iac/federation/aws-target/terraform/main.tf:10hashicorp/http>= 3.4iac/federation/gcp-target/terraform/main.tf:6hashicorp/google>= 5.0iac/federation/gcp-target/terraform/main.tf:10hashicorp/http>= 3.4iac/federation/gcp-sa-impersonation/terraform/main.tf:6hashicorp/google>= 5.0iac/federation/gcp-sa-impersonation/terraform/main.tf:10hashicorp/http>= 3.4iac/federation/azure-target/terraform/main.tf:6hashicorp/azuread~> 3.8iac/federation/azure-target/terraform/main.tf:10hashicorp/azurerm~> 4.0iac/federation/azure-target/terraform/main.tf:14hashicorp/http>= 3.4Note that
http >= 3.4is unbounded in all five bundles, includingazure-target, which this issue lists as "already pinned". The optionalhttpalignment mentioned in the Proposal section is therefore the one item that applies to every bundle without exception, and is worth promoting out of "optionally".2. The
azurerm3.x vs 4.x split is deliberate and documented, and is NOT a divergence. The other reviewer is correct on this specific point.terraform/modules/iam/azure/cudly-reservation-role/main.tf:5-12carries an explicit comment:The consumption is confirmed on both sides (
terraform/environments/azure/ci-cd-permissions/reservation_role.tf:20andiac/federation/azure-target/terraform/main.tf:68-72). Anyone re-raising theazurerm3/4 split as a defect should be pointed here; it is load-bearing.3. A third divergence exists that this issue's scope explicitly excludes. Inside
terraform/environments/aws, two roots pin different AWS provider majors:terraform/environments/aws/main.tf:10:aws ~> 5.0(matching every module underterraform/modules/**)terraform/environments/aws/ci-cd-permissions/main.tf:10:aws ~> 6.0The ci-cd-permissions bootstrap root is the one that provisions the deploy identity's IAM, so it applies IAM resources through a provider major that no other root in the repo has been tested against. This is outside this issue's stated scope (
iac/federation/**) and outside #12's table, so it is not currently tracked anywhere. It is carried in the groupedchore(terraform/envs)medium/low issue from this review, cross-referencing this one.Practical takeaway for this issue
Nothing here changes the proposal. It confirms the four AWS/GCP bundle pins are still needed, confirms leaving
azure-targetat~> 4.0is right, and suggests promoting thehttp >= 3.4alignment from optional to in-scope since it is the only constraint that is unbounded in all five bundles.Related
security(iac): provider version constraints use >= / ~> 5.0) covers the general "pin to a tested range" hygiene argument and overlaps this issue's table partially. Neither covers theterraform/environments/aws~> 6.0vs~> 5.0split.IAmJSD commentedon Oct 23, 2026
Claiming: working on this