Rails: Credentials

Rails: Credentials

iSergium

Начиная с версии 5.2 в Rails перешли с секретов (secrets.yml) на полномочия (credentials.yml).

Это менеджер ключей и паролей (да и вообще любых строк), хранящий всё в зашифрованном виде. Разберём как перевести имеющиеся секреты под новые требования на примере secret_key_base.

В данных примерах использовались: Rails 6.0.3.1, Capistrano 2.15.9Bundler 2.1.4.

1. Нужно создать

Можно и на локальном сервере, затем скопировать на релизный. Консольная команда, вызывающая редактирование credentials:

EDITOR=vim rails credentials:edit

Если через бандлы, то:

EDITOR=vim bundle exec rails credentials:edit

Редактор можно выбрать любой, даже с GUI. В него ввести практически то же самое, что было в secrets.yml, формат соответственно YAML.

development:
  secret_key_base: 461989807a53d2de8dacd1c73585713c37fddfe...
staging:
  secret_key_base: fd9065a781d4e3e96f17790c7d25ca45dcb1d8d...
production:
  secret_key_base: 914edbe043002157751b338ef7d571b949654cc...

Если в secrets.yml использовался <%= ENV["SECRET_KEY_BASE"] %>, то нужно его заменить на сам ключ.

После первого сохранения будут созданы master.key (в нём хранится ключ шифрования, при повторных сохранениях будет использоваться уже он) и credentials.yml.enc (это зашифрованные credentials).

Adding config/master.key to store the encryption key: 5ca595fdd3a6a774f0ae6b52c3fa29fc
Save this in a password manager your team can access.
If you lose the key, no one, including you, can access anything encrypted with it.
      create config/master.key
File encrypted and saved.

2. Нужно задействовать.

1. В config/environments, как минимум в production.rb:

config.secret_key_base = Rails.application.credentials[Rails.env.to_sym][:secret_key_base]

Также включить требование ключа:

config.require_master_key = true

2. В иных местах, где использовался этот ключ, заменить на такую же конструкцию:

YourApp::Application.config.db_token = Rails.application.credentials[Rails.env.to_sym][:secret_key_base]

Но в этом примере правильнее всё-таки задействовать config:

YourApp::Application.config.db_token = Rails.application.config.secret_key_base

3. Использовать на релизе.

Ключ можно хранить в двух местах: config/master.key и переменная окружения RAILS_MASTER_KEY. Отсюда вариативность использования:

3.1 RAILS_MASTER_KEY

export RAILS_MASTER_KEY=5ca595fdd3a6a774f0ae6b52c3fa29fc

Вариант простой, но не безопасный - любой процесс на сервере имеет к ним доступ. Также, если на одном сервере больше одного проекта, им придётся использовать одну переменную. Так что рекомендую второй способ.

3.2 master.key

На примере, когда на проекте используются репозиторий и деплои.

Файл master.key не рекомендуется хранить в открытых репозиториях. Если Ваш репозиторий закрыт от ненужных глаз, то данной частью можно пренебречь, иначе не забыть добавить его в .gitignore. Файл credentials.yml.enc зашифрован и его лучше хранить в репозитории.

Одним из вариантов использования master.key на сервере является хранение его во внешней папке с ограниченным доступом и при деплое делать ссылку на него в папке config. Допустим, есть папка shared, находящаяся вне проекта, доступная только необходимым пользователям, и на которую есть ссылка shared в папке проекта. Туда и можно скинуть данный файл.

Создание ссылки на файл на примере Capistrano. Сам таск:

namespace :custom do
  task :create_symlinks do
    run "ln #{release_path}/shared/master.key #{release_path}/config/master.key"
  end
end

Выполнение его нужно добавить после обновления кода, но перед выполнением любых подключений к БД, например миграций:

after "deploy:finalize_update", "custom:create_symlinks", "deploy:migrate"

С credentials.yml.enc всё проще - он добавится вместе с остальным кодом. После такого деплоя релизный проект сможет читать зашифрованные в файле ключи. Если что-то пошло не так, получите ошибку:

ArgumentError: Missing `secret_key_base` for 'production' environment, set this string with `rails credentials:edit`

Если это первое использование на релизе, то рельсы нужно пнуть с помощью rails credentials:edit:

EDITOR=vim rails credentials:edit

или через bundle:

EDITOR=vim bundle exec rails credentials:edit

Готово:

"/tmp/47452.credentials.yml" 14L, 652C written
File encrypted and saved.

Немного о хранении других ключей

Хранить можно любые значения, например:

development:
  stripe:
    secret_key: sk_test_asdfgh123
    token: rk_test_Hkkjbh43
production:
  stripe:
    secret_key: sk_live_qwerty456
    token: rk_live_dsIIjhh5

service1_key: sdgnhcs3sc435dc

github:
  app_id: 1111
  app_secret: dfgdrghj6f

Обращение к ним:

Rails.application.credentials[Rails.env.to_sym][:stripe][:secret_key]

Rails.application.credentials[:service1_key]

Rails.application.credentials[:github}[:app_id]

Также можно запросить целый объект:

Rails.application.credentials.github

Начиная с Rails 6 можно использовать отдельные файлы для разных сред:

rails credentials:edit --environment staging

Дополнительно