私が担当している製品の機密情報の管理は、Rails 5.1で導入されたEncrypted Secrets(secrets.yml.encを使う方式)を使っていて、5.2になって導入されたCredentials方式の導入は見送っていました。
理由は、5.2のCredentials方式だと、各環境毎の設定が行えなかったからです。そのため、5.2のリリース後にはCredentialsを複数の環境で扱えるようにするためのgemがいくつか出てきました。しかし、そこまでしてCredentialsに移行しても、ある意味レールから外れたカスタマイズをすることになりますし、Encrypted Secretsが非推奨になったわけではなかったので、Encrypted Secretsを使い続けていました。
現在もまだRails 5.2系を使っているのですが、これを6系にバージョンアップするために引っかかりそうなところを調査していたところ、Rails 6からはCredentials方式を後方互換性を保ったまま、各環境で使えるようになったという記事をRails 6エンジニア養成読本で読みました。
これを使えるようにしたいのですが、いきなり6にアップグレードすることは難しいです。
そこで、まずこの機能を先に取り込めるかどうかを検証しようと思いました。
バックポート用のコードを発見
調べ始めてちょっとしたら、gistで希望通りのコードと思われるものが公開されていました。
Backport Rails 6 per-environment credentials · GitHub
これを検証したところ、Rails 6のCredentialsと同様に各環境用のcredentials.yml.encとmaster.keyが作られました。
導入
導入に関しては、上記のgistを参考にしてください。
各環境のCredentialsを作成する
Rails 6のCredentialsの作成と同様の手順で行えます。下記のコマンドを実行すると、config/credentials/staging.yml.enc
とconfig/credentials/staging.key
が生成された後、VSCodeでstaging用のCredentialsの設定ファイルが開きます。
env EDITOR="code --wait" bin/rails credentials:edit --environment=staging
適当に入力後に保存して、そのファイルのタブを閉じると、設定完了です。簡単。
各環境のCredentialsを見る
Encrypted Secretsの頃は設定項目を見るだけのコマンドがなかったので、わざわざ編集モードで開く必要があったのですが(変更なしでも変更と見なされるのでgitで戻す必要があった)、Credentialsならば、閲覧用のコマンドがあります。便利!
bin/rails credentials:show --environment=staging
Credentialsに移行するために行なった作業
ざっくりとした手順は、以下の通りです。
secrets.yml.key
をコピーしてmaster.key
を作る。secrets.yml.enc
から各環境用に値をコピーする。Rails.application.secrets
をRails.application.credentials
に一斉置換する。config/environments/production.rb
をはじめとする全ての環境でEncrypted Secretsを使う設定を削除、RAILS_MASTER_KEY
を必須とする設定を行う- 開発環境で動作検証を行う
- stagingの環境変数
RAILS_MASTER_KEY
の値をconfig/credentials/staging.key
の値に変更する - stagingにデプロイして動作検証を行う
- 問題ないことを確認後、
secrets.yml
,secrets.yml.enc
,secrets.yml.key
を削除する。
master.keyを作る
master.keyには、本番環境で設定されている環境変数RAILS_MASTER_KEY
と同じ値を設定します。これはsecrets.yml.key
と同様のはずですので、コピーしてしまいます。
cp config/secrets.yml.key config/master.key
また、忘れずに.gitignore
にmaster.keyを追加しておきましょう。
/config/master.key
各環境用に機密情報をコピーする
以下のコマンドでEncrypted Secretsを表示します。
env EDITOR="code --wait" bin/rails secrets:edit
Encrypted Secretsの頃は、yamlのrootに環境名を設定する必要がありました。
production: aws: access_key: foo access_secret_key: bar staging: aws: access_key: foo_staging access_secret_key: bar_staging
これを、各環境のCredentialsにコピーしていきます。
production環境
まず、production環境です。以下のコマンドを実行すると、config/credentials.yml.enc
が生成され、編集モードで開きます。
env EDITOR="code --wait" bin/rails credentials:edit
以下のように設定し、保存します。
aws: access_key: foo access_secret_key: bar
staging環境
次に、staging環境です。以下のコマンドを実行すると、config/credentials/staging.yml.enc
とconfig.credentials/staging.key
が生成され、編集モードで開きます。
env EDITOR="code --wait" bin/rails credentials:edit --environment=staging
以下のように設定し、保存します。
aws: access_key: foo_staging access_secret_key: bar_staging
こんな感じで環境の数だけ作っていきます。
development, test環境
secrets.ymlも削除したいため、development, test用のCredentialsも作成しました。
secrets.yml
に設定していた内容をコピーします。
env EDITOR="code --wait" bin/rails credentials:edit --environment=development
test環境も同様に行いました。
機密情報の参照先を一斉置換する
Credentialsは指定方法がRails.application.credentials
なので、Rails.application.secrets
をRails.application.credentials
に一斉置換します。
各環境でEncryped Secretsを使う設定を削除
config/environments/production.rb
など、Encrypted Secretsを使っていた環境で、以下の行を削除します。
# Attempt to read encrypted secrets from `config/secrets.yml.enc`. # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or # `config/secrets.yml.key`. config.read_encrypted_secrets = true
そして、環境変数RAILS_MASTER_KEY
、又はmaster.keyに該当するものを必須とする設定を行います。
# Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). config.require_master_key = true
開発環境で動作検証を行う
ここまでできれば、設定が間違っていないか動作検証を行います。
bin/rails s
アプリが起動することと、ある程度動作することを確認します。
staging環境のRAILS_MASTER_KEYを変更する
先に、staging環境の環境変数RAILS_MASTER_KEY
を、config/credentials/staging.key
の値に変更します。
うちではHerokuを使っているので、この設定を先にせずにコードをデプロイして検証しようとしたところ、RAILS_MASTER_KEY
の値が異なるためCredentialsが解読できずにデプロイが失敗しました。忘れずにデプロイ前に変更しましょう。
stagingにデプロイして動作検証を行う
ここまでできれば、stagingにデプロイできていると思いますので、動作検証をします。
Encrypted Secretsに関するファイルの削除
問題ないことを確認後、secrets.yml
, secrets.yml.enc
, secrets.yml.key
を削除しましょう。
これで、あとは本番環境にデプロイすれば大丈夫だと思います。
と思いきや…
落とし穴(RAILS_MASTER_KEYがなくてCIがコケた)
secrets.ymlを削除したことで、CIでコケていました…。うちではCircleCIを使っているので、CircleCIにて、環境変数RAILS_MASTER_KEY
を作ってconfig/credentials/test.key
の値を設定したところ、テストも無事に通りました。
忘れずにCIにもRAILS_MASTER_KEY
の設定を!!