How to Handle Sensitive Credentials in Rails 5 Apps

Rails 4.1 introduced secrets.yml. The default file has secret_key_base. You can also store access keys to external APIs, http basic login and other sensitive credentials.

development:
  secret_key_base: 3b7cd727ee24e8444053437c36cc66c3
  some_api_key: SOMEKEY

You can now access the values in development by:

Rails.application.secrets.some_api_key

Instead of having a dependency on:

Rails.application.secrets

that might change in the future, we can create a class and encapsulate this behind a stable interface like this:

class Credential
  def self.some_api_key
    Rails.application.secrets.some_api_key
  end
end

Now you will depend only on this stable interface throughout your application. Like this:

Credential.some_api_key

This isolates any changes to the way Rails exposes the values to one Credential class. The sensitive values are hard-coded in the secrets.yml and we add it to .gitignore to prevent checking it into source control. A better way is not to hard-code the credentials and use environment variables. The secrets.yml will look like this:

development:
  secret_key_base: ENV[SECRET_KEY_BASE]
  some_api_key: ENV[SOMEKEY]

In production, you need to define the values in either ~/.bashrc or ~/.profile like this:

export SOMEKEY='thisisverysecret'

For Moonshine, you can edit the config/moonshine.yml and add a line for secrets.yml like this:

# Use :shared_config to copy directories straight from your local project
# directory to the server: these are files that you don't have/want in scm.
:shared_config:
  - config/database.yml
  - config/secrets.yml

Here is my secrets.yml:

# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
#   git config --global core.excludesfile '~/.gitignore_global'

# Ignore bundler config.
/.bundle

# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal

public/favicon.ico
config/database.yml
config/secrets.yml
coverage/**/*
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp

When I deploy using Capistrano the secrets.yml file gets uploaded to the server. The secrets.yml file does not contain any sensitive information anymore. So, it's not really necessary to remove it from source control. The secrets.yml uses environment variables for different environment like this:

development:
  http_basic_user: fake
  http_basic_password: fake
  mailchimp_api_key: fake
  secret_key_base: fake
  stripe_secret_key: <%= ENV['STRIPE_SECRET_KEY'] %>
  stripe_publishable_key: <%= ENV['STRIPE_PUBLISHABLE_KEY'] %>  

test:
  http_basic_user: fake
  http_basic_password: fake
  mailchimp_api_key: fake
  secret_key_base: fake
  stripe_secret_key: <%= ENV['STRIPE_SECRET_KEY'] %>
  stripe_publishable_key: <%= ENV['STRIPE_PUBLISHABLE_KEY'] %>  

production:
  secret_key_base: <%= ENV['SECRET_KEY_BASE'] %>
  sendgrid_username: <%= ENV['SENDGRID_USERNAME'] %> 
  sendgrid_password: <%= ENV['SENDGRID_PASSWORD'] %> 

If you enjoyed this article, please share it by clicking one of the sharing button below.


Related Articles


Ace the Technical Interview

  • Easily find the gaps in your knowledge
  • Get customized lessons based on where you are
  • Take consistent action everyday
  • Builtin accountability to keep you on track
  • You will solve bigger problems over time
  • Get the job of your dreams

Take the 30 Day Coding Skills Challenge

Gain confidence to attend the interview

No spam ever. Unsubscribe anytime.