Rails 5.2 の Credentials を各環境でも使えるようにする gem を作りました

Rails 5.2 で追加される Credentials 機能を development, test, staging などで使えるようにする gem を作ったので紹介します。

github.com

Rails 5.2 の Credentials とは?

API token やパスワードなどの情報を暗号化し、リポジトリで管理できるようにする機能です。 暗号化に使用する鍵は config/master.key もしくは RAILS_MASTER_KEY 環境変数を使います。

今までの Rails では秘匿情報を環境変数で管理するのが主流でした。 しかし、この方法では管理する環境変数が多くなってしまったり、バージョン管理できません。

5.2 で導入される Credentials の機能を使うことで、秘匿情報をリポジトリで管理することができるようになり、サーバに設定する環境変数も1つで済むようになります。

Rails 5.1 で追加された encrypted secrets に似ている?

This will eventually replace Rails.application.secrets and the encrypted secrets introduced in Rails 5.1.

引用: https://github.com/rails/rails/blob/v5.2.0.rc1/activesupport/CHANGELOG.md

encrypted secrets は忘れてください。

Credentials の不満点

DHH曰く「productionしか秘匿情報は必要ない」とのこと。

It's only in production (and derivative environments, like exposed betas) where the secret actually needs to be secret.

引用: https://github.com/rails/rails/pull/30067

いや、staging 環境で使う API token とかがあるので他環境でも使いたい...(´・ω・)ッス

別の方が Environment-specific credentials という Issue を作っていますが、 Close されてるし、 Rails では対応されなそう。

各環境の秘匿情報を管理する gem を作った

そんな経緯で RailsEnvCredentials の gem を作りました。

各環境で別々の credentials.yml.enc を使うことができます。

基本的な使い方

Gemfile に gem を追加して、 bundle install してください。

group :development, :test do
  gem 'rails-env-credentials'
end

もし staging 環境で使う場合は group に :staging も追加する必要があります。

development 用の credentials を生成するには env_credentials:edit コマンドを使います。

$ rails env_credentials:edit -e development

development 環境用に credentials-development.yml.enc が生成されます。 鍵は config/master-development.keyRAILS_MASTER_KEY_DEVELOPMENT 環境変数を使います。

秘匿情報の diff を表示する

credentials.yml.enc は暗号化されているため、普通に git diff をしても差分は表示できません。

$ git diff config/credentials.yml.enc
diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc
index 1a69bf0..c0517de 100644
--- a/config/credentials.yml.enc
+++ b/config/credentials.yml.enc
@@ -1 +1 @@
-SN7yXV6C2NZSdp/ij84h6Tox7iJ6VLHWgnhbY7BFe5TTsLa6V9g1D/iI1H5WMCBEECcpL/z096spDpcjXdq1aS2w3Wz9GijvuCiJNA8LaiWzqN9FMDmPB8eJjff+qebG+mN4Wdmc1/LDWV0GvYYQWAzDuYv3Kyv7jrxh/6MQjm2h9+i1AlBj7ofnzppvz9m8yiM2kyoqk/5aFdNiUqCdvzqbxIAXf0qvL/GPezKVOgbLcKL+/ytIFDvQeFc+BJ9d/RHsvOfyy1hSJxAhstJsf9I2WlI8gWYBjNip6nZzEQUCuhJpFEd+tXTzTOt3ZlWHzodQA9W3E+BScDOUgAPM7eJ9eCCDHvSQrvgI9i9KfpuxFP51OTODqYkR1+kfW7g/ZupvAhwMAM504af7zFLgHxad5Q==--UjL1q8veV48t5/oe--pUi30wtwFBJlM5PIJI0U2A==
\ No newline at end of file
+i3rH3HDSUPAwal/Mi8SsFg+UqKfyudpjTxFpYrXxElOvQYo7wsIZ9v5NRe6mew/WnMNiM/B66jJM4KIf1voMRWrTJaGfkWc4ARLjgcgLNu4rj4+LHyZZ2LkkgqZpTHObtLHEH5E/7ZNQVpHJ1CwfMR/SwGgaDPJFVbM3uF3tGSzY0Fyg3jgeyiiU6Vuk+H6CUGFMxDsjnIj1oMrpACX42vDfpy5wZquyzycG6LpmJsFqofirmb9sT1n32mDoA6k138SDLdnUiNpftNGGK8q9+SaT8e5OzZ8CMSeMLD64psRYCL+qZip+ZX0zvdVmSkUaH/y71bkHTChhMNZzHcW69FBNgfirMmWchjePUlw1+LIjrAIQL9JQD5Wv3E5Yl6RRKX0LSsrtUqEmABz9Lxbq9uGh/HEsC2OnrLOGYFvvKYs53Y1lQVF29f3NKSdk--VINiczKtUJKG4hro--oRD2+JF7lbL/wO8d3dP0Mw==
\ No newline at end of file

これは Git の設定を活用することで表示できるようになります。

まず、下記の内容で .gitattributes を作成します。

config/credentials*.yml.enc diff=env_credentials

次に Git に復号化のコマンドを設定します。

$ git config diff.env_credentials.textconv 'rails env_credentials:show --file'

この状態で git diff を実行すると、復号化した内容で差分が表示されるようになります。

$ git diff config/credentials.yml.enc
diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc
index 1a69bf0..c0517de 100644
--- a/config/credentials.yml.enc
+++ b/config/credentials.yml.enc
@@ -4,3 +4,5 @@
 
 # Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
 secret_key_base: 358e4c7f994ffdba2a8994c00bf902303d1456d1f4d4e3d8e6c6c843628de5bc158f061fd1759b7a4a015395627ad9b34a4e8714167da0387695cb9906bbe1ba
+aws:
+  access_key_id: 123

まとめ

production 以外での秘匿情報の管理って需要ありそうだけど、Rails にプルリクを投げて英語で説得する自信は無かったので、とりあえず gem を作ってみた。

もし gem が結構使われて、需要ありそうってのが分かったらプルリクを投げるかもしれない。