Skip to content

Commit 5eabf97

Browse files
authored
Merge pull request #37212 from hashicorp/jbardin/sensitive-output
ensure outputs carry sensitive marks forward
2 parents d857f20 + 3c1e163 commit 5eabf97

3 files changed

Lines changed: 74 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: BUG FIXES
2+
body: Nested module outputs could lose sensitivity, even when marked as such in the configuration
3+
time: 2025-06-04T14:40:21.12567-04:00
4+
custom:
5+
Issue: "37212"

internal/terraform/context_plan2_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6847,3 +6847,68 @@ data "test_data_source" "foo" {
68476847

68486848
}
68496849
}
6850+
6851+
func TestContext2Plan_sensitiveOutput(t *testing.T) {
6852+
m := testModuleInline(t, map[string]string{
6853+
"main.tf": `
6854+
module "child" {
6855+
source = "./child"
6856+
}
6857+
6858+
output "is_secret" {
6859+
// not only must the plan store the output as sensitive, it must also be
6860+
// evaluated as such
6861+
value = issensitive(module.child.secret)
6862+
}
6863+
`,
6864+
"./child/main.tf": `
6865+
output "secret" {
6866+
sensitive = true
6867+
value = "test"
6868+
}
6869+
`,
6870+
})
6871+
6872+
ctx := testContext2(t, &ContextOpts{})
6873+
6874+
plan, diags := ctx.Plan(m, states.NewState(), DefaultPlanOpts)
6875+
tfdiags.AssertNoErrors(t, diags)
6876+
6877+
expectedChanges := &plans.Changes{
6878+
Outputs: []*plans.OutputChange{
6879+
{
6880+
Addr: mustAbsOutputValue("module.child.output.secret"),
6881+
Change: plans.Change{
6882+
Action: plans.Create,
6883+
BeforeIdentity: cty.NullVal(cty.DynamicPseudoType),
6884+
AfterIdentity: cty.NullVal(cty.DynamicPseudoType),
6885+
Before: cty.NullVal(cty.DynamicPseudoType),
6886+
After: cty.StringVal("test"),
6887+
},
6888+
Sensitive: true,
6889+
},
6890+
{
6891+
Addr: mustAbsOutputValue("output.is_secret"),
6892+
Change: plans.Change{
6893+
Action: plans.Create,
6894+
BeforeIdentity: cty.NullVal(cty.DynamicPseudoType),
6895+
AfterIdentity: cty.NullVal(cty.DynamicPseudoType),
6896+
Before: cty.NullVal(cty.DynamicPseudoType),
6897+
After: cty.True,
6898+
},
6899+
},
6900+
},
6901+
}
6902+
changes, err := plan.Changes.Decode(nil)
6903+
if err != nil {
6904+
t.Fatal(err)
6905+
}
6906+
6907+
sort.SliceStable(changes.Outputs, func(i, j int) bool {
6908+
return changes.Outputs[i].Addr.String() < changes.Outputs[j].Addr.String()
6909+
})
6910+
6911+
if diff := cmp.Diff(expectedChanges, changes, ctydebug.CmpOptions); diff != "" {
6912+
t.Fatalf("unexpected changes: %s", diff)
6913+
}
6914+
}

internal/terraform/evaluate.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ func (d *evaluationStateData) GetModule(addr addrs.ModuleCall, rng tfdiags.Sourc
430430
namedVals := d.Evaluator.NamedValues
431431
moduleInstAddr := absAddr.Instance(instKey)
432432
attrs := make(map[string]cty.Value, len(outputConfigs))
433-
for name := range outputConfigs {
433+
for name, cfg := range outputConfigs {
434434
outputAddr := moduleInstAddr.OutputValue(name)
435435

436436
// Although we do typically expect the graph dependencies to
@@ -446,6 +446,9 @@ func (d *evaluationStateData) GetModule(addr addrs.ModuleCall, rng tfdiags.Sourc
446446
continue
447447
}
448448
outputVal := namedVals.GetOutputValue(outputAddr)
449+
if cfg.Sensitive {
450+
outputVal = outputVal.Mark(marks.Sensitive)
451+
}
449452
attrs[name] = outputVal
450453
}
451454

0 commit comments

Comments
 (0)