Append secrets to credentials.yml.enc programmatically
Asked Answered
R

2

10

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.

Roundly answered 13/5, 2019 at 19:48 Comment(0)
R
10

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.

Robertson answered 10/9, 2020 at 19:2 Comment(4)
Thanks. Actually I hoped that there would be a dedicated command for this task, but your proposal works well and therefore it is a nice workaround Using just a single ">" helps in the case of creating the fresh credentials file based on a stub. I would like to see such a command in a future Rails version so that an input file can be supplied that might even be deleted right after the command has been executed so that it is like just encrypting it.Roundly
Doesn't seem to be working anymore. ``` # EDITOR='echo "foo: bar" >> ' rails credentials:edit foo: bar >> /tmp/20231013-85-8k81o7-credentials.yml File encrypted and saved. ``` However, opening the file via editor afterwards shows it doesn't contain foo: bar.Schleswigholstein
@Schleswigholstein I have just tried this morning using Rails 7.0, and it still works.Robertson
@Robertson sorry for bothering again. I have made another attempt, and here is the output: pastebin.com/ZrvdY0LJ. The content of the credential file doesn't seem affected. Do you see something wrong in my execution?Schleswigholstein
S
0

If you want to do this from a Ruby script, you can reuse Rails' internal ActiveSupport::EncryptedConfiguration:

def credentials_encrypted_file
  ActiveSupport::EncryptedConfiguration.new(
    config_path: "config/credentials.yml.enc",
    key_path: "config/master.key",
    env_key: "RAILS_MASTER_KEY",
    raise_if_missing_key: true
  )
end

credentials_injection = "\n\nfoo: bar"

credentials_encrypted_file.change do |tmp_path|
  inject_into_file tmp_path, credentials_injection
end

An example of use can be found in Rails::Generators::CredentialsGenerator

Score answered 11/6, 2023 at 20:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.