Merge pull request #26986 from hashicorp/pselle/validate-sensitive

Unmark values before provider validate call
This commit is contained in:
Pam Selle 2020-11-20 11:25:27 -05:00 committed by GitHub
commit 9ac9564207
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 121 additions and 8 deletions

View File

@ -62,19 +62,19 @@ func simpleTestSchema() *configschema.Block {
Optional: true,
},
"test_number": {
Type: cty.String,
Type: cty.Number,
Optional: true,
},
"test_bool": {
Type: cty.String,
Type: cty.Bool,
Optional: true,
},
"test_list": {
Type: cty.String,
Type: cty.List(cty.String),
Optional: true,
},
"test_map": {
Type: cty.String,
Type: cty.Map(cty.String),
Optional: true,
},
},

View File

@ -1131,6 +1131,71 @@ func TestContext2Validate_interpolateMap(t *testing.T) {
}
}
func TestContext2Validate_varSensitive(t *testing.T) {
// Smoke test through validate where a variable has sensitive applied
m := testModuleInline(t, map[string]string{
"main.tf": `
variable "foo" {
default = "xyz"
sensitive = true
}
variable "bar" {
sensitive = true
}
data "aws_data_source" "bar" {
foo = var.bar
}
resource "aws_instance" "foo" {
foo = var.foo
}
`,
})
p := testProvider("aws")
p.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse {
// Providers receive unmarked values
if got, want := req.Config.GetAttr("foo"), cty.UnknownVal(cty.String); !got.RawEquals(want) {
t.Fatalf("wrong value for foo\ngot: %#v\nwant: %#v", got, want)
}
return providers.ValidateResourceTypeConfigResponse{}
}
p.ValidateDataSourceConfigFn = func(req providers.ValidateDataSourceConfigRequest) (resp providers.ValidateDataSourceConfigResponse) {
if got, want := req.Config.GetAttr("foo"), cty.UnknownVal(cty.String); !got.RawEquals(want) {
t.Fatalf("wrong value for foo\ngot: %#v\nwant: %#v", got, want)
}
return providers.ValidateDataSourceConfigResponse{}
}
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
},
Variables: InputValues{
"bar": &InputValue{
Value: cty.StringVal("boop"),
SourceType: ValueFromCaller,
},
},
})
diags := ctx.Validate()
if diags.HasErrors() {
t.Fatal(diags.Err())
}
if !p.ValidateResourceTypeConfigCalled {
t.Fatal("expected ValidateResourceTypeConfigFn to be called")
}
if !p.ValidateDataSourceConfigCalled {
t.Fatal("expected ValidateDataSourceConfigFn to be called")
}
}
// Manually validate using the new PlanGraphBuilder
func TestContext2Validate_PlanGraphBuilder(t *testing.T) {
fixture := contextFixtureApplyVars(t)

View File

@ -374,9 +374,11 @@ func (n *EvalValidateResource) Validate(ctx EvalContext) tfdiags.Diagnostics {
}
}
// Use unmarked value for validate request
unmarkedConfigVal, _ := configVal.UnmarkDeep()
req := providers.ValidateResourceTypeConfigRequest{
TypeName: cfg.Type,
Config: configVal,
Config: unmarkedConfigVal,
}
resp := provider.ValidateResourceTypeConfig(req)
@ -404,9 +406,11 @@ func (n *EvalValidateResource) Validate(ctx EvalContext) tfdiags.Diagnostics {
return diags
}
// Use unmarked value for validate request
unmarkedConfigVal, _ := configVal.UnmarkDeep()
req := providers.ValidateDataSourceConfigRequest{
TypeName: cfg.Type,
Config: configVal,
Config: unmarkedConfigVal,
}
resp := provider.ValidateDataSourceConfig(req)

View File

