Home /

Notes to self /

Rails from secrets to credentials

Rails from secrets to credentials

It's a 6 minute read

The Rails 5.2 release brought with it a new way of handling secret keys. So in this now I’m going to explain how to update your Rails app and how to implement Credentials for storing information like API keys, passwords to 3rd party tools, randomly-generated secrets, or encryption algorithms.

In Rails 5.1 and earlier, the best practice for storing private data was to use a .secrets file that assigned the data to constants used elsewhere in the app, and to make sure this file was listed in your .gitignore so that the information was never made publicly available on GitHub (or other repos).

The problems with this were that

Now with Rails 5.2 and later, apps come with a master.key file that’s automatically referenced in the .gitignore. This key is used to decrypt your new credentials.yml.enc file, which can and should be checked into your version control. The key and the credentials file come as a set. The private data in credentials.yml.enc is encrypted but can be edited and saved directly when you open and decrypt the file from command line.

First things first

First of all, you will need to update your Rails version. There are two options here: a simple update of just your Rails version, or a deeper update to rewrite your configuration as though you’d just created a fresh app.

The simple version is to copy the text in the GEMFILE section on the right from rubygems.org, for example in your Gemfile replace the current line containing

gem 'rails'

with

gem 'rails', '~> 6.0', '>= 6.0.2.2'

Ideally, update all your gems by running bundle update followed by bundle install.

For a more thorough update, after the steps above, run rails app:update. This will add or modify files in bin and config. For each file, you have the options [Ynaqdh]

Though every app is different, it’s probably ok to overwrite anything you haven’t edited (like bin files) and probably NOT ok to overwrite anything you have edited, like config/routes.rb and config/application.rb. I went with Y for all files out of curiosity, and then had to add my routes and application back from a recent GitHub commit. If rails app:update adds a database migration, be sure to run rails db:migrate locally and heroku run rails db:migrate in production (for example).

Note: using rails is equivalent to rake in this case.

Let’s get this working

At this point, test your app to make sure everything works before proceeding with updating from Secrets to Credentials. How to Implement Credentials: The command for creating the new pair of files (master.key and credentials.yml.enc) is the same as the command for editing them. If you use VS Code, you’ll use the command:

EDITOR="code --wait" rails credentials:edit

If you use Atom, you’ll use

EDITOR="atom --wait" rails credentials:edit

and so on for whatever editor you prefer.

It’ll look like nothing is happening in your console, but the file should open in your editor after a few seconds. To start with, it should look like this:

aws:
  access_key_id: 123
  secret_access_key: 345
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.

secret_key_base: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The secret_key_base is paired with your credentials.yml.enc, so don’t edit it. Use yaml syntax to organize/nest/label your private data. For a credentials.yml.enc containing this:

aws:
  access_key_id: 123
  secret_access_key: 345
my_secret: 'ABC'
api_keys:
  google:
    maps: 'DEF'
    places: 'GHI'
  spotify: 'JKL'

You would access 123 in any of your Ruby files with:

Rails.application.credentials.aws[:secret_key_id]

You would access ‘ABC’ with:

Rails.application.credentials.my_secret

You would access ‘DEF’ with:

Rails.application.credentials.api_keys[:google][:maps]

With your credentials.yml.enc set up and used in your code, you can now delete the .secrets file and remove it from your .gitignore.

Using Credentials in Production: Finally, if you’ll need to access the credentials in production (and you probably will) then add or comment in the following in config/environments/production.rb:

config.require_master_key = true

When you deploy your code to a server, Rails will need another way of accessing your master key since it’s not in version control. You can set it as an environment variable. For example, in Heroku this would be:

heroku config:set RAILS_MASTER_KEY=XXXXXXXXXXXXXXXXXXXXXXXXX

That’s it — you’re all set! Welcome to improved security with encrypted Rails Credentials.

Privacy Work Terms

© 2021 Alan Reid