Storing Secret Credentials in Rails 5.2 and Up
Aatif Jiwani, Former Rails Developer Intern
Article Categories:
Posted on
Keeping your credentials safe as a developer is extremely important. You don’t want to commit any sensitive information, like passwords or API keys, to your remote git repository as it can allow malicious users to access the services you are using.
The Good Ol’ Days #
Since version 4.1, Rails has helped developers store their secrets by generating a new secrets.yml
file in the config folder. By default, this file contains a SECRET_KEY_BASE
that is used to “derive keys for encrypted cookies… [and] HMAC signed cookies.”[1] However, you could add additional keys to this file:
# config/secrets.yml
development:
secret_key_base: n3mb3r5a5ndl3t4ter5
secret_api_key: SOME_PRIVATE_KEY
Once everything is saved, you could access it via Rails.application.secrets.secret_api_key
. This way, you could store your secret credentials in a single file and simply make sure that secrets.yml
is part of your .gitignore
.
The release of Rails 5.1 added another file named secrets.yml.enc
to allow for encrypting your secret credentials, but this caused some confusion. The combination of config/secrets.yml
, config/secrets.yml.enc
, and SECRET_KEY_BASE
made it so it wasn’t clear where secrets should be stored and what the relevance of SECRET_KEY_BASE
was [2] .
A New Beginning #
With this confusion in mind, Rails released version 5.2 and created an entirely new way to store your secret credentials that I will walk you through.
First, make sure you install the newest version of Rails by running:
gem update rails
This ensures that the Rails Gem you install is the most up to date (you can find the most recent release of Rails on the official RubyGems page[3]). After doing so, when you create a new Rails project, you should see two files in your config folder:
credentials.yml.enc
is an encrypted file that will contain all your secret credentials. Your private API keys and passwords will all be stored in this file, all encrypted. Since this file is encrypted, it is safe to push this to a remote git repository or a server.master.key
is a file containing your encryption key. Without this file or if it is modified, Rails will not be able to read your credentials stored incredentials.yml.enc
. This file should NOT be pushed to a git repo or any server as it can be used to decryptcredentials.yml.enc
and someone can steal sensitive information.
You must be wondering, how do I add my secret credentials to credentials.yml.enc
if it is encrypted? Well, you need to go into your command line interface and run:
EDITOR="subl --wait" bin/rails credentials:edit
Without the --wait
flag, your credentials.yml.enc
will be saved immediately without giving you the chance to edit. Also, you can replace “subl” with the command line shortcut to whatever your favorite text-editor is (in this case, the command above will open credentials.yml.enc
in Sublime since I’ve made the shortcut available). Now, you can edit and store new credentials in YAML format, save the file, and Rails will automatically re-encrypt credentials.yml.enc
for you. You can access these secret credentials at any point in your application by using:
Rails.application.credentials.dig(:key_name)
And you’re good to go! If you do not want to redefine your EDITOR
everytime you want to edit your credentials, simply add to your shell profile:
export EDITOR="subl --wait"
Now, all you need to do to edit your credentials is run:
bin/rails credentials:edit
Heroku and other Deployment Strategies #
If you’re deploying your app to Heroku, the encryption key from master.key
is stored in an entirely different way. Heroku allows you to add special configuration variables in the Settings tab of your app’s dashboard. There, you can add a new config variable called RAILS_MASTER_KEY
and paste the encryption key into the space provided. Once saved, the Rails application is smart enough to detect that the master key is stored as a config variable to decrypt your secret credentials.
The underlying technology of this method is that Heroku is setting an environment variable that Rails can access via ENV[“RAILS_MASTER_KEY”]
. Therefore, to store your master key on other remote servers, you just have to save the encryption key as an environment variable.
Collaboration #
What if you need to share your master.key
with other developers working on your team or project? Simply sending a message containing the special key over spaces like Slack isn’t safe and ultimately isn’t good practice. That’s why password management is a giant field of its own and there are a multitude of ways to securely share your credentials with trusted people. Two services I personally use are 1Password and OneTimeSecret.
1Password is a secure password manager that allows users to store any kind of credentials: passwords, API keys, software licenses, etc. In fact, 1Password allows organizations to get in on it so team members can securely share a pool of sensitive information amongst everyone on their team.
OneTimeSecret is more for quickly sharing credentials with your team and less for long-term storage like 1Password. You can generate a secret link, password-protected or not, that will contain the sensitive information once opened. However, there’s a catch! Once you open the link for the first time, you should store the given information somewhere more secure as you cannot open the link ever again. Also, the secret-holder can set an expiry time on the link so you have a certain timeframe to retrieve the secret information and store it in another location.
Now, you know how to safely store credentials and reduce the risk of unauthorized access!