Search code examples
terraformterraform-provider-gcp

How do I pass a data source value to a .tfvars file value?


I'm trying to create a secret on GCP's Secret Manager.

The secret value is coming from Vault (HCP Cloud).

How can I pass a value of the secret if I'm using a .tfvars file for the values?

Creating the secret without .tfvars works. Other suggestions rather than data source are welcomed as well. I saw that referring locals isn't possible as well inside tfvars.

vault.tf:

provider "vault" {
  address = "https://testing-vault-public-vault-numbers.numbers.z1.hashicorp.cloud:8200"
  token   = "someToken"
}

data "vault_generic_secret" "secrets" {
  path = "secrets/terraform/cloudcomposer/kafka/"
}

main.tf:

resource "google_secret_manager_secret" "connections" {
  provider  = google-beta
  count     = length(var.connections)
  secret_id = "${var.secret_manager_prefix}-${var.connections[count.index].name}"
  replication {
    automatic = true
  }
}

resource "google_secret_manager_secret_version" "connections-version" {
  count       = length(var.connections)
  secret      = google_secret_manager_secret.connections[count.index].id
  secret_data = var.connections[count.index].uri
}

dev.tfvars:

image_version                     = "composer-2-airflow-2.1.4"
env_size                          = "LARGE"
env_name                          = "development"
region                            = "us-central1"
network                           = "development-main"
subnetwork                        = "development-subnet1"
secret_manager_prefix = "test"
connections = [
  { name = "postgres", uri = "postgresql://postgres_user:[email protected]:5432/"}, ## This one works
  { name = "kafka", uri = "${data.vault_generic_secret.secrets.data["kafka_dev_password"]}" 
]

Getting:

Error: Invalid expression on ./tfvars/dev.tfvars line 39: Expected the start of an expression, but found an invalid expression token.

Thanks in advance.


Solution

  • Values in the tfvars files have to be static, i.e., they cannot use any kind of a dynamic assignment like when using data sources. However, in that case, using local variables [1] should be a viable solution:

    locals {
      connections = [
        {
          name = "kafka",
          uri = data.vault_generic_secret.secrets.data["kafka_dev_password"]
        }
      ]
    }
    

    Then, in the resource you need to use it in:

    resource "google_secret_manager_secret" "connections" {
      provider  = google-beta
      count     = length(local.connections)
      secret_id = "${var.secret_manager_prefix}-${local.connections[count.index].name}"
      replication {
        automatic = true
      }
    }
    
    resource "google_secret_manager_secret_version" "connections-version" {
      count       = length(local.connections)
      secret      = google_secret_manager_secret.connections[count.index].id
      secret_data = local.connections[count.index].uri
    }
    

    [1] https://developer.hashicorp.com/terraform/language/values/locals