Generally in applications there are various secrets and credentials, that we need to make use of like API keys, secrets, etc.For such secrets we need the ability to conveniently and securely manage credentials.
Rails 5.1 added a feature to use secrets
to manage credentials.
The multi/http/railsdoubletap exploit module has been added to the framework. This module can predict the secretkeybase to a Ruby on Rails application while it is running in development mode and use the secretkeybase to generate a serialized payload. Sending that payload back to the Rails application can then result in remote code execution.
Rails 5.2 replaced secrets
with credentials
, since encrypted and un-encrypted secrets were making it harder to manage them.
A set of files were used to manage these credentials:
config/credentials.yml.enc
config/master.key
config/credentials.yml.enc
is an encrypted file which store the credentials. As this is a encrypted file, we can safely commit it to our version control systems.
config/master.key
contains RAILS_MASTER_KEY
which is used to decrypt the config/credentials.yml.enc
. We should not commit this file to version control.
As config/credentials.yml.enc
is encrypted we should never directly read from or write to it. Instead, we will use utilities provided by Rails which abstract encryption and decryption process for us.
We can edit the credentials
by running the following command:
This will open a vim editor with the decrypted version of the credentials file.
We can add new credentials in YAML format. Lets add the following lines, save the changes,
and exit.
When we save it, it encrypts again using the same master key.
If default editor is not set and we haven’t specified the editor, then we get the following message:
We can now access the credentials in the following way:
There was no built in support for multiple environment credentials before Rails 6. We could manage credentials for different environments but it was upto us to explicitly specify which set of credentials to use for a specific environment.
Strings come after numbers and are sorted lexicographically in ascendingorder. Children with a numeric value come next, sorted in ascending order. Firebase database generated primary key data. Ifmultiple children have the same numerical value for the specified childnode, they are sorted by key. If multiple children have a value of true, they aresorted lexicographically by key. Children with a value of true for the specified child keycome next.
We could store the credentials in a single file as below:
Then, config can be accessed using the following command:
There are some problems with this approach:
Another way to manage environment specific credentials was by creating environment specific files.For example, we can create config/staging.yml.enc
for staging environmentand config/production.yml.enc
for production environment.To read config from these files, Rails 5.2 providedencrypted
method to support for managing multiple credentials
files.
This approach involved writing even more boiler plate code to manage the keys and the encrypted files for every environment.
Now, Rails 6 has added support for multi environment credentials.
It provides utility to easily create and use environment specific credentials. Each of these have their own encryption keys.
The changes added in the above PR are backwards compatible. If environment specific credentials are not present then rails will use the global credentials and master key which are represented by following files:
config/credentials.yml.enc
config/master.key
We use the global configuration only for development
and test
environments. We share the config/master.key
with our entire team.
To create credentials for production
environment, we can run the following command:
The above command does the following:
config/credentials/production.key
if missing. Don’t commit this file to VCS.config/credentials/production.yml.enc
if missing. Commit this file to VCS.We share the production.key
with limited members of our team who have access for production deployment.
Let’s add following credentials and save:
Similarly we can create credentials for different environment like staging
.
For any environment Rails automatically detects which set of credential to use.Environment specific credentials will take precedence over global credentials. If environment specific credentials are present, they will be used else Rails will default to global credentials.
For development:
For production:
We can also set the value of the encryption key in specific environment variable Rails will auto detect and use it.
We can either use the generic environment variable RAILS_MASTER_KEY
or an environment specific environment variable like RAILS_PRODUCTION_KEY
If these variable are set then we don’t need to create the *.key
files.Rails will auto detect these variables and use them to encrypt/decrypt the credential files.
The environment variable can be used for example on Heroku
or similar platforms.