Rails Credentials can be Confusing

Jon Sully

2 Minutes

Some conventions to follow

Rails’ encrypted credentials feature is neat but can be a bit confusing and docs are quite minimal. For my own future’s sake, here are a brief set of explanations and conventions to follow.

For backwards compatibility reasons and history, your app may have a ‘global’ credentials file. This consists of the file pair:

~/config/credentials.yml.enc
~/config/master.key

Additionally, Rails 6 brought environment-specific credentials files consisting of credential file-pairs in ~/config/credentials/ such as:

~/config/credentials/development.yml.enc
~/config/credentials/development.key
~/config/credentials/production.yml.enc
~/config/credentials/production.yml.enc

If the environment-specific yml files exist they will take precedence over the ‘global’ file. So even if you’re just doing local development, the presence of development.yml.enc will cause Rails to load that file, not the global credentials.yml.enc.

You may edit your environment-specific credentials files by passing -e=<ENV> to rails credentials:edit and only by passing that flag (or its more verbose variant). Setting the RAILS_ENV does not control credentials:edit like basically all other rails tasks. E.g.

RAILS_ENV=production rails credentials:edit

Will not edit the production credentials file. Strange right? Basically every other Rails command follows RAILS_ENV, but not this one. Beware, this can catch you really off guard. You need to pass the environment you want to edit as a specific argument to the task:

rails credentials:edit -e production
# or
rails credentials:edit --environment production

There’s a bit of an ongoing discussion as to why this is the case, but as George Claghorn summarized, one shouldn’t have to boot the Rails app in Production mode (which may not be possible to do locally) just to edit the production credentials. It makes sense, but having a Rails task that doesn’t adhere to RAILS_ENV leaves a bit of a tension 🤔

Beyond that, having a mix of the ‘global’ credentials file and some environment-specific credentials files can also be a bit of a foot-gun. Forgetting which is which, when/where each is loaded, and that we need to add credentials to more than one file can make for a not-fun-day. I’d recommend either using the global credentials configuration (single pair of files, all environments share the same keys) or environment-specific credentials files with no global file so that each environment gets their own keys without having to worry about which credentials file gets loaded into the app.

Finally, environments that aren’t suitable for transfering a *.key file to (staging, prod, remote environemnts) need to use the environment variable RAILS_MASTER_KEY, which, despite using the name ‘master key’ should actually just contain the decryption key for that environment (the same string of characters contained within that environment’s *.key file).

Comments? Thoughts?

Anonymous

Also each environment master key (i.e. development.key, production.key, etc.) must never be checked into source control and are usually loaded as an environment variable in the shell which makes editing credentials for different environments a cumbersome process of reexporting RAILS_MASTER_KEY. It’s not elegant.

February 2023

Will not edit the production credentials file. Strange right? Basically every other Rails command follows RAILS_ENV, but not this one. Beware, this can catch you really off guard. You need to pass the environment you want to edit as a specific argument to the task:

Jon Sully (Author)

For now, anyway! Turns out this is changing in Rails 7.1! This was just merged: https://github.com/rails/rails/pull/47107

April 2023 Calendar

If the environment-specific yml files exist they will take precedence over the ‘global’ file. So even if you’re just doing local development, the presence of development.yml.enc will cause Rails to load that file, not the global credentials.yml.enc.

Betina Jessen

Handling sensitive data, such as API keys or database credentials, is a critical aspect of application security. The credentials feature in Rails provides a convenient and secure way to store and access this sensitive information. However, due to its intricacies, it can sometimes be a source of confusion for developers. This comment recognizes the potential difficulties developers may face when working with Rails credentials, such as understanding the encryption process, managing multiple environments, or integrating with deployment systems. It underscores the importance of thorough documentation, best practices, and proper education on effectively utilizing Rails credentials to ensure the security and confidentiality of sensitive data. By addressing the confusion surrounding Rails credentials, developers can enhance their understanding and utilization of this essential feature, thus strengthening the overall security posture of their Rails applications. Printable calendar 2023

monthlycalendar2023

Beyond that, having a mix of the ‘global’ credentials file and some environment-specific credentials files can also be a bit of a foot-gun. Forgetting which is which, when/where each is loaded, and that we need to add credentials to more than one file can make for a not-fun-day. I’d recommend either using the global credentials configuration (single pair of files, all environments share the same keys) or environment-specific credentials files with no global file so that each environment gets their own keys without having to worry about which credentials file gets loaded into the app. August 2023

Reply

Please note: spam comments happen a lot. All submitted comments are run through OpenAI to detect and block spam.