Rails 環境別の設定ごと secrets.yml -> credentialへ移行

こんにちは。MUGENUPの林です。

私の担当サービスは、かつてRails 5.1以下を使っていた名残で、secrets.ymlで秘密情報を管理していました。

※現在の バージョンは 5.2.3 です。

secrets.ymldatabase.ymlが手動管理ということは、変更漏れによるエラーが発生してしまう可能性が高く危険です。

credentialへ移行し、変更の必要のないmaster.keyのみ手動管理する方法に切り替えることにしました。

credentialはRails5.2より追加されました。

railsguides.jp

credential作成

EDITOR="vim" bin/rails credentials:edit のコマンドで編集画面が表示されます。

EDITOR="vim"は作業環境でエディター設定をしている場合は省略可能です。

以下、初期の中身です。

# aws:
#   access_key_id: 123
#   secret_access_key: 345

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: 〜シークレットキー〜

secret_key_base は残し、既存のconfig/secrets.yml をそのままコピーしてペーストしましょう。※ 理由は最後に

secret_key_base: 〜シークレットキー〜
default: &default
development:
  <<: *default
test:
  <<: *default
staging:
  <<: *default
production:
  <<: *default

といった形でコピー&ペーストすることで、環境別の設定もそのまま引き継げます。

保存すると、config/credentials.yml.encconfig/master.keyが出来上がります。

.gitignore では

# Ignore master key for decrypting credentials and more.
/config/master.key

が追加されています。

credentialsは、環境別の設定をソースコード側で自動参照してくれないので、 ソースコード内のRails.application.secretsRails.application.credentials[Rails.env.to_sym]と置き換えましょう。

config/database.yml は?

  host: <%= Rails.application.credentials[Rails.env.to_sym][:db][:host] %>
  password: <%= Rails.application.credentials[Rails.env.to_sym][:db][:password] %>

host と password だけ credentials に任せる形にして、秘密の情報を無くし、 Gitの追跡対象に追加しました。

.gitignore から

/config/database.yml

を消すことで、コミットができるようになります。

circleCIは?

f:id:mgnup:20191219164315p:plain 設定のEnvironment VariablesからRAILS_MASTER_KEY環境変数(Name)として追加できるので、 master.keyの中身をValueに入れて追加します。

capistranoは?

手動管理していたconfig/secrets.yml, config/database.ymlに対して貼られていたシンボリックリンクを、master.keyに置き換えます。

先に対象サーバーのシンボリックリンク先になるファイルを設置しましょう。

(例: [Railsソースコードのあるパス]/shared/config/master.key)

config/deploy.rbでデプロイ時の設定が行われているので、こちらを書き換えましょう。

set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')
↓
set :linked_files, fetch(:linked_files, []).push('config/master.key')

他にもsetup等でconfig/secrets.yml, config/database.ymlがある場合は、適宜置き換えてください。

以上で完了です!

secret_key_base は、development / test と staging / production で取得方法が変わる

(development / test はダミーの文字列を自動生成して通ってしまう)

ようなので、慎重にご対応ください。

github.com


※secret_key_baseだけは特別対応をします!

Before

default: &default
development:
  <<: *default
  secret_key_base: 〜今までのシークレットキー〜

のように、環境別に secret_key_base を設定していた場合はそちらを消し、

After

secret_key_base: 〜シークレットキー〜
default: &default
development:
  <<: *default

と、defaultの外に、credential作成時に作られた最新のシークレットキーを書きましょう。

  • Rails本体が secret_key_base を参照するときの Rails.application.credentials.secret_key_baseRails.application.credentials[Rails.env.to_sym].secret_key_baseと置き換えることができない
  • credentialsを初めて作成したときに secret_key_base が自動生成されることから、 credentialsと secret_key_base は1:1で、環境別に用意するものではなくなったと推測

以上の理由から、 secret_key_base は一つに統一し、Rails.application.credentials.secret_key_baseで呼び出せる形に整えることにしました。

ちなみに、環境別の設定に書くと

Missing 'secret_key_base' for 'staging' environment, set this string with 'rails credentials:edit'

というエラーが出てしまいます。