Bug Description
v3.0.0 made the KMS protection level configurable for FedRAMP Moderate. The variable was added to
four stages, and a regime-aware default was written — but the default is never used, and the variable
is never supplied.
1. Stage 0 computes the right default and then ignores it.
# fast/stages-aw/0-bootstrap/main.tf:39
kms_protection_level = coalesce(var.kms_protection_level,
var.assured_workloads.regime == "FEDRAMP_MODERATE" ? "SOFTWARE" : "HSM")
local.kms_protection_level is referenced nowhere else in the stage. The keys are built from the
variable directly:
# fast/stages-aw/0-bootstrap/kms.tf:15-20
locals {
version_template = {
algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION"
protection_level = var.kms_protection_level
}
}
At v2.13.0 the same lines read protection_level = "HSM", unconditionally.
2. The variable has no default and no source. 0-bootstrap/variables.tf:228 declares it
nullable = true with no default, so Terraform prompts for it. It does not appear in
terraform.tfvars.sample, and docs/ddg.md never mentions it, so an operator following the
deployment guide has nothing telling them the value exists.
3. Stage 0 does not pass it on, and three more stages require it. outputs.tf exposes a
standalone output "kms_protection_level", but the value is in neither local.tfvars nor
local.tfvars_globals — the two maps that become the .auto.tfvars.json files the later stages
consume. Meanwhile 1-resman/variables.tf:259, 2-networking-a-fedramp/variables.tf:239 and
3-security/variables.tf:192 each declare kms_protection_level with no default and no
tfdoc:variable:source annotation. Each of those stages therefore stops and prompts as well.
The net effect on a documented deployment is four interactive prompts for a variable the guide does
not describe. Pressing Enter supplies "": in Stage 0 the unused coalesce cannot save it, because
kms.tf reads the variable, so "" reaches the key. Supplying null produces the same result the
other way — the organization's logging and GCS keys are created without HSM protection on a
FedRAMP High deployment, which is the case the hardcoded "HSM" used to guarantee.
Environment and Deployment Context
Steps to Reproduce
- Follow
docs/ddg.md to prepare fast/stages-aw/0-bootstrap/terraform.tfvars from terraform.tfvars.sample, with assured_workloads.regime = "FEDRAMP_HIGH".
terraform plan. Terraform prompts: var.kms_protection_level — Enter a value:.
- Press Enter. Inspect the planned
google_kms_crypto_key resources in the log-export project: version_template.protection_level is "", not HSM.
- Continue to Stage 1, Stage 2 and Stage 3. Each prompts for the same variable, because it is in neither
.auto.tfvars.json Stage 0 generates.
Expected Behavior
A FedRAMP High deployment that follows the deployment guide produces HSM-protected keys with no prompt, exactly as it did at v2.13.0. A FedRAMP Moderate deployment gets SOFTWARE from the regime, or from one explicit setting. Downstream stages inherit the value from Stage 0's outputs like every other shared value.
Actual Behavior
Four prompts for an undocumented variable; an empty answer silently degrades the organization's KMS protection level on a FedRAMP High deployment.
Relevant Logs and Errors
var.kms_protection_level
KMS protection level.
Enter a value:
Additional Context
Bug Description
v3.0.0made the KMS protection level configurable for FedRAMP Moderate. The variable was added tofour stages, and a regime-aware default was written — but the default is never used, and the variable
is never supplied.
1. Stage 0 computes the right default and then ignores it.
local.kms_protection_levelis referenced nowhere else in the stage. The keys are built from thevariable directly:
At
v2.13.0the same lines readprotection_level = "HSM", unconditionally.2. The variable has no default and no source.
0-bootstrap/variables.tf:228declares itnullable = truewith nodefault, so Terraform prompts for it. It does not appear interraform.tfvars.sample, anddocs/ddg.mdnever mentions it, so an operator following thedeployment guide has nothing telling them the value exists.
3. Stage 0 does not pass it on, and three more stages require it.
outputs.tfexposes astandalone
output "kms_protection_level", but the value is in neitherlocal.tfvarsnorlocal.tfvars_globals— the two maps that become the.auto.tfvars.jsonfiles the later stagesconsume. Meanwhile
1-resman/variables.tf:259,2-networking-a-fedramp/variables.tf:239and3-security/variables.tf:192each declarekms_protection_levelwith no default and notfdoc:variable:sourceannotation. Each of those stages therefore stops and prompts as well.The net effect on a documented deployment is four interactive prompts for a variable the guide does
not describe. Pressing Enter supplies
"": in Stage 0 the unusedcoalescecannot save it, becausekms.tfreads the variable, so""reaches the key. Supplyingnullproduces the same result theother way — the organization's logging and GCS keys are created without HSM protection on a
FedRAMP High deployment, which is the case the hardcoded
"HSM"used to guarantee.Environment and Deployment Context
main@6d7d08c0(2026-09-09); introduced inv3.0.0(f64ce6cd) by PR Add support for FedRAMP Moderate Assured Workloads deployments #162. Atv2.13.0(8f5b67a6)0-bootstrap/kms.tf:18isprotection_level = "HSM"and no stage declares the variable.Steps to Reproduce
docs/ddg.mdto preparefast/stages-aw/0-bootstrap/terraform.tfvarsfromterraform.tfvars.sample, withassured_workloads.regime = "FEDRAMP_HIGH".terraform plan. Terraform prompts:var.kms_protection_level — Enter a value:.google_kms_crypto_keyresources in the log-export project:version_template.protection_levelis"", notHSM..auto.tfvars.jsonStage 0 generates.Expected Behavior
A FedRAMP High deployment that follows the deployment guide produces HSM-protected keys with no prompt, exactly as it did at
v2.13.0. A FedRAMP Moderate deployment getsSOFTWAREfrom the regime, or from one explicit setting. Downstream stages inherit the value from Stage 0's outputs like every other shared value.Actual Behavior
Four prompts for an undocumented variable; an empty answer silently degrades the organization's KMS protection level on a FedRAMP High deployment.
Relevant Logs and Errors
Additional Context
kms.tfuseslocal.kms_protection_levelinstead ofvar.kms_protection_level, so the regime default applies; (2) addkms_protection_leveltolocal.tfvarsin0-bootstrap/outputs.tfand mark the downstream declarations# tfdoc:variable:source 0-bootstrap; (3) add a commented line toterraform.tfvars.sampleand a row to the DDG variables table.default = nullon the four declarations would remove the prompts on its own, but on its own it would also make the FedRAMP High degradation silent rather than interactive — (1) is the part that matters.ec82b554) made3-securityapply this variable to keys that set noversion_template, which is the fix for [Bug] 3-security: keyring-level version_template is silently discarded — keys without a per-key version_template are created as SOFTWARE, not HSM #107. That change is correct and is not affected by this report; it inherits the same unset value.