The management of our application secrets (things such as service credentials and the secret_key_base) is belong to the most priority list. Rails 5.1 introduced Encrypted Secrets to help simplify the management of our application secrets. It will make 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.
Why encrypted secrets? Since Rails 4.1, the framework has given us the ability to centrally store secrets in the config/secrets.yml file. The glaring shortcoming of secrets.yml is that the file actually is in no way secure, and we cannot actually safely check it into version control with any production credentials. The convention for production credentials was always to load them within secrets.yml but from the host environment. Usually secrets file would end up looking something like this:
development: secret_key_base: 972888f3521e5c5ec8491cd3295e51af38fc93e059c1a00e8e03804288f64d77753b66a5108baaddfe6 some_api_key: 055ef473d6df1055 test: secret_key_base: 1d1be5ad7ea1e9d833e752a2de941217222fe9c6ea5467b9d63f69d38c8aa4c4219db9edc37d3b80fc4 some_api_key: 055ef473d6df1055 production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> some_api_key: <%= ENV["SOME_API_KEY"] %>
Rails 5.1+’s Encrypted Secrets feature can now keep production secrets in a second fully encrypted file (AES-256 by default), which is managed by the framework. Secrets from the encrypted secrets.yml.enc file are merged with secrets from the unencrypted secrets.yml file.
Getting started with Encrypted Secrets
To see this in action as of 5.1.0.beta1:
gem install rails -v 5.1.0.beta1 rails new testsekrets cd testsekrets
The generated scaffolding includes a config/secrets.yml for storing unencrypted secrets. Encrypted secrets is not set up by default, and in order to bootstrap it you need to run:
After running code, we will get :
This will drop a few files into our project tree:
- config/secrets.yml.key – contains the actual secret key used by the framework to AES-encrypt your secrets.
- config/secrets.yml.enc – the encrypted digest form of your (encrypted) secrets.
As per the instructions, we need store the one-time generated encryption key in 1password, or vault, or wherever just our team shares secrets. We should not lose the key. Generally, 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.
To edit your secrets, invoke the command:
EDITOR=subl bin/rails secrets:edit
EDITOR=vim bin/rails secrets:edit
The secrets:edit task will decrypt secrets and pop them open in editor where we can make changes. When we quit the editor, the framework will re-encrypt the secrets and overwrite the existing secrets.yml.enc file.
Usage in production
In production, Rails will look for the decryption key either in the environment variable RAILS_MASTER_KEY or in a local copy of the key file (config/secrets.yml.key). How we get the environment variable exposed to our application or how we inject the key file is a matter that is specific to our particular hosting and infrastructure management setup.