A Guide to Encrypted Credentials in Rails

Peter AbahPeter Abah
4 min read

Credentials/secrets are sensitive pieces of information or configurations, such as API tokens from third party services, that a web application needs to function.

It is important that developers keep these credentials private to prevent security vulnerabilities. This can be done by making sure credentials are not to be committed to version control systems like Git and shared publicly.

To illustrate why it is important to keep these credentials private at all times, consider a Rails app using Amazon S3 and Rails Active Storage for storing user uploaded content. If access tokens are stored directly in a file (e.g., storage/config.yml), and this file ends up in a public source control repository, anyone with access to these tokens could potentially compromise your S3 storage and the data it holds.

In this article, I will explain managing credentials in Ruby on Rails, multi-environment credentials, and how to handle deployment of rails apps using encrypted credentials.

Introduction

Ruby on Rails is a full-stack framework used to build various types of web applications. These applications need to integrate with various third-party services, such as Stripe for payment processing and Amazon S3 or Cloudinary for file storage. Tokens are usually required when integrating these services, and developers need a secure method to store and share these tokens.

To address this need, Ruby on Rails provides built-in mechanisms for managing sensitive information like tokens. One common approach is to use environment variables, which allow developers to store configuration details securely outside the codebase. These variables are set in specific environments (such as development, testing, and production) and are easily accessible within the Rails application.

But this method has various drawbacks, especially when there's a need to share these tokens securely across multiple teams. In response to this problem, Ruby on Rails provides encrypted credentials.

Encrypted credentials

Rails 5.2 introduced encrypted credentials. Tokens are stored in an encrypted file (config/credentials.yml.enc) created by Rails. Developers can safely add this file to shared version control system and share them among team members.

Two files are important:

  • config/credentials.yml.enc, which contains the encrypted tokens
  • config/master.key, which is used to decrypt the encrypted credentials file. It's crucial not to commit config/master.key to version control.

config/credentials.yml.enc is an encrypted YAML file which stores the application tokens. It contains secret_key_base by default, which Ruby on Rails uses internally.

This file should not be edited directly since it is encrypted. You can edit it by running the following command in command line:

rails credentials:edit

When you run this command, rails decrypts the credentials file and opens it in your default text editor. If there is no default text editor set, you can set the EDITOR environment variable in the command:

EDITOR=vim rails credentials:edit

If you are using VSCode, add a --wait option to the EDITOR env variable.

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

Rails creates a default credentials file when you run the command if config/credentials.yml.enc does not exist. After editing and closing the file, the file is automatically encrypted by rails.

The config/master.key file stores the key used to encrypt the config/credentials.yml.enc file, and it should not be committed to version control. The file is added to .gitignore by default.

The config/master.key file is also stored in RAILS_MASTER_KEY environment variable and rails fetches the key from environment variable if config/master.key does not exist.

Since config/credentials.yml.enc is encrypted, it can be added to version control and shared.

Accessing encrypted credentials

You can access encrypted credentials in your Rails application using:

Rails.application.credentials

For example, if your credentials file looks like this:

secret_key_base: <secret_key_base>
api:
  stripe:
    token: <your_key_here>

You can access the Stripe API token in your Rails application using this:

Rails.application.credentials.api.stripe.token

Multi-Environment Credentials

Rails 6.0 introduced support for multi-environment credentials. Credentials specific to an environment can be edited by adding the environment option to the rails credentials command:

rails credentials:edit --environment <environment>

Where <environment> is the environment for the credentials you want to edit. For example, to edit credentials for staging environment, you will run this command:

rails credentials:edit --environment staging

The command creates config/credentials/staging.yml.enc and config/credentials/staging.key. Rails automatically detects when your application is in staging environment and uses the appropriate credentials file.

Run the following command to edit environment-specific credentials in production:

rails credentials:edit --environment production

Deployment

Set the RAILS_MASTER_KEY environment variable to match the contents of config/master.key to ensure encrypted credentials work after deployment.

For Heroku users, set the environment variable using:

heroku config:set RAILS_MASTER_KEY=$(cat config/master.key)

Set RAILS_MASTER_KEY environment variable to the value of the key specific to the environment if your application uses multi-environment credentials. If the environment is in production, you set RAILS_MASTER_KEY environment variable to the value in config/credentials/production.key

0
Subscribe to my newsletter

Read articles from Peter Abah directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Peter Abah
Peter Abah