A simple, standard, open pattern for safely using secrets from secure stores like Vault in your applications.
Applications need secrets—API keys for integrated services, database credentials, etc. With any luck, you likely stopped including these secrets in your codebase long ago. If you follow the twelve-factor app pattern, you probably store passwords or other secrets in the environment and safely reference these environment variables in your app code.
But how do the secrets get put in the environment? In simple cases, this can be part of a deploy process. But once your application deployment becomes more complex, it's much easier to store passwords in a central, secure store such as Hashicorp's Vault or Square's Keywhiz.
Now you have a new problem: should you burden all of your applications with Vault-specific code? What if you switch backing stores, or use different methods in your development environment?
The solution is to relay secrets from the store to the application in a standard way. Introducing the Secretfile:
# Secretfile
AWS_ACCESS_KEY_ID secrets/services/aws:id
AWS_ACCESS_KEY_SECRET secrets/services/aws:secret
PG_USERNAME postgresql/$VAULT_ENV/creds/readonly:username
PG_PASSWORD postgresql/$VAULT_ENV/creds/readonly:password
In the AWS
examples, we're specifying that the secrets named on the left should be drawn from the corresponding Vault path on the right. In the PG
examples, we show that Secretfile consumers will interpolate environment variables ($VAR
or ${VAR}
) as needed.
Secretfile
in your application directory following the format above.VAULT_ADDR
environment variable and a token in either VAULT_TOKEN
or ~/.vault-token
.$ credentials-to-env myprogram arg1 arg2
credentials::var("TOP_SECRET").unwrap();
SecretGarden.add_backend :vault
s3 = AWS::S3.new access_key_id: SecretGarden.fetch('AWS_ACCESS_KEY_ID')
Faraday leads the Secretfile project and sponsors credentials-to-env, credentials, and SecretGarden.