From 8cba2bfc395df704c4278b079f8d20f2537d4561 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Tue, 23 Mar 2021 17:06:18 -0400 Subject: [PATCH] check for unknowns when marking resource values When we map schema sensitivity to resource values, there may be unknowns when dealing with planned objects. Check for unknowns before iterating over block values. --- terraform/evaluate.go | 7 ++- terraform/evaluate_test.go | 93 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/terraform/evaluate.go b/terraform/evaluate.go index 4bf19fefc..6dde19700 100644 --- a/terraform/evaluate.go +++ b/terraform/evaluate.go @@ -979,12 +979,17 @@ func getValMarks(schema *configschema.Block, val cty.Value, path cty.Path) []cty if !blockS.Block.ContainsSensitive() { continue } + + blockV := val.GetAttr(name) + if blockV.IsNull() || !blockV.IsKnown() { + continue + } + // Create a copy of the path, with this step added, to add to our PathValueMarks slice blockPath := make(cty.Path, len(path), len(path)+1) copy(blockPath, path) blockPath = append(path, cty.GetAttrStep{Name: name}) - blockV := val.GetAttr(name) switch blockS.Nesting { case configschema.NestingSingle, configschema.NestingGroup: pvm = append(pvm, getValMarks(&blockS.Block, blockV, blockPath)...) diff --git a/terraform/evaluate_test.go b/terraform/evaluate_test.go index 7a96767f1..427b2291a 100644 --- a/terraform/evaluate_test.go +++ b/terraform/evaluate_test.go @@ -1,6 +1,7 @@ package terraform import ( + "fmt" "sync" "testing" @@ -550,3 +551,95 @@ func evaluatorForModule(stateSync *states.SyncState, changesSync *plans.ChangesS Changes: changesSync, } } + +func TestMarkProviderSensitive(t *testing.T) { + schema := &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "unsensitive": { + Type: cty.String, + Optional: true, + }, + "sensitive": { + Type: cty.String, + Sensitive: true, + }, + }, + + BlockTypes: map[string]*configschema.NestedBlock{ + "list": &configschema.NestedBlock{ + Nesting: configschema.NestingList, + Block: configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "unsensitive": { + Type: cty.String, + Optional: true, + }, + "sensitive": { + Type: cty.String, + Sensitive: true, + }, + }, + }, + }, + }, + } + + for _, tc := range []struct { + given cty.Value + expect cty.Value + }{ + { + cty.UnknownVal(schema.ImpliedType()), + cty.UnknownVal(schema.ImpliedType()), + }, + { + cty.ObjectVal(map[string]cty.Value{ + "sensitive": cty.UnknownVal(cty.String), + "unsensitive": cty.UnknownVal(cty.String), + "list": cty.UnknownVal(schema.BlockTypes["list"].ImpliedType()), + }), + cty.ObjectVal(map[string]cty.Value{ + "sensitive": cty.UnknownVal(cty.String).Mark("sensitive"), + "unsensitive": cty.UnknownVal(cty.String), + "list": cty.UnknownVal(schema.BlockTypes["list"].ImpliedType()), + }), + }, + { + cty.ObjectVal(map[string]cty.Value{ + "sensitive": cty.NullVal(cty.String), + "unsensitive": cty.UnknownVal(cty.String), + "list": cty.ListVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "sensitive": cty.UnknownVal(cty.String), + "unsensitive": cty.UnknownVal(cty.String), + }), + cty.ObjectVal(map[string]cty.Value{ + "sensitive": cty.NullVal(cty.String), + "unsensitive": cty.NullVal(cty.String), + }), + }), + }), + cty.ObjectVal(map[string]cty.Value{ + "sensitive": cty.NullVal(cty.String).Mark("sensitive"), + "unsensitive": cty.UnknownVal(cty.String), + "list": cty.ListVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "sensitive": cty.UnknownVal(cty.String).Mark("sensitive"), + "unsensitive": cty.UnknownVal(cty.String), + }), + cty.ObjectVal(map[string]cty.Value{ + "sensitive": cty.NullVal(cty.String).Mark("sensitive"), + "unsensitive": cty.NullVal(cty.String), + }), + }), + }), + }, + } { + t.Run(fmt.Sprintf("%#v", tc.given), func(t *testing.T) { + got := markProviderSensitiveAttributes(schema, tc.given) + if !got.RawEquals(tc.expect) { + t.Fatalf("\nexpected: %#v\ngot: %#v\n", tc.expect, got) + } + }) + } +}