Terraform
Write-only Arguments
Write-only arguments are managed resource attributes that are configured by practitioners but are not persisted to the Terraform plan or state artifacts. Write-only arguments are supported in Terraform 1.11 and later. Write-only arguments should be used to handle secret values that do not need to be persisted in Terraform state, such as passwords, API keys, etc. The provider is expected to be the terminal point for an ephemeral value, which should either use the value by making the appropriate change to the API or ignore the value. Write-only arguments can accept ephemeral values and are not required to be consistent between plan and apply operations.
General Concepts
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 cannot be used with set attributes, set nested 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
.- Provider developers do not need to explicitly set write-only argument values to
null
after using them as the plugin framework will handle the nullification of write-only arguments for all RPCs.
- Provider developers do not need to explicitly set write-only argument values to
Any value that is set for a write-only argument in the state or plan (during Plan Modification) by the provider will be reverted to
null
by plugin framework before the RPC response is sent to Terraform.Write-only argument values cannot produce a Terraform plan difference.
- This is because the prior state value for a write-only argument will always be
null
and the planned/final state value will also benull
, therefore, it cannot produce a diff on its own. - The one exception to this case is if the write-only argument is added to
requires_replace
during Plan Modification (i.e., using theRequiresReplace()
plan modifier), in that case, the write-only argument will always cause a diff/trigger a resource recreation.
- This is because the prior state value for a write-only argument will always be
Since write-only arguments can accept ephemeral values, write-only argument configuration values are not expected to be consistent between plan and apply.
Schema
An attribute can be made write-only by setting the WriteOnly
field to true
in the schema. Attributes with WriteOnly
set to true
must also have
one of Required
or Optional
set to true
. If a list nested, map nested, or single nested attribute has WriteOnly
set to true
, all child attributes must also have WriteOnly
set to true
.
A set nested block cannot have any child attributes with WriteOnly
set to true
. Computed
cannot be set to true for write-only arguments.
Schema example:
"password_wo": schema.StringAttribute{
Required: true,
WriteOnly: true,
},
Retrieving Write-only Values
Write-only argument values should be retrieved from the configuration instead of the plan. Refer to accessing values for more details on retrieving values from configuration.
PreferWriteOnlyAttribute Validators
The PreferWriteOnlyAttribute()
validators available in the terraform-plugin-framework-validators
Go module
can be used when you have a write-only version of an existing attribute, and you want to encourage practitioners to use the write-only version whenever possible.
The validator returns a warning if the Terraform client is 1.11 or above and the value of the existing attribute is non-null.
PreferWriteOnlyAttribute()
is available as a resource-level validator in the resourcevalidator
package or
as an attribute-level validator in the [type]validator
packages (i.e., stringvalidator
package)
Usage:
// Resource-level validator
// Used inside a resource.Resource type ConfigValidators method
_ = []resource.ConfigValidator{
// Throws a warning diagnostic encouraging practitioners to use
// password_wo if password has a known value
resourcevalidator.PreferWriteOnlyAttribute(
path.MatchRoot("password"),
path.MatchRoot("password_wo"),
),
}
// Attribute-level validator
// Used within a Schema method of a Resource
_ = schema.Schema{
Attributes: map[string]schema.Attribute{
"password": schema.StringAttribute{
Optional: true,
Validators: []validator.String{
// Throws a warning diagnostic encouraging practitioners to use
// password_wo if password has a known value.
stringvalidator.PreferWriteOnlyAttribute(
path.MatchRoot("password_wo"),
),
},
},
"password_wo": schema.StringAttribute{
WriteOnly: true,
Optional: true,
},
},
}
resource "example_db_instance" "ex" {
username = "foo"
password = "bar" # returns a warning encouraging practitioners to use `password_wo` instead.
}
Best Practices
Since write-only arguments have no prior values, user intent or value changes cannot be determined with a write-only argument alone. To determine when to use/not use a write-only argument value in your provider, we recommend one of the following:
- Pair write-only arguments with a configuration attribute (required or optional) to “trigger” the use of the write-only argument
- For example, a
password_wo
write-only argument can be paired with a configuredpassword_wo_version
attribute. When thepassword_wo_version
is modified, the provider will send thepassword_wo
value to the API.
- For example, a
- Use a keepers attribute (which is used in the Random Provider) that will take in arbitrary key-pair values. Whenever there is a change to the
keepers
attribute, the provider will use the write-only argument value. - Use the resource's private state to store secure hashes of write-only argument values, the provider will then use the hash to determine if a write-only argument value has changed in later Terraform runs.