terraform icon indicating copy to clipboard operation
terraform copied to clipboard

Ability to not store certain attributes in TF state

Open mbrancato opened this issue 3 years ago • 10 comments

Terraform state can contain secrets, this is well documented. But sometimes, there are situations where I absolutely just don't want Terraform to retain the secret value.

Current Terraform Version

Terraform v1.1.5
on darwin_amd64

Use-cases

Let's assume that TF is run as a service account which has the ability to create resources, and make some modifications to that resource. And let's assume that resources is a cloud database as well. The TF service account can create and set the initial user of the cloud database instance, but it doesn't immediately have access to the data in the database.

Again, let's assume the IAM permissions on the TF service account let it create the DB and initial user, but do not let it update the password for the DB.

What I would like is a way to allow TF to bootstrap creating the DB, setting the initial static admin username and password, passing those same credentials on to be stored in HashiCorp Vault. This could be static KV secrets or the database secret engine used to create dynamic credentials by policy. TF would read a random password from the Vault sys/policies/password/*/generate path, and use that to set a random password for the admin user. In the end, the TF state file would not have stored the values from the Vault data source, or the cloud database resource in the TF state.

Note: this assumes the TF user knows that they need to ignore changes and otherwise compensate for the fact that the IAM permissions may not allow for updating the password and/or the random password would change on each TF run.

Attempted Solutions

I tried using lifecycle.ignore_changes - this works from a user experience perspective in that it will bootstrap the user and not change it on subsequent runs, but it still stores the actual password in the TF state.

resource "vault_generic_secret" "db_password" {
  path = "secret/db"

  data_json = jsonencode({ password = data.vault_generic_secret.random_pw.data.password })
  disable_read = true

  lifecycle {
    ignore_changes = [
      data_json
    ]
  }
}

Proposal

A setting, similar to sensitive_attributes, that tells TF to store the empty / zero version of that attribute's type in the state and not the actual value used at runtime.

Unlike sensitive_attributes, this would need to be configurable by the user, similar to lifecycle.ignore_changes.

resource "vault_generic_secret" "db_password" {
  path = "secret/db"

  data_json = jsonencode({ password = data.vault_generic_secret.random_pw.data.password })
  disable_read = true

  lifecycle {
    ignore_changes = [
      data, data_json
    ]
    do_not_store = [
      data, data_json
    ]
  }
}

This will cause config drift for user's who enable this and do not have a full grasp of where it is used.

mbrancato avatar Feb 03 '22 19:02 mbrancato