DopplerHQ / terraform-provider-doppler

Apache License 2.0
23 stars 9 forks source link

BUG: provider erroneously assumes that an empty secret value indicates lack of access. #77

Closed rtrox closed 8 months ago

rtrox commented 9 months ago

When managing secrets, if terraform attempts to set a value for a secret that exists, but has an empty value (for example, when creating a resource for a new environment in an existing project), having a nil value for that secret leads the terraform provider to believe it doesn't have access to retrieve it, rather than correctly realizing the secret simply has an empty value.

Reproduction:

  1. Create a new environment in an existing project.
  2. Create a secret in an existing environment via terraform.
  3. Change the secret to point to the new project instead (note that when I did this, I had separate tokens for each of the two projects, with separate terraform configs).
  4. Run terraform apply.

Example of the error:

╷
│ Error: One or more secret fields are restricted: [raw computed]. You must use a service account or service token to manage these resources. Otherwise, Terraform cannot fetch these restricted secrets to check the validity of their state.
│
│   with doppler_secret.cnpg_backup_key_bitty,
│   on b2_bitty_cnpg_backup_bucket.tf line 12, in resource "doppler_secret" "cnpg_backup_key_bitty":
│   12: resource "doppler_secret" "cnpg_backup_key_bitty" {
│
╵

Remediations attempted:

Successful remediation: To fix this broken state, I had to set a bogus password value "asdf" through the UI, and then re-run terraform apply.

Provider Configs:

variable "doppler_token" {
  type = string
}

provider "doppler" {
  doppler_token = var.doppler_token
}

provider "doppler" {
  doppler_token = data.doppler_secrets.tf_read.map.DOPPLER_BITTY_WRITE_TOKEN
  alias         = "bty_write"
}

provider "doppler" {
  doppler_token = data.doppler_secrets.tf_read.map.DOPPLER_CHONGUS_WRITE_TOKEN
  alias         = "cho_write"
}

data "doppler_secrets" "tf_read" {
  project = "tf-at-home"
  config  = "prd"
}

relevant secret entry:

resource "doppler_secret" "cnpg_backup_key_bitty" {
  provider = doppler.bty_write
  project  = "k8s-at-home"
  config   = "bty"
  name     = "CNPG_BACKUP_BACKBLAZE_BUCKET"
  value = jsonencode({
    "application_key_id" = module.bb_bucket_k8s_bitty_rtrox_io_cnpg_backup.application_keys["k8s-bitty-rtrox-io-cnpg-backup"].application_key_id,
    "application_key"    = module.bb_bucket_k8s_bitty_rtrox_io_cnpg_backup.application_keys["k8s-bitty-rtrox-io-cnpg-backup"].application_key
    "endpoint"           = module.bb_bucket_k8s_bitty_rtrox_io_cnpg_backup.bucket.endpoint
    "bucket"             = module.bb_bucket_k8s_bitty_rtrox_io_cnpg_backup.bucket.bucket_name
  })
}

This is the relevant code, it seems to naively assume that a nil value means it doesn't have access: https://github.com/DopplerHQ/terraform-provider-doppler/blob/2407bf224c49e7e3a509735cc2d4b95e34074c14/doppler/resource_secret.go#L119-L132

nmanoogian commented 9 months ago

Thanks for reporting this, @rtrox and I appreciate the detail! It looks like we're missing ForceNew flags for the doppler_secret resource. A doppler_secret can't be moved from one project or config to another, it must be deleted and recreated. We use null values in the fetch secrets API to indicate that a secret's value is restricted but we should never have attempted to fetch the secret if it doesn't exist.

I'll get the fix up shortly 👍 Thanks again!