Secrets Management for Terraform
To help you manage secrets in Terraform, we’ve built a Terraform provider and a state backend. For a detailed use case, check out the announcement blog post.
In this step-by-step guide, you’ll learn how to keep hardcoded secrets out of Terraform code and securely share your .tfstate
file.
For full reference, check out the GitHub repository and the reference documentation.
Before you begin
Before you start using SecretHub with Terraform, make sure you have completed the following steps:
- Set up SecretHub on your workstation.
Getting help
Come chat with us on Discord or email us at support@secrethub.io
Step 1: Install the provider
Registry install (Terraform v0.13)
To install this provider, add the following code to your Terraform configuration and run terraform init
:
terraform {
required_providers {
secrethub = {
source = "secrethub/secrethub"
version = ">= 1.2.0"
}
}
}
You can verify the downloaded provider is signed by us by checking if the key ID in the output of terraform init
matches B7F647C8C55CB6D5
.
Manual install (Terraform v0.12 and below)
Select your operating system and architecture below to find out how to install the SecretHub Terraform Provider.
Execute the following in your terminal to install the latest version of the Terraform Provider on Linux:
amd64
mkdir -p ~/.terraform.d/plugins && curl -SfL https://github.com/secrethub/terraform-provider-secrethub/releases/latest/download/terraform-provider-secrethub-linux-amd64.tar.gz | tar zxf - -C ~/.terraform.d/plugins
x86/i386
mkdir -p ~/.terraform.d/plugins && curl -SfL https://github.com/secrethub/terraform-provider-secrethub/releases/latest/download/terraform-provider-secrethub-linux-386.tar.gz | tar zxf - -C ~/.terraform.d/plugins
Execute the following in your terminal to install the latest version of the Terraform Provider on MacOS:
mkdir -p ~/.terraform.d/plugins && curl -SfL https://github.com/secrethub/terraform-provider-secrethub/releases/latest/download/terraform-provider-secrethub-darwin-amd64.tar.gz | tar zxf - -C ~/.terraform.d/plugins
Execute the following in PowerShell to install the latest version of the Terraform Provider on Windows:
amd64
$tmp = "$(New-TemporaryFile).zip"; Invoke-WebRequest -OutFile $tmp https://github.com/secrethub/terraform-provider-secrethub/releases/latest/download/terraform-provider-secrethub-windows-amd64.zip; $tmp | Expand-Archive -Force -DestinationPath "${env:APPDATA}\terraform.d\plugins" ; $tmp | Remove-Item
x86/i386
$tmp = "$(New-TemporaryFile).zip"; Invoke-WebRequest -OutFile $tmp https://github.com/secrethub/terraform-provider-secrethub/releases/latest/download/terraform-provider-secrethub-windows-386.zip; $tmp | Expand-Archive -Force -DestinationPath "${env:APPDATA}\terraform.d\plugins" ; $tmp | Remove-Item
Go to the releases page on GitHub to fetch the latest releases of the Terraform Provider.
You can manually install it by placing the content of the archive in %APPDATA%\terraform.d\plugins
for Windows and ~/.terraform.d/plugins
for all other operating systems.
For help on manually installing Terraform Providers, please refer to the official Terraform documentation.
Configure the provider
With the provider installed, you can configure it in your project by passing in a credential for your SecretHub account.
provider "secrethub" {
credential = file("~/.secrethub/credential")
}
You can also source the credential from the SECRETHUB_CREDENTIAL
environment variable.
If upon signup you’ve chosen to lock your credential with a passphrase, you need to set the credential_passphrase
field on the provider.
You can use a Terraform variable for this and let it prompt on every run:
variable "secrethub_passphrase" {}
provider "secrethub" {
credential = file("~/.secrethub/credential")
credential_passphrase = var.secrethub_passphrase
}
With the provider configured, you can run:
terraform init
That’s it. The SecretHub Terraform provider is now properly setup and ready to be used.
Step 2: Write secrets
Before writing secrets, make sure you have created a repo and the directories you’re going to be adding secrets to, either in your shared organization workspace or in your personal workspace.
In the examples throughout this guide, we’re using the your-username/start
as the repo name.
Make sure to change that with yours.
To create a secret, you can use the secrethub_secret
resource. You can specify a value directly or you can auto-generate a value:
resource "secrethub_secret" "db_password" {
path = "your-username/start/dev/db/password"
generate {
length = 22
use_symbols = true
}
}
resource "secrethub_secret" "db_user" {
path = "your-username/start/dev/db/user"
value = "mydbuser"
}
Run terraform apply
and your secrets are now on SecretHub!
You can use them now to create other resources:
resource "heroku_app" "your_app" {
name = "your-app"
region = "us"
sensitive_config_vars {
DB_PASSWORD = secrethub_secret.db_password.value
DB_USER = secrethub_secret.db_user.value
}
}
Or, for the purposes of this tutorial, just print their values:
output "db_password" {
value = secrethub_secret.db_password.value
}
output "db_user" {
value = secrethub_secret.db_user.value
}
Now, let’s say the requirements for your password strength change: the password needs to be at least 28 characters long.
You can simply change the length
field and Terraform will automatically generate a new password for you and propagate it to where it’s used throughout your project:
resource "secrethub_secret" "db_password" {
path = "your-username/start/dev/db/password"
generate {
length = 28
}
}
You can also manually tell Terraform to generate a new value for the secret, by using the taint
command:
terraform taint secrethub_secret.db_password && terraform apply
Path redundancy
To avoid redundancy in secret paths throughout your secret resources, you can use Terraform variables and/or local blocks:
variable "env" {
default = "dev"
}
locals {
secrethub_dir = "your-username/start/${var.env}"
}
resource "secrethub_secret" "db_password" {
path = "${local.secrethub_dir}/db/password"
generate {
length = 22
use_symbols = true
}
}
resource "secrethub_secret" "db_user" {
path = "${local.secrethub_dir}/db/user"
value = "mydbuser"
}
Step 3: Read external secrets
To read a secret that has been created outside the scope of this Terraform project (e.g. through the CLI or in a different Terraform project), you can use the secrethub_secret
data source.
You only need to specify the path of the secret:
data "secrethub_secret" "db_password" {
path = "${local.secrethub_dir}/db/password"
}
data "secrethub_secret" "db_user" {
path = "${local.secrethub_dir}/db/user"
}
Just like the secret resource, you can use the value of the secret data source throughout your project by referencing the value
field.
resource "heroku_app" "your_app" {
name = "your-app"
region = "us"
sensitive_config_vars {
DB_PASSWORD = data.secrethub_secret.db_password.value
DB_USER = data.secrethub_secret.db_user.value
}
}
By default the data source retrieves the latest version of your secret. To instead get a specific version of a secret, just add the version number to the path:
data "secrethub_secret" "db_password_version_1" {
path = "${local.secrethub_dir}/db/password:1"
}
Step 4: Import an existing secret
If you already have some secrets on SecretHub and you would like to start managing these using Terraform, you’re going to need them to be added to your .tfstate
.
For this you can leverage Terraform’s import command.
First declare the resource in your Terraform project:
resource "secrethub_secret" "db_password" {
path = "${local.secrethub_dir}/db/password"
}
Then, instead of running terraform apply
, run the import
command, linking the secret on SecretHub to the secrethub_secret
resource you’ve just declared:
terraform import secrethub_secret.db_password your-username/start/dev/db/password
The secret has now beed added to your .tfstate
.
If you decide to remove the resource from your configuration, it will now also delete it on SecretHub.
Backend for your .tfstate
Not only does SecretHub integrate with Terraform through a provider, it can also serve as a secure backend for your .tfstate
.
Because it simply treats your .tfstate
like any other secret in SecretHub, you get all the security features that your .tfstate
deserves without any additional setup.
To use SecretHub as a state backend, you need to run the SecretHub HTTP Proxy. You can run it as a Docker container:
docker run -it -p 127.0.0.1:8080:8080 --name secrethub -v $HOME/.secrethub:/secrethub secrethub/http-proxy
For more installation options, check out the GitHub page.
Then add the following backend configuration to your Terraform project:
terraform {
backend "http" {
address = "http://localhost:8080/v1beta/secrets/raw/your-username/start/terraform.tfstate"
}
}
This will write your .tfstate
to SecretHub at path your-username/start/terraform.tfstate
.
To start the state migration, run:
terraform init
Terraform will now prompt to migrate your local .tfstate
to SecretHub.
Afterwards, Terraform clears the local state, leaving only a local backup copy present.
You can verify that the state got migrated correctly by running:
terraform state pull
Alternatively, verify it using the SecretHub CLI:
secrethub read your-username/start/terraform.tfstate
You can then safely delete the remaining .tfstate.backup
file.
Next steps
You now know all there is to know to manage secrets in Terraform with the SecretHub integration.
To learn more about SecretHub, check out these resources:
- Use a shared organization workspace instead of your personal developer account.
- Create a non-human service account to run Terraform in automation (e.g. CI)
Finally, to get your account back to a clean state, you can run:
terraform destroy
And you can remove the start
repository on SecretHub used in this guide:
secrethub repo rm your-username/start
And you’re done. Happy coding!