Skip to content

Commit

Permalink
chore: mark secret fields as sensitive
Browse files Browse the repository at this point in the history
  • Loading branch information
johanneswuerbach committed Jun 13, 2024
1 parent f0e550f commit 8c5863a
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 36 deletions.
4 changes: 2 additions & 2 deletions docs/resources/resource_definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ resource "humanitec_resource_definition" "azure-blob" {

Optional:

- `secret_refs` (String) JSON encoded secrets section of the data set. They can hold sensitive information that will be stored in the primary organization secret store and replaced with the secret store paths when sent outside, or secret references stored in a defined secret store. Can't be used together with secrets.
- `secrets_string` (String) JSON encoded secret data set. Passed around as-is. Can't be used together with secret_refs.
- `secret_refs` (String, Sensitive) JSON encoded secrets section of the data set. They can hold sensitive information that will be stored in the primary organization secret store and replaced with the secret store paths when sent outside, or secret references stored in a defined secret store. Can't be used together with secrets.
- `secrets_string` (String, Sensitive) JSON encoded secret data set. Passed around as-is. Can't be used together with secret_refs.
- `values_string` (String) JSON encoded input data set. Passed around as-is.


Expand Down
2 changes: 2 additions & 0 deletions internal/provider/resource_definition_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,13 @@ func (r *ResourceDefinitionResource) Schema(ctx context.Context, req resource.Sc
"secrets_string": schema.StringAttribute{
MarkdownDescription: "JSON encoded secret data set. Passed around as-is. Can't be used together with secret_refs.",
Optional: true,
Sensitive: true,
},
"secret_refs": schema.StringAttribute{
MarkdownDescription: "JSON encoded secrets section of the data set. They can hold sensitive information that will be stored in the primary organization secret store and replaced with the secret store paths when sent outside, or secret references stored in a defined secret store. Can't be used together with secrets.",
Optional: true,
Computed: true,
Sensitive: true,
Validators: []validator.String{
stringvalidator.ConflictsWith(path.Expressions{
path.MatchRelative().AtParent().AtName("secrets_string"),
Expand Down
102 changes: 68 additions & 34 deletions internal/provider/resource_definition_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,26 @@ import (

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/stretchr/testify/assert"
)

type stringErrFn func() (string, error)

func staticString(s string) stringErrFn {
return func() (string, error) {
return s, nil
}
}

func jsonString(s any) stringErrFn {
return func() (string, error) {
b, err := json.Marshal(s)
return string(b), err
}
}

func TestAccResourceDefinition(t *testing.T) {

timestamp := time.Now().UnixNano()
tests := []struct {
name string
Expand All @@ -21,8 +38,8 @@ func TestAccResourceDefinition(t *testing.T) {
resourceAttrName string
resourceAttrNameIDValue string
resourceAttrNameUpdateKey string
resourceAttrNameUpdateValue1 string
resourceAttrNameUpdateValue2 string
resourceAttrNameUpdateValue1 stringErrFn
resourceAttrNameUpdateValue2 stringErrFn
importStateVerifyIgnore []string
}{
{
Expand All @@ -32,12 +49,12 @@ func TestAccResourceDefinition(t *testing.T) {
},
resourceAttrNameIDValue: fmt.Sprintf("s3-test-%d", timestamp),
resourceAttrNameUpdateKey: "driver_type",
resourceAttrNameUpdateValue1: "humanitec/s3",
resourceAttrNameUpdateValue1: staticString("humanitec/s3"),
resourceAttrName: "humanitec_resource_definition.s3_test",
configUpdate: func() string {
return testAccResourceDefinitionS3ResourceWithDifferentDriver(fmt.Sprintf("s3-test-%d", timestamp), "us-east-1", "humanitec/terraform")
},
resourceAttrNameUpdateValue2: "humanitec/terraform",
resourceAttrNameUpdateValue2: staticString("humanitec/terraform"),
importStateVerifyIgnore: []string{"driver_inputs.secrets_string", "force_delete"},
},
{
Expand All @@ -47,12 +64,12 @@ func TestAccResourceDefinition(t *testing.T) {
},
resourceAttrNameIDValue: fmt.Sprintf("s3-test-%d", timestamp),
resourceAttrNameUpdateKey: "driver_type",
resourceAttrNameUpdateValue1: "humanitec/s3",
resourceAttrNameUpdateValue1: staticString("humanitec/s3"),
resourceAttrName: "humanitec_resource_definition.s3_test",
configUpdate: func() string {
return testAccResourceDefinitionS3Resource(fmt.Sprintf("s3-test-%d", timestamp), "us-east-1")
},
resourceAttrNameUpdateValue2: "humanitec/s3",
resourceAttrNameUpdateValue2: staticString("humanitec/s3"),
importStateVerifyIgnore: []string{"driver_inputs.secrets_string", "force_delete"},
},
{
Expand All @@ -62,12 +79,12 @@ func TestAccResourceDefinition(t *testing.T) {
},
resourceAttrNameIDValue: fmt.Sprintf("s3-test-%d", timestamp),
resourceAttrNameUpdateKey: "driver_inputs.values_string",
resourceAttrNameUpdateValue1: "{\"region\":\"us-east-1\"}",
resourceAttrNameUpdateValue1: jsonString(map[string]interface{}{"region": "us-east-1"}),
resourceAttrName: "humanitec_resource_definition.s3_test",
configUpdate: func() string {
return testAccResourceDefinitionS3Resource(fmt.Sprintf("s3-test-%d", timestamp), "us-east-2")
},
resourceAttrNameUpdateValue2: "{\"region\":\"us-east-2\"}",
resourceAttrNameUpdateValue2: jsonString(map[string]interface{}{"region": "us-east-2"}),
importStateVerifyIgnore: []string{"driver_inputs.secrets_string", "force_delete"},
},
{
Expand All @@ -77,12 +94,12 @@ func TestAccResourceDefinition(t *testing.T) {
},
resourceAttrNameIDValue: fmt.Sprintf("postgres-test-%d", timestamp),
resourceAttrNameUpdateKey: "driver_inputs.values_string",
resourceAttrNameUpdateValue1: "{\"host\":\"127.0.0.1\",\"instance\":\"test:test:test\",\"name\":\"test-1\",\"port\":5432}",
resourceAttrNameUpdateValue1: jsonString(map[string]interface{}{"host": "127.0.0.1", "instance": "test:test:test", "name": "test-1", "port": 5432}),
resourceAttrName: "humanitec_resource_definition.postgres_test",
configUpdate: func() string {
return testAccResourceDefinitionPostgresResource(fmt.Sprintf("postgres-test-%d", timestamp), "test-2")
},
resourceAttrNameUpdateValue2: "{\"host\":\"127.0.0.1\",\"instance\":\"test:test:test\",\"name\":\"test-2\",\"port\":5432}",
resourceAttrNameUpdateValue2: jsonString(map[string]interface{}{"host": "127.0.0.1", "instance": "test:test:test", "name": "test-2", "port": 5432}),
importStateVerifyIgnore: []string{"driver_inputs.secrets_string", "force_delete"},
},
{
Expand All @@ -92,12 +109,12 @@ func TestAccResourceDefinition(t *testing.T) {
},
resourceAttrNameIDValue: fmt.Sprintf("gke-test-%d", timestamp),
resourceAttrNameUpdateKey: "driver_inputs.values_string",
resourceAttrNameUpdateValue1: "{\"loadbalancer\":\"1.1.1.1\",\"name\":\"test-1\",\"project_id\":\"test\",\"zone\":\"europe-west3\"}",
resourceAttrNameUpdateValue1: jsonString(map[string]interface{}{"loadbalancer": "1.1.1.1", "name": "test-1", "project_id": "test", "zone": "europe-west3"}),
resourceAttrName: "humanitec_resource_definition.gke_test",
configUpdate: func() string {
return testAccResourceDefinitionGKEResource(fmt.Sprintf("gke-test-%d", timestamp), "test-2")
},
resourceAttrNameUpdateValue2: "{\"loadbalancer\":\"1.1.1.1\",\"name\":\"test-2\",\"project_id\":\"test\",\"zone\":\"europe-west3\"}",
resourceAttrNameUpdateValue2: jsonString(map[string]interface{}{"loadbalancer": "1.1.1.1", "name": "test-2", "project_id": "test", "zone": "europe-west3"}),
importStateVerifyIgnore: []string{"driver_inputs.secrets_string", "force_delete"},
},
{
Expand All @@ -107,12 +124,12 @@ func TestAccResourceDefinition(t *testing.T) {
},
resourceAttrNameIDValue: fmt.Sprintf("dns-test-%d", timestamp),
resourceAttrNameUpdateKey: "driver_inputs.values_string",
resourceAttrNameUpdateValue1: "{\"host\":\"test-1\"}",
resourceAttrNameUpdateValue1: jsonString(map[string]interface{}{"host": "test-1"}),
resourceAttrName: "humanitec_resource_definition.dns_test",
configUpdate: func() string {
return testAccResourceDefinitionDNSStaticResource(fmt.Sprintf("dns-test-%d", timestamp), "test-2")
},
resourceAttrNameUpdateValue2: "{\"host\":\"test-2\"}",
resourceAttrNameUpdateValue2: jsonString(map[string]interface{}{"host": "test-2"}),
importStateVerifyIgnore: []string{"driver_inputs.secrets_string", "force_delete"},
},
{
Expand All @@ -122,12 +139,12 @@ func TestAccResourceDefinition(t *testing.T) {
},
resourceAttrNameIDValue: fmt.Sprintf("ingress-test-%d", timestamp),
resourceAttrNameUpdateKey: "driver_inputs.values_string",
resourceAttrNameUpdateValue1: "{\"labels\":{\"name\":\"test-1\"},\"no_tls\":true}",
resourceAttrNameUpdateValue1: jsonString(map[string]interface{}{"labels": map[string]interface{}{"name": "test-1"}, "no_tls": true}),
resourceAttrName: "humanitec_resource_definition.ingress_test",
configUpdate: func() string {
return testAccResourceDefinitionIngressResource(fmt.Sprintf("ingress-test-%d", timestamp), "test-2")
},
resourceAttrNameUpdateValue2: "{\"labels\":{\"name\":\"test-2\"},\"no_tls\":true}",
resourceAttrNameUpdateValue2: jsonString(map[string]interface{}{"labels": map[string]interface{}{"name": "test-2"}, "no_tls": true}),
importStateVerifyIgnore: []string{"driver_inputs.secrets_string", "force_delete"},
},
{
Expand All @@ -137,12 +154,12 @@ func TestAccResourceDefinition(t *testing.T) {
},
resourceAttrNameIDValue: fmt.Sprintf("provision-test-%d", timestamp),
resourceAttrNameUpdateKey: "provision.awspolicy.match_dependents",
resourceAttrNameUpdateValue1: "true",
resourceAttrNameUpdateValue1: staticString("true"),
resourceAttrName: "humanitec_resource_definition.provision_test",
configUpdate: func() string {
return testAccResourceDefinitionProvisionResource(fmt.Sprintf("provision-test-%d", timestamp), "false")
},
resourceAttrNameUpdateValue2: "false",
resourceAttrNameUpdateValue2: staticString("false"),
importStateVerifyIgnore: []string{"driver_inputs.secrets_string", "force_delete"},
},
{
Expand All @@ -152,48 +169,65 @@ func TestAccResourceDefinition(t *testing.T) {
},
resourceAttrNameIDValue: fmt.Sprintf("k8s-logging-test-%d", timestamp),
resourceAttrNameUpdateKey: "name",
resourceAttrNameUpdateValue1: "test-1",
resourceAttrNameUpdateValue1: staticString("test-1"),
resourceAttrName: "humanitec_resource_definition.k8s_logging_test",
configUpdate: func() string {
return testAccResourceDefinitionK8sLoggingResource(fmt.Sprintf("k8s-logging-test-%d", timestamp), "test-2")
},
resourceAttrNameUpdateValue2: "test-2",
resourceAttrNameUpdateValue2: staticString("test-2"),
importStateVerifyIgnore: []string{"driver_inputs.secrets_string", "force_delete"},
},
{
name: "S3 static - secret refs",
configCreate: func() string {
return testAccResourceDefinitionS3taticResourceWithSecretRefs(fmt.Sprintf("s3-test-with-secrets-%d", timestamp), "accessKeyIdPath1", "secretAccessKeyPath1")
},
resourceAttrNameIDValue: fmt.Sprintf("s3-test-with-secrets-%d", timestamp),
resourceAttrNameUpdateKey: "driver_inputs.secret_refs",
resourceAttrNameUpdateValue1: "{\"aws_access_key_id\":{\"ref\":\"accessKeyIdPath1\",\"store\":\"external-secret-store\",\"version\":\"1\"},\"aws_secret_access_key\":{\"ref\":\"secretAccessKeyPath1\",\"store\":\"external-secret-store\",\"version\":\"1\"}}",
resourceAttrName: "humanitec_resource_definition.s3_test_with_secrets",
resourceAttrNameIDValue: fmt.Sprintf("s3-test-with-secrets-%d", timestamp),
resourceAttrNameUpdateKey: "driver_inputs.secret_refs",
resourceAttrNameUpdateValue1: jsonString(map[string]interface{}{
"aws_access_key_id": map[string]interface{}{"ref": "accessKeyIdPath1", "store": "external-secret-store", "version": "1"},
"aws_secret_access_key": map[string]interface{}{"ref": "secretAccessKeyPath1", "store": "external-secret-store", "version": "1"},
}),
resourceAttrName: "humanitec_resource_definition.s3_test_with_secrets",
configUpdate: func() string {
return testAccResourceDefinitionS3taticResourceWithSecretRefs(fmt.Sprintf("s3-test-with-secrets-%d", timestamp), "accessKeyIdPath2", "secretAccessKeyPath2")
},
resourceAttrNameUpdateValue2: "{\"aws_access_key_id\":{\"ref\":\"accessKeyIdPath2\",\"store\":\"external-secret-store\",\"version\":\"1\"},\"aws_secret_access_key\":{\"ref\":\"secretAccessKeyPath2\",\"store\":\"external-secret-store\",\"version\":\"1\"}}",
importStateVerifyIgnore: []string{"force_delete"},
resourceAttrNameUpdateValue2: jsonString(map[string]interface{}{
"aws_access_key_id": map[string]interface{}{"ref": "accessKeyIdPath2", "store": "external-secret-store", "version": "1"},
"aws_secret_access_key": map[string]interface{}{"ref": "secretAccessKeyPath2", "store": "external-secret-store", "version": "1"},
}),
importStateVerifyIgnore: []string{"force_delete"},
},
{
name: "S3 static - secret ref set values",
configCreate: func() string {
return testAccResourceDefinitionS3taticResourceWithSecretRefValues(fmt.Sprintf("s3-test-with-secrets-%d", timestamp), "accessKeyId1", "secretAccessKey1")
},
resourceAttrNameIDValue: fmt.Sprintf("s3-test-with-secrets-%d", timestamp),
resourceAttrNameUpdateKey: "driver_inputs.secret_refs",
resourceAttrNameUpdateValue1: "{\"aws_access_key_id\":{\"value\":\"accessKeyId1\"},\"aws_secret_access_key\":{\"value\":\"secretAccessKey1\"}}",
resourceAttrName: "humanitec_resource_definition.s3_test_with_secrets",
resourceAttrNameIDValue: fmt.Sprintf("s3-test-with-secrets-%d", timestamp),
resourceAttrNameUpdateKey: "driver_inputs.secret_refs",
resourceAttrNameUpdateValue1: jsonString(map[string]interface{}{
"aws_access_key_id": map[string]interface{}{"value": "accessKeyId1"},
"aws_secret_access_key": map[string]interface{}{"value": "secretAccessKey1"},
}),
resourceAttrName: "humanitec_resource_definition.s3_test_with_secrets",
configUpdate: func() string {
return testAccResourceDefinitionS3taticResourceWithSecretRefValues(fmt.Sprintf("s3-test-with-secrets-%d", timestamp), "accessKeyId2", "secretAccessKey2")
},
resourceAttrNameUpdateValue2: "{\"aws_access_key_id\":{\"value\":\"accessKeyId2\"},\"aws_secret_access_key\":{\"value\":\"secretAccessKey2\"}}",
importStateVerifyIgnore: []string{"driver_inputs.secret_refs", "force_delete"},
resourceAttrNameUpdateValue2: jsonString(map[string]interface{}{
"aws_access_key_id": map[string]interface{}{"value": "accessKeyId2"},
"aws_secret_access_key": map[string]interface{}{"value": "secretAccessKey2"},
}),
importStateVerifyIgnore: []string{"driver_inputs.secret_refs", "force_delete"},
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
updateValue1, err := tc.resourceAttrNameUpdateValue1()
assert.NoError(t, err)
updateValue2, err := tc.resourceAttrNameUpdateValue2()
assert.NoError(t, err)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Expand All @@ -203,7 +237,7 @@ func TestAccResourceDefinition(t *testing.T) {
Config: tc.configCreate(),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(tc.resourceAttrName, "id", tc.resourceAttrNameIDValue),
resource.TestCheckResourceAttr(tc.resourceAttrName, tc.resourceAttrNameUpdateKey, tc.resourceAttrNameUpdateValue1),
resource.TestCheckResourceAttr(tc.resourceAttrName, tc.resourceAttrNameUpdateKey, updateValue1),
),
},
// ImportState testing
Expand All @@ -217,7 +251,7 @@ func TestAccResourceDefinition(t *testing.T) {
{
Config: tc.configUpdate(),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(tc.resourceAttrName, tc.resourceAttrNameUpdateKey, tc.resourceAttrNameUpdateValue2),
resource.TestCheckResourceAttr(tc.resourceAttrName, tc.resourceAttrNameUpdateKey, updateValue2),
),
},
// Delete testing automatically occurs in TestCase
Expand Down

0 comments on commit 8c5863a

Please sign in to comment.