credentialsproduction-environmentruby-on-rails-5.2

Append secrets to credentials.yml.enc programmatically


Is there a way to programmatically add secrets to config/credentials.yml.enc in Rails 5.2?

Pushing the credentials.yml.enc to the repository for internal use may be fine, but as soon as the app is used by other people, they require different secrets within their environment. Like the Oauth2 credentials will differ for each implementation.

Running the app within docker (for example) will require more manual interaction, and Docker-know-how than usual. In most cases the more secure way is only used if it isn't much more effort.

One will need to run docker exec <app-name> -it /bin/bash first to be able to run rails credentials:edit.

It would be way better to be able to fill the credentials file programmatically. One could for example provide a temporary credentials file like:

production:
  postgresql:
    username: 'admin'
    password: 'very_insecure'

Then there could be a script adding the file's content to the credentials-file and deleting the temporary file afterwards.

For sure the RAILS_MASTER_KEY environment variable must be set (could be again a script moving the content of the master.key file into the variable) to gain any profit of that.


Solution

  • You can do this via some trickery with the EDITOR environment variable.

    Normally, you'd use EDITOR=nano rails credentials:edit in order to have Rails pass (a temporarily decrypted copy of) credentials.yml.enc to nano for modification, with the result being re-encrypted when nano terminates.

    If we substitute nano with cat (EDITOR=cat rails credentials:edit), Rails will pass the (decrypted) file to cat instead, causing its contents to be printed on-screen. In other words, Rails is effectively just running $EDITOR tempfile.name.

    Therefore, if we do this:

    EDITOR='echo "foo: bar" >> ' rails credentials:edit
    

    ...then the result will be this:

    echo "foo: bar" >> tempfile.name
    

    tl;dr: You can abuse EDITOR to (indirectly) do pretty much anything you'd do for a regular plain-text file.