lang/funcs: Make nonsensitive more permissive
Calling the nonsensitive function with values which are not sensitive will result in an error. This restriction was added with the goal of preventing confusingly redundant use of this function. Unfortunately, this breaks when using nonsensitive to reveal the value of sensitive resource attributes. This is because the validate walk does not (and cannot) mark attributes as sensitive based on the schema, because the resource value itself is unknown. This commit therefore alters this restriction such that it permits nonsensitive unknown values, and adds a test case to cover this specific scenario.
This commit is contained in:
parent
1212bbec9f
commit
c1f7193454
|
@ -48,7 +48,7 @@ var NonsensitiveFunc = function.New(&function.Spec{
|
|||
return args[0].Type(), nil
|
||||
},
|
||||
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
|
||||
if !args[0].HasMark("sensitive") {
|
||||
if args[0].IsKnown() && !args[0].HasMark("sensitive") {
|
||||
return cty.DynamicVal, function.NewArgErrorf(0, "the given value is not sensitive, so this call is redundant")
|
||||
}
|
||||
v, marks := args[0].Unmark()
|
||||
|
|
|
@ -133,17 +133,20 @@ func TestNonsensitive(t *testing.T) {
|
|||
cty.NumberIntVal(1),
|
||||
`the given value is not sensitive, so this call is redundant`,
|
||||
},
|
||||
{
|
||||
cty.DynamicVal,
|
||||
`the given value is not sensitive, so this call is redundant`,
|
||||
},
|
||||
{
|
||||
cty.NullVal(cty.String),
|
||||
`the given value is not sensitive, so this call is redundant`,
|
||||
},
|
||||
|
||||
// Unknown values may become sensitive once they are known, so we
|
||||
// permit them to be marked nonsensitive.
|
||||
{
|
||||
cty.DynamicVal,
|
||||
``,
|
||||
},
|
||||
{
|
||||
cty.UnknownVal(cty.String),
|
||||
`the given value is not sensitive, so this call is redundant`,
|
||||
``,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -377,3 +377,65 @@ resource "test_object" "a" {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestContext2Plan_unmarkingSensitiveAttributeForOutput(t *testing.T) {
|
||||
m := testModuleInline(t, map[string]string{
|
||||
"main.tf": `
|
||||
resource "test_resource" "foo" {
|
||||
}
|
||||
|
||||
output "result" {
|
||||
value = nonsensitive(test_resource.foo.sensitive_attr)
|
||||
}
|
||||
`,
|
||||
})
|
||||
|
||||
p := new(MockProvider)
|
||||
p.GetProviderSchemaResponse = getProviderSchemaResponseFromProviderSchema(&ProviderSchema{
|
||||
ResourceTypes: map[string]*configschema.Block{
|
||||
"test_resource": {
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
"sensitive_attr": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
|
||||
return providers.PlanResourceChangeResponse{
|
||||
PlannedState: cty.UnknownVal(cty.Object(map[string]cty.Type{
|
||||
"id": cty.String,
|
||||
"sensitive_attr": cty.String,
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
state := states.NewState()
|
||||
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Config: m,
|
||||
Providers: map[addrs.Provider]providers.Factory{
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||
},
|
||||
State: state,
|
||||
})
|
||||
|
||||
plan, diags := ctx.Plan()
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.ErrWithWarnings())
|
||||
}
|
||||
|
||||
for _, res := range plan.Changes.Resources {
|
||||
if res.Action != plans.Create {
|
||||
t.Fatalf("expected create, got: %q %s", res.Addr, res.Action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue