Terraform#
Terraform can be used to directly read and write secrets in Vault.
Warning
Caution should be taken as reading and writing secrets with terraform presents the security risk of secrets being included either in your configuration (terraform write resource) or in your terraform state file (terraform write resource, terraform read datasource). Security best practice would only be to use the terraform ephemeral vault_kv_secret_v2
datasource as the secret data will only be read at plan/apply time and not stored to the terraform state. Other examples have been included but should be evaluated to meet your team's security standards.
Note
For examples on how to configure a team's Vault namespace with terraform (i.e. policies, approles, etc.), see this example repository
Provider Authentication#
If you would like to use your own permissions in vault and have the vault CLI installed, the easiest way to get started is to run the following command which will generate a 1 hour token.
vault login --method=saml --namespace=admin
You can also set the VAULT_TOKEN
environment variable instead. With either of these methods, there is no need to specify the token
attribute in the Vault provider block.
Github Actions Provider Authentication#
If you would like to run terraform from a github action, you can use the hashicorp/vault-action
along with JWT auth to retrieve a token. Setting exportToken: true
will make the token available as the VAULT_TOKEN
environment variable for subsequent steps (terraform will automatically recognize).
- name: Authenticate to Vault
id: vault-auth
uses: hashicorp/vault-action@v3
with:
url: ${{ env.VAULT_ADDRESS }}
role: secm_repo_github_actions
namespace: ${{ env.NAMESPACE }}
path: jwt-github-actions
method: jwt
jwtGithubAudience: https://github.com/umn-<CESI>
exportToken: true
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: hashicorp/setup-terraform@v3
- name: Terraform Init
id: tf_init
run: >-
terraform init
- name: Terraform Apply
id: tf_apply
run: >-
terraform apply -auto-approve
Provider Config#
provider "vault" {
address = "https://hcp-vault-private-vault-fc507e0d.5d5b1f21.z1.hashicorp.cloud:8200/"
# Either specify the namespace here in the provider block or at the individual resource level, not both
namespace = "admin/<CESI>"
skip_child_token = true
}
terraform {
required_providers {
vault = {
source = "hashicorp/vault"
version = "5.0.0"
}
}
}
Ephemeral vault_kv_secret_v2 (read)#
See this article for more information on terraform ephemeral resources, or this article for the provider documentation.
# Ephemeral resource to read a secret from Vault
ephemeral "vault_kv_secret_v2" "example" {
mount = "secret"
name = "db/creds/myapp"
}
# Use the secret to create a database user (just an example)
resource "postgresql_role" "app_user" {
name = "app_user"
login = true
password = ephemeral.vault_kv_secret_v2.example.data["password"]
}
Datasource vault_kv_secret_v2 (read)#
Warning
See the warning at the top of the article for more information on why this datasource may not follow security best practices. This datasource has also been depreciated in favor of the ephemeral datasource.
data "vault_kv_secret_v2" "example" {
mount = "secret"
name = "db/creds/myapp"
}
Resource vault_kv_secret_v2 (write)#
Warning
See the warning at the top of the article for more information on why this resource may not follow security best practices.
resource "vault_kv_secret_v2" "example" {
mount = "secret"
name = "db/creds/myapp"
cas = 1
delete_all_versions = true
data_json = jsonencode(
{
zip = "zap",
foo = "bar"
}
)
custom_metadata {
max_versions = 5
data = {
foo = "vault@example.com",
bar = "12345"
}
}
}