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 tokensconfig/master.key
, which is used to decrypt the encrypted credentials file. It's crucial not to commitconfig/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