Merge pull request #28381 from hashicorp/alisdair/fix-double-mark-sensitive-attrs
core: Fix double-marked sensitive attributes
This commit is contained in:
commit
ec001d3e18
|
@ -8,6 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
|
"github.com/hashicorp/terraform/configs/configschema"
|
||||||
"github.com/hashicorp/terraform/providers"
|
"github.com/hashicorp/terraform/providers"
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
|
@ -367,3 +368,80 @@ resource "aws_instance" "bin" {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContext2Apply_additionalSensitiveFromState(t *testing.T) {
|
||||||
|
// Ensure we're not trying to double-mark values decoded from state
|
||||||
|
m := testModuleInline(t, map[string]string{
|
||||||
|
"main.tf": `
|
||||||
|
variable "secret" {
|
||||||
|
sensitive = true
|
||||||
|
default = ["secret"]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "test_resource" "a" {
|
||||||
|
sensitive_attr = var.secret
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "test_resource" "b" {
|
||||||
|
value = test_resource.a.id
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
Type: cty.String,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"sensitive_attr": {
|
||||||
|
Type: cty.List(cty.String),
|
||||||
|
Optional: true,
|
||||||
|
Sensitive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
state := states.BuildState(func(s *states.SyncState) {
|
||||||
|
s.SetResourceInstanceCurrent(
|
||||||
|
mustResourceInstanceAddr(`test_resource.a`),
|
||||||
|
&states.ResourceInstanceObjectSrc{
|
||||||
|
AttrsJSON: []byte(`{"id":"a","sensitive_attr":["secret"]}`),
|
||||||
|
AttrSensitivePaths: []cty.PathValueMarks{
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("sensitive_attr"),
|
||||||
|
Marks: cty.NewValueMarks("sensitive"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: states.ObjectReady,
|
||||||
|
}, mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx := testContext2(t, &ContextOpts{
|
||||||
|
Config: m,
|
||||||
|
Providers: map[addrs.Provider]providers.Factory{
|
||||||
|
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||||
|
},
|
||||||
|
State: state,
|
||||||
|
})
|
||||||
|
|
||||||
|
_, diags := ctx.Plan()
|
||||||
|
if diags.HasErrors() {
|
||||||
|
t.Fatal(diags.ErrWithWarnings())
|
||||||
|
}
|
||||||
|
|
||||||
|
_, diags = ctx.Apply()
|
||||||
|
if diags.HasErrors() {
|
||||||
|
t.Fatal(diags.ErrWithWarnings())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -782,9 +782,15 @@ func (d *evaluationStateData) GetResource(addr addrs.Resource, rng tfdiags.Sourc
|
||||||
|
|
||||||
val := ios.Value
|
val := ios.Value
|
||||||
|
|
||||||
// If our schema contains sensitive values, mark those as sensitive
|
// If our schema contains sensitive values, mark those as sensitive.
|
||||||
|
// Since decoding the instance object can also apply sensitivity marks,
|
||||||
|
// we must remove and combine those before remarking to avoid a double-
|
||||||
|
// mark error.
|
||||||
if schema.ContainsSensitive() {
|
if schema.ContainsSensitive() {
|
||||||
val = markProviderSensitiveAttributes(schema, val)
|
var marks []cty.PathValueMarks
|
||||||
|
val, marks = val.UnmarkDeepWithPaths()
|
||||||
|
marks = append(marks, getValMarks(schema, val, nil)...)
|
||||||
|
val = val.MarkWithPaths(marks)
|
||||||
}
|
}
|
||||||
instances[key] = val
|
instances[key] = val
|
||||||
}
|
}
|
||||||
|
@ -954,12 +960,6 @@ func moduleDisplayAddr(addr addrs.ModuleInstance) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// markProviderSensitiveAttributes returns an updated value
|
|
||||||
// where attributes that are Sensitive are marked
|
|
||||||
func markProviderSensitiveAttributes(schema *configschema.Block, val cty.Value) cty.Value {
|
|
||||||
return val.MarkWithPaths(getValMarks(schema, val, nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getValMarks(schema *configschema.Block, val cty.Value, path cty.Path) []cty.PathValueMarks {
|
func getValMarks(schema *configschema.Block, val cty.Value, path cty.Path) []cty.PathValueMarks {
|
||||||
var pvm []cty.PathValueMarks
|
var pvm []cty.PathValueMarks
|
||||||
for name, attrS := range schema.Attributes {
|
for name, attrS := range schema.Attributes {
|
||||||
|
|
|
@ -563,7 +563,7 @@ func evaluatorForModule(stateSync *states.SyncState, changesSync *plans.ChangesS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMarkProviderSensitive(t *testing.T) {
|
func TestGetValMarks(t *testing.T) {
|
||||||
schema := &configschema.Block{
|
schema := &configschema.Block{
|
||||||
Attributes: map[string]*configschema.Attribute{
|
Attributes: map[string]*configschema.Attribute{
|
||||||
"unsensitive": {
|
"unsensitive": {
|
||||||
|
@ -647,7 +647,7 @@ func TestMarkProviderSensitive(t *testing.T) {
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(fmt.Sprintf("%#v", tc.given), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%#v", tc.given), func(t *testing.T) {
|
||||||
got := markProviderSensitiveAttributes(schema, tc.given)
|
got := tc.given.MarkWithPaths(getValMarks(schema, tc.given, nil))
|
||||||
if !got.RawEquals(tc.expect) {
|
if !got.RawEquals(tc.expect) {
|
||||||
t.Fatalf("\nexpected: %#v\ngot: %#v\n", tc.expect, got)
|
t.Fatalf("\nexpected: %#v\ngot: %#v\n", tc.expect, got)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue