Vault_generic_secret and variables in json?

Hi all,

So I am configuring Vault with Terraform and using vault_generic_secret to enter my secrets. The issue is that I’m using gitlab to do this as I don’t want the secrets in my raw code of course. I’m using gitlab variables to define the secrets. Looks like the only way to enter secrets is through json

So here is my resource:

resource "vault_generic_secret" "secret" {
  path = "kv/mysecret"
  depends_on = [vault_mount.kv2]

  data_json = <<EOT
{
  "username":   "$my_user",
  "password":   "$my_password"
}
EOT
}

The secret values I get from this are $my_user $my_password, so it’s not evaluating the variables. I’ve even tried curly braces around the variable names with no luck.

There has to be a simple solution for this that I am ignorant of :slight_smile:

thanks for any input

Hi @tnr,

When building JSON values in Terraform I recommend always using the jsonencode function, rather than string concatenation using templates, because then you can just construct a suitable data structure using normal Terraform expressions and let Terraform be the one responsible for making it valid JSON syntax.

In your case, that would look something like the following:

variable "username" {
  type = string
}

variable "password" {
  type      = string
  sensitive = true
}

resource "vault_generic_secret" "secret" {
  depends_on = [vault_mount.kv2]

  path = "kv/mysecret"
  data_json = jsonencode({
    username = var.username
    password = var.password
  })
}

You could then arrange for your GitLab task to pass in the values to those variables. One relatively-easy way to do that is to set environment variables whose names start with TF_VAR_, which in this case would be TF_VAR_username and TF_VAR_password (case sensitive), which Terraform can then use as values for those two input variables I declared in the example above.

With that said, if you intend to populate Vault using Terraform please be sure to read the guidelines and recommendations in the hashicorp/vault provider documentation to understand what additional steps you might need to take in order to protect the sensitive values. The sensitive = true in the example above is only for hiding values in the Terraform UI and so the values you specify for password will still be included in clear text in the state snapshots produced by this configuration and in saved plan files, if you use terraform plan -out=tfplan or similar to carry a plan between two workflow steps as an artifact.

Thank you for the reply, I was actually working on what you replied with as I’ve done much Googling this morning piecing stuff together :slight_smile: jsonencode was not part of that but that looks much cleaner and I will implement that.

I am torn on this a bit as it seems to negate what Vault was designed to do, be a place to store secrets among other things and not have them living anywhere else. Well, now they are in Gitlab as variables as well as any terraform artifacts, but not having its config codified can lead to other issues as well. So yeah, I’m a bit torn on this solution.

Indeed… while I can’t give you specific security advice (what’s appropriate will always depend on your specific situation and your threat model), I will say that when folks use the hashicorp/vault provider to populate Vault it’s normally for secrets that were generated as part of Terraform’s normal work, such as saving a key that was dynamically generated and returned as part of creating some other object.

Using Terraform in this way to place static credentials into Vault is not so conventional, particularly if part of getting there is to save them as variables in your CI system. If you’re going to manually configure the static secrets somewhere, it could be reasonable for that “somewhere” to be Vault itself directly, rather than a CI process that writes to Vault.

Of course, there can be advantages and disadvantages on both sides, so the final decision is ultimately yours to make.