How we started to use Rails 5.2 Encrypted Secrets for securing Amazon S3 key pairs for use with Active Storage.
Here is a useful starting point: Rails Encrypted Credentials on Rails 5.2
Our development and production envionment is Linux, and we precompile our assets before deployment.
Part 1: Encrypt your secrets
With Rails 5.2 a sort of ‘password safe’ is introduced, whereby you commit your encrypted secret credentials to source control, but not your master password.
To encrypt your secret credentials, you execute the
$ rails credentials:edit command in your terminal.
It is useful to read the help text that goes with it:
$ rails credentials:help Usage: bin/rails credentials [options]
=== Storing Encrypted Credentials in Source Control
credentialscommands provide access to encrypted credentials, so you can safely store access tokens, database passwords, and the like safely inside the app without relying on a mess of ENVs.
This also allows for atomic deploys: no need to coordinate key changes to get everything working as the keys are shipped with the code.
Applications after Rails 5.2 automatically have a basic credentials file generated that just contains the secret_key_base used by MessageVerifiers/MessageEncryptors, like the ones signing and encrypting cookies.
For applications created prior to Rails 5.2, we’ll automatically generate a new credentials file in
config/credentials.yml.encthe first time you run
bin/rails credentials:edit. If you didn’t have a master key saved in
config/master.key, that’ll be created too.
Don’t lose this master key! Put it in a password manager your team can access. Should you lose it no one, including you, will be able to access any encrypted credentials.
Don’t commit the key! Add
config/master.keyto your source control’s ignore file. If you use Git, Rails handles this for you.
Rails also looks for the master key in
ENV["RAILS_MASTER_KEY"], if that’s easier to manage.
You could prepend that to your server’s start command like this:
=== Editing Credentials
This will open a temporary file in
$EDITORwith the decrypted contents to edit the encrypted credentials.
When the temporary file is next saved the contents are encrypted and written to
config/credentials.yml.encwhile the file itself is destroyed to prevent credentials from leaking.
On Linux, to have
$ rails credentials:edit open our editor (pluma)
and wait for us to edit the contents, we run this:
$ EDITOR="time pluma" rails credentials:edit
‘time’ makes it wait while we edit and save the file. You can substitute ‘pluma’ with whatever editor you use. The file opens in your editor, and we edited ours to look like this:
#credentials.yml.enc.12345 aws: access_key_id: QWERJKLQCMCNVTNDSIFEGJS secret_access_key: gtmmnYKdV4GGU9bj7QpBFIia8kpfXfuNR+MBgKeB # Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies. secret_key_base: tis2CaJpYDRuw0CkpFY15d3f4u1VyGudZxhYHTyDtis2CaJpYDRuw0CkpFY15d3f4u1VyGudZxhYHTyDtis2CaJpYDRuw0CkpFY15d3f4u1VyGudZxhYHTyDgfhfghht
and save the file:
New credentials encrypted and saved.
Note that some indentation errors such as one additional space before the ‘aws’ in the above example may fail silently and your file could be incorrectly encrypted, so take care to get it right. This happened to us when we later got this error:
ArgumentError: Missing `secret_key_base` for 'production' environment, set this string with `rails credentials:edit`
Part 2: Update your configuration(s)
To use the credentials in the production environment, add the following to config/environments/production.rb
#config/environments/production.rb ... config.require_master_key = true ...
Update anywhere where the unencrypted credentials are configured, for example we changed config/storage.yml to look like this:
# config/storage.yml amazon: service: S3 access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> region: us-west-1 bucket: www.mySite.com
You will need to add an environment key value pair in your production environment the value can be found in ‘config/master.key’.
Part 3: Precompile assets and deploy
On precompiling the assets for production, we got this problem:
$ RAILS_ENV=production rake assets:clean assets:precompile rake aborted! ArgumentError: Missing `secret_key_base` for 'production' environment, set this string with `rails credentials:edit`
The solution was to re-edit and save the credentials to correct an indentation error, as noted above.
Encrypted secrets makes it easier to keep third party access tokens, database passwords, and the like safely inside the app without relying on a mess of environment variables.
It also solved our Amazon S3 access problems with Active Storage direct upload.
This is a move towards atomic deployment: keys can now be shipped with the code.