2017-02-24

Our applications need access to secrets - passwords, tokens, special URLs. Platforms like Cloud Foundry and Heroku have made environment variables easy to use, and so we use them. Albeit they are typically not as secretive as we might like.

Here's a one-liner to look up every secret that you have access to across all applications on a single Cloud Foundry platform:

Sure, you have authority to look at all those secrets. But should it really be that easy? It's like being able to open every safe in a vault simultaneously. Do you ever have a real reason to do it? Perhaps there are really only downsides from it being abused?

The next version of Ruby on Rails 5.1 will make it easier to keep secrets more secret: developers can encrypt secrets inside the source code so that they are only available inside the running application process.

To see this in action as of 5.1.0.beta1:

The generated scaffolding includes a config/secrets.yml for storing unencrypted secrets. That is, from now on you would not use this file for production secrets.

Secretive secrets are not enabled by default. Turn them on with:



As per the instructions, store the one-time generated encryption key in 1password, or vault, or wherever your team shares secrets:



As per the instructions, don't lose this key.

Developers of the application can either:

Place this key in config/secrets.yml.key; or

Set env var RAILS_MASTER_KEY to this value

It is the latter that we will also use when deploying to production with Cloud Foundry below.

The file config/secrets.yml.enc is like a little encrypted database of secrets that you can safely commit with the rest of your source code.

To edit it:

The root key is scopes the RAILS_ENV environment:

To access our new production secret, use Testsekrets::Application.secrets. Try the Rails console:

There are our additional secrets: :sharedkey and :mykey.

The additional keys api_key and secret_key_base were merged in from the unencrypted/human readable config/secrets.yml that was created by rails new scaffolding.

In development, you will get different secrets:

You don't see :sharedkey above because the config/environments/development.rb does not have the following line, but config/environments/production.rb does:

Deploying to Cloud Foundry

Now, instead of storing secrets in environment variables, we have two changes to encrypt them:

Use bin/rails secrets:edit to store the secrets; and access them within your application via Testsekrets::Application.secrets[key]

Pass the secret-keeping encryption key from above via RAILS_MASTER_KEY:

NOTE: at the time of writing I wasn't sure what $SECRET_KEY_BASE used for; Rafael helped me out on Twitter. I've updated the command above.

@drnic secret_key_base is to encrypt session and is there since rails 4, so it is not related to the new secrets configuration.

— Rafael França (@rafaelfranca) February 24, 2017

@drnic rake secret (I think it is that) generates a valid string for that config.

— Rafael França (@rafaelfranca) February 24, 2017

Bonus

If you have Vault in production, then you can also share secrets with Cloud Foundry applications using a Vault service broker, such as https://www.hashicorp.com/blog/cloud-foundry-vault-service-broker/

Show more