Use Vault for Local Dev Secrets


This is a way to use Vault to provide app secrets for local dev.

Why Use Vault Locally

You want to use Vault in your local dev environment for a couple main reasons:

  1. You'll have a secure way to share secrets.
  2. It'll be easier to keep secrets up to date.
  3. It'll make your local env match your production environment more.

Local-specific Vault Problem

In your deployed environments, presumably, Vault just exists. There's an agent on the machine, and you can access secrets through it.

You need to set up something similar for local dev. Here's a potential solution:

Install Vault Client Locally

Hashicorp has some good OS-specific Vault install instructions. Go follow one of those setups.

Verify the installation by running:

vault

You should get a nice "Usage" output.

Find Vault Server Location

Next, you'll need to find your company's Vault server address. It'll probably look something like:

https://somesubdomain.vault.somehash.aws.hashicorp.cloud:8200/

Set VAULT_ADDR

Once you have the server address in hand, set that in your environment:

export VAULT_ADDR=https://somesubdomain.vault.somehash.aws.hashicorp.cloud:8200/

The vault client cli needs this for the next step.

Log in to Vault

Now run:

vault login

This will ask you for a Token. To find that token, log in to the Vault server at the address above in your browser and use the Vault web ui. Once logged in using your authentication creds, you'll see a Profile button in the top left. Clicking that will reveal a dropdown. You want to select the dropdown option "Copy token". Paste that into the prompt shown by vault login, above.

Access to Secrets

Now your vault client cli has access to the secrets in Vault. You can retrieve one by specifying the namespace and the path to the secret:

vault kv get --namespace=admin/dev -field=EXAMPLE_API_KEY secret/my-proj/api-creds

If the secret exists, it'll be returned in stdout.

Of course, this will already have to have been entered into Vault in order to retrieve it. That's not covered here. I've done that previously via the web ui.

Also note that this command is using a dev/ namespace. This implies that there's a separate namespace for dev, distinct from any others that might exist, like stage/ or prod/. Your setup my vary.

Make Secrets Available to Dev Server

As we've observed, local dev is a bit different than a deployed environment. If, for instance, my dev app server reads a .env.local for its environment variables, then I'd like Vault to be able to shovel those secret values into that file, upon my request.

To that end, I write an env.local.sh script:

#!/bin/bash
#
# This file is committed. .env.local (because it will contain plain text secrets) is not.

set -e

export VAULT_ADDR=https://somesubdomain.vault.somehash.aws.hashicorp.cloud:8200/

get_cred () {
  field=$1
  vault kv get --namespace=admin/dev -field=${field} secret/my-proj/api-creds
}

echo "EXAMPLE_API_HOST=https://localhost:4444" >> .env.local
echo "EXAMPLE_API_KEY=$(get_cred EXAMPLE_API_KEY)" >> .env.local

Note that this script also includes non-secret environment variables, which can be committed in plaintext. They're here so they can be managed in one place.

Now, every time I want to refresh my env vars from Vault, I run the script: ./env.local.sh, and now my .env.local file is updated with the latest secrets. And when I start my dev app server, it reads that file, and I have secrets for local dev.

How do you do it? How would you streamline this process?