From b7f3e6fe032c4f302abaf31fb3060df8eee303d8 Mon Sep 17 00:00:00 2001 From: Selena Goods Date: Tue, 18 Feb 2025 18:51:35 -0500 Subject: [PATCH] helper/schema: Add validation to prevent write-only attributes in set nested blocks (#1427) * Add validation to prevent write-only attributes in set nested blocks * Add changelog entries --- .changes/unreleased/BUG FIXES-20250218-172440.yaml | 6 ++++++ .changes/unreleased/NOTES-20250218-172625.yaml | 5 +++++ helper/schema/schema.go | 8 +++++++- helper/schema/schema_test.go | 8 ++++---- .../docs/plugin/sdkv2/resources/write-only-arguments.mdx | 5 ++++- website/docs/plugin/sdkv2/schemas/schema-behaviors.mdx | 3 ++- 6 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 .changes/unreleased/BUG FIXES-20250218-172440.yaml create mode 100644 .changes/unreleased/NOTES-20250218-172625.yaml diff --git a/.changes/unreleased/BUG FIXES-20250218-172440.yaml b/.changes/unreleased/BUG FIXES-20250218-172440.yaml new file mode 100644 index 0000000000..8b8d7eb3e0 --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20250218-172440.yaml @@ -0,0 +1,6 @@ +kind: BUG FIXES +body: 'helper/schema: Fixed bug that allowed write-only attributes within set nested blocks. +Any attribute within a set nested block with `WriteOnly` set to `true` will now trigger an error message.' +time: 2025-02-18T17:24:40.023079-05:00 +custom: + Issue: "1427" diff --git a/.changes/unreleased/NOTES-20250218-172625.yaml b/.changes/unreleased/NOTES-20250218-172625.yaml new file mode 100644 index 0000000000..87ae830373 --- /dev/null +++ b/.changes/unreleased/NOTES-20250218-172625.yaml @@ -0,0 +1,5 @@ +kind: NOTES +body: Write-only attribute support is in technical preview and offered without compatibility promises until Terraform 1.11 is generally available. +time: 2025-02-18T17:26:25.941391-05:00 +custom: + Issue: "1375" diff --git a/helper/schema/schema.go b/helper/schema/schema.go index 0c779b31de..ea6cd768d1 100644 --- a/helper/schema/schema.go +++ b/helper/schema/schema.go @@ -975,7 +975,13 @@ func (m schemaMap) internalValidate(topSchemaMap schemaMap, attrsOnly bool) erro case *Resource: attrsOnly := attrsOnly || v.ConfigMode == SchemaConfigModeAttr - if v.Computed && schemaMap(t.SchemaMap()).hasWriteOnly() { + blockHasWriteOnly := schemaMap(t.SchemaMap()).hasWriteOnly() + + if v.Type == TypeSet && blockHasWriteOnly { + return fmt.Errorf("%s: Set Block type cannot contain WriteOnly attributes", k) + } + + if v.Computed && blockHasWriteOnly { return fmt.Errorf("%s: Block types with Computed set to true cannot contain WriteOnly attributes", k) } diff --git a/helper/schema/schema_test.go b/helper/schema/schema_test.go index d0fa1a9fdf..988e43ea02 100644 --- a/helper/schema/schema_test.go +++ b/helper/schema/schema_test.go @@ -5303,7 +5303,7 @@ func TestSchemaMap_InternalValidate(t *testing.T) { }, true, }, - "Set configuration block nested attribute with WriteOnly set returns no errors": { + "Set configuration block nested attribute with WriteOnly set returns error": { map[string]*Schema{ "config_block_attr": { Type: TypeSet, @@ -5319,7 +5319,7 @@ func TestSchemaMap_InternalValidate(t *testing.T) { }, }, }, - false, + true, }, "List configuration block with ConfigModeAttr set, sub block nested attribute with WriteOnly set returns no errors": { map[string]*Schema{ @@ -5350,7 +5350,7 @@ func TestSchemaMap_InternalValidate(t *testing.T) { false, }, - "Set configuration block with ConfigModeAttr set, sub block nested attribute with WriteOnly set returns no errors": { + "Set configuration block with ConfigModeAttr set, sub block nested attribute with WriteOnly set returns error": { map[string]*Schema{ "block": { Type: TypeSet, @@ -5376,7 +5376,7 @@ func TestSchemaMap_InternalValidate(t *testing.T) { }, }, }, - false, + true, }, "List computed block nested attribute with WriteOnly set returns error": { map[string]*Schema{ diff --git a/website/docs/plugin/sdkv2/resources/write-only-arguments.mdx b/website/docs/plugin/sdkv2/resources/write-only-arguments.mdx index 1ed7faa6cf..f4a82ad436 100644 --- a/website/docs/plugin/sdkv2/resources/write-only-arguments.mdx +++ b/website/docs/plugin/sdkv2/resources/write-only-arguments.mdx @@ -16,7 +16,9 @@ which should either use the value by making the appropriate change to the API or The following are high level differences between `Required`/`Optional` arguments and write-only arguments: -- Write-only arguments can accept ephemeral and non-ephemeral values +- Write-only arguments can accept ephemeral and non-ephemeral values. + +- Write-only arguments cannot be used with set attributes and set nested blocks. - Write-only argument values are only available in the configuration. The prior state, planned state, and final state values for write-only arguments should always be `null`. @@ -51,6 +53,7 @@ write-only arguments should always be `null`. - Cannot be used when `Default` is `specified` - Cannot be used with `DefaultFunc` - Cannot be used with aggregate schema types (e.g. `typeMap`, `typeList`, `typeSet`), but non-computed nested block types can contain write-only arguments. +- Cannot be used within a set nested block type. ## Retrieving Write-only Values diff --git a/website/docs/plugin/sdkv2/schemas/schema-behaviors.mdx b/website/docs/plugin/sdkv2/schemas/schema-behaviors.mdx index 9e98a4abbb..30ac5262d9 100644 --- a/website/docs/plugin/sdkv2/schemas/schema-behaviors.mdx +++ b/website/docs/plugin/sdkv2/schemas/schema-behaviors.mdx @@ -213,7 +213,8 @@ resource "example_instance" "ex" { - Cannot be used when `ForceNew` is `true` - Cannot be used when `Default` is `specified` - Cannot be used with `DefaultFunc` -- Cannot be used with aggregate schema types (e.g. `typeMap`, `typeList`, `typeSet`), but non-computed nested block types can contain write-only arguments. +- Cannot be used with aggregate schema types (e.g. `typeMap`, `typeList`, `typeSet`), but non-computed list nested block types can contain write-only arguments. +- Cannot be used within a set nested block type `WriteOnly` should be used for arguments that handle secret values that do not need to be persisted in Terraform plan or state, such as passwords, API keys, etc. Write-only argument values are not sent to Terraform and do not