From 66091ae36cc2e2f6627d09d181d665af753e82bf Mon Sep 17 00:00:00 2001 From: Pam Selle <204372+pselle@users.noreply.github.com> Date: Wed, 28 Oct 2020 15:11:45 -0400 Subject: [PATCH] Unmark values before showing in JSON This prevents "sensitive" values from unintentionally showing as nil when running terraform show -json --- command/jsonstate/state.go | 10 +-- command/jsonstate/state_test.go | 65 +++++-------------- .../sensitive-variables/output.json | 22 +++++++ .../sensitive-variables/terraform.tfstate | 33 ++++++++++ 4 files changed, 79 insertions(+), 51 deletions(-) create mode 100644 command/testdata/show-json-state/sensitive-variables/output.json create mode 100644 command/testdata/show-json-state/sensitive-variables/terraform.tfstate diff --git a/command/jsonstate/state.go b/command/jsonstate/state.go index 24eba59b5..fdf2d483f 100644 --- a/command/jsonstate/state.go +++ b/command/jsonstate/state.go @@ -9,7 +9,6 @@ import ( ctyjson "github.com/zclconf/go-cty/cty/json" "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states/statefile" "github.com/hashicorp/terraform/terraform" @@ -100,7 +99,10 @@ type resource struct { // resource, whose structure depends on the resource type schema. type attributeValues map[string]interface{} -func marshalAttributeValues(value cty.Value, schema *configschema.Block) attributeValues { +func marshalAttributeValues(value cty.Value) attributeValues { + // unmark our value to show all values + value, _ = value.UnmarkDeep() + if value == cty.NilVal || value.IsNull() { return nil } @@ -295,7 +297,7 @@ func marshalResources(resources map[string]*states.Resource, module addrs.Module return nil, err } - current.AttributeValues = marshalAttributeValues(riObj.Value, schema) + current.AttributeValues = marshalAttributeValues(riObj.Value) if len(riObj.Dependencies) > 0 { dependencies := make([]string, len(riObj.Dependencies)) @@ -327,7 +329,7 @@ func marshalResources(resources map[string]*states.Resource, module addrs.Module return nil, err } - deposed.AttributeValues = marshalAttributeValues(riObj.Value, schema) + deposed.AttributeValues = marshalAttributeValues(riObj.Value) if len(riObj.Dependencies) > 0 { dependencies := make([]string, len(riObj.Dependencies)) diff --git a/command/jsonstate/state_test.go b/command/jsonstate/state_test.go index 55d3c47f6..efbaa182c 100644 --- a/command/jsonstate/state_test.go +++ b/command/jsonstate/state_test.go @@ -75,60 +75,27 @@ func TestMarshalOutputs(t *testing.T) { func TestMarshalAttributeValues(t *testing.T) { tests := []struct { - Attr cty.Value - Schema *configschema.Block - Want attributeValues + Attr cty.Value + Want attributeValues }{ { cty.NilVal, - &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "foo": { - Type: cty.String, - Optional: true, - }, - }, - }, nil, }, { cty.NullVal(cty.String), - &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "foo": { - Type: cty.String, - Optional: true, - }, - }, - }, nil, }, { cty.ObjectVal(map[string]cty.Value{ "foo": cty.StringVal("bar"), }), - &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "foo": { - Type: cty.String, - Optional: true, - }, - }, - }, attributeValues{"foo": json.RawMessage(`"bar"`)}, }, { cty.ObjectVal(map[string]cty.Value{ "foo": cty.NullVal(cty.String), }), - &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "foo": { - Type: cty.String, - Optional: true, - }, - }, - }, attributeValues{"foo": json.RawMessage(`null`)}, }, { @@ -141,18 +108,22 @@ func TestMarshalAttributeValues(t *testing.T) { cty.StringVal("moon"), }), }), - &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "bar": { - Type: cty.Map(cty.String), - Required: true, - }, - "baz": { - Type: cty.List(cty.String), - Optional: true, - }, - }, + attributeValues{ + "bar": json.RawMessage(`{"hello":"world"}`), + "baz": json.RawMessage(`["goodnight","moon"]`), }, + }, + // Marked values + { + cty.ObjectVal(map[string]cty.Value{ + "bar": cty.MapVal(map[string]cty.Value{ + "hello": cty.StringVal("world"), + }), + "baz": cty.ListVal([]cty.Value{ + cty.StringVal("goodnight"), + cty.StringVal("moon").Mark("sensitive"), + }), + }), attributeValues{ "bar": json.RawMessage(`{"hello":"world"}`), "baz": json.RawMessage(`["goodnight","moon"]`), @@ -161,7 +132,7 @@ func TestMarshalAttributeValues(t *testing.T) { } for _, test := range tests { - got := marshalAttributeValues(test.Attr, test.Schema) + got := marshalAttributeValues(test.Attr) eq := reflect.DeepEqual(got, test.Want) if !eq { t.Fatalf("wrong result:\nGot: %#v\nWant: %#v\n", got, test.Want) diff --git a/command/testdata/show-json-state/sensitive-variables/output.json b/command/testdata/show-json-state/sensitive-variables/output.json new file mode 100644 index 000000000..a4e74aa37 --- /dev/null +++ b/command/testdata/show-json-state/sensitive-variables/output.json @@ -0,0 +1,22 @@ +{ + "format_version": "0.1", + "terraform_version": "0.14.0", + "values": { + "root_module": { + "resources": [ + { + "address": "test_instance.test", + "mode": "managed", + "type": "test_instance", + "name": "test", + "provider_name": "registry.terraform.io/hashicorp/test", + "schema_version": 0, + "values": { + "id": "621124146446964903", + "ami": "abc" + } + } + ] + } + } +} diff --git a/command/testdata/show-json-state/sensitive-variables/terraform.tfstate b/command/testdata/show-json-state/sensitive-variables/terraform.tfstate new file mode 100644 index 000000000..55712452a --- /dev/null +++ b/command/testdata/show-json-state/sensitive-variables/terraform.tfstate @@ -0,0 +1,33 @@ +{ + "version": 4, + "terraform_version": "0.14.0", + "serial": 1, + "lineage": "d7a6880b-6875-288f-13a9-696a65c73036", + "outputs": {}, + "resources": [ + { + "mode": "managed", + "type": "test_instance", + "name": "test", + "provider": "provider[\"registry.terraform.io/hashicorp/test\"]", + "instances": [ + { + "schema_version": 0, + "attributes": { + "id": "621124146446964903", + "ami": "abc" + }, + "sensitive_attributes": [ + [ + { + "type": "get_attr", + "value": "ami" + } + ] + ], + "private": "bnVsbA==" + } + ] + } + ] +}