@ -26,6 +26,9 @@ func TestEvalValidateResource_managedResource(t *testing.T) {
if got, want := req.Config.GetAttr("test_string"), cty.StringVal("bar"); !got.RawEquals(want) {
t.Fatalf("wrong value for test_string\ngot: %#v\nwant: %#v", got, want)
}
if got, want := req.Config.GetAttr("test_number"), cty.NumberIntVal(2); !got.RawEquals(want) {
t.Fatalf("wrong value for test_number\ngot: %#v\nwant: %#v", got, want)
}
return providers.ValidateResourceTypeConfigResponse{}
}
@ -36,6 +39,7 @@ func TestEvalValidateResource_managedResource(t *testing.T) {
Name: "foo",
Config: configs.SynthBody("", map[string]cty.Value{
"test_string": cty.StringVal("bar"),
"test_number": cty.NumberIntVal(2).Mark("sensitive"),
}),
}
node := &EvalValidateResource{
@ -117,6 +121,9 @@ func TestEvalValidateResource_dataSource(t *testing.T) {
if got, want := req.Config.GetAttr("test_string"), cty.StringVal("bar"); !got.RawEquals(want) {
t.Fatalf("wrong value for test_string\ngot: %#v\nwant: %#v", got, want)
}
if got, want := req.Config.GetAttr("test_number"), cty.NumberIntVal(2); !got.RawEquals(want) {
t.Fatalf("wrong value for test_number\ngot: %#v\nwant: %#v", got, want)
}
return providers.ValidateDataSourceConfigResponse{}
}
@ -127,6 +134,7 @@ func TestEvalValidateResource_dataSource(t *testing.T) {
Name: "foo",
Config: configs.SynthBody("", map[string]cty.Value{
"test_string": cty.StringVal("bar"),
"test_number": cty.NumberIntVal(2).Mark("sensitive"),
}),
}

View File

@ -6,6 +6,7 @@ import (
"github.com/zclconf/go-cty/cty"
ctyjson "github.com/zclconf/go-cty/cty/json"
"github.com/zclconf/go-cty/cty/msgpack"
"github.com/hashicorp/terraform/configs/hcl2shim"
"github.com/hashicorp/terraform/providers"
@ -124,6 +125,24 @@ func (p *MockProvider) getSchema() providers.GetSchemaResponse {
return ret
}
func (p *MockProvider) getResourceSchema(name string) providers.Schema {
schema := p.getSchema()
resSchema, ok := schema.ResourceTypes[name]
if !ok {
panic("unknown resource type " + name)
}
return resSchema
}
func (p *MockProvider) getDatasourceSchema(name string) providers.Schema {
schema := p.getSchema()
dataSchema, ok := schema.DataSources[name]
if !ok {
panic("unknown data source " + name)
}
return dataSchema
}
func (p *MockProvider) PrepareProviderConfig(r providers.PrepareProviderConfigRequest) providers.PrepareProviderConfigResponse {
p.Lock()
defer p.Unlock()
@ -137,13 +156,22 @@ func (p *MockProvider) PrepareProviderConfig(r providers.PrepareProviderConfigRe
return p.PrepareProviderConfigResponse
}
func (p *MockProvider) ValidateResourceTypeConfig(r providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse {
func (p *MockProvider) ValidateResourceTypeConfig(r providers.ValidateResourceTypeConfigRequest) (resp providers.ValidateResourceTypeConfigResponse) {
p.Lock()
defer p.Unlock()
p.ValidateResourceTypeConfigCalled = true
p.ValidateResourceTypeConfigRequest = r
// Marshall the value to replicate behavior by the GRPC protocol,
// and return any relevant errors
resourceSchema := p.getResourceSchema(r.TypeName)
_, err := msgpack.Marshal(r.Config, resourceSchema.Block.ImpliedType())
if err != nil {
resp.Diagnostics = resp.Diagnostics.Append(err)
return resp
}
if p.ValidateResourceTypeConfigFn != nil {
return p.ValidateResourceTypeConfigFn(r)
}
@ -151,13 +179,21 @@ func (p *MockProvider) ValidateResourceTypeConfig(r providers.ValidateResourceTy
return p.ValidateResourceTypeConfigResponse
}
func (p *MockProvider) ValidateDataSourceConfig(r providers.ValidateDataSourceConfigRequest) providers.ValidateDataSourceConfigResponse {
func (p *MockProvider) ValidateDataSourceConfig(r providers.ValidateDataSourceConfigRequest) (resp providers.ValidateDataSourceConfigResponse) {
p.Lock()
defer p.Unlock()
p.ValidateDataSourceConfigCalled = true
p.ValidateDataSourceConfigRequest = r
// Marshall the value to replicate behavior by the GRPC protocol
dataSchema := p.getDatasourceSchema(r.TypeName)
_, err := msgpack.Marshal(r.Config, dataSchema.Block.ImpliedType())
if err != nil {
resp.Diagnostics = resp.Diagnostics.Append(err)
return resp
}
if p.ValidateDataSourceConfigFn != nil {
return p.ValidateDataSourceConfigFn(r)
}