※ 弊社 feedforce で毎週行っている、インフラ共有会を元にした記事で
す。AWS で Rails を使っている方を想定していますが、数人規模のチー
ムを意識した内容になっています。

こちらの記事で yaml_vault を知ったので、実際に試してみました。

yaml_vault+KMSでRailsアプリのconfig/secrets.ymlを暗号化してgitにコミットして管理する - Qiita

環境変数つらい

SaaS の API Key などの秘匿情報をコードに埋め込まないために、Rails
dotenv を使っている方も多いかと思います。

しかし、README.md にあるように 作者の @bkeepers さんは production
での利用は奨励していません。

dotenv was originally created to load configuration variables into
`ENV` in *development*. There are  typically better ways to manage
configuration    in   production    environments    -   such    as
`/etc/environment`  managed by  [[Puppet|https://github.com/puppetlabs/puppet]] or  [[Chef|https://github.com/chef/chef]], `heroku  config`, etc.

とは言え、/etc/environment を Chef の Encrypted Data Bag 等で構成
管理するのも管理レイヤーが違うためモヤモヤします。それに、稼働中の
プロセスの環境変数が書き換わったか確認するのは、なかなか面倒です。

以上の問題を yaml_vault が解決してくれました。@joker1007 さんに感謝!

運用例

例えばこんな config/secrets.yml があったとします。development と
test は隠す必要がないためベタ書きですが、staging と production は
環境変数で設定しています。

development:
  secret_key_base: c4eeb5e80b2fbcc568efc7b8c2587a274330dfd7ce6b023d7049d61f682fcef88b7c9106b27bb7aa8d3750ea0a64008f94508ac45feaffc1ace638fa2a4c14ca

test:
  secret_key_base: 1d7a7dc6e551abe00bd1f8aa87f43cec198bcd0689a812d74c5344da9af89a965f29a4e00420c565a6f5b0908bde523ad08f6594f2878c44fc3321bf53b33f87

staging:
  secret_key_base: <%= ENV['SECRET_KEY_BASE'] %>
  bugsnag_api_key: <%= ENV['BUGSNAG_API_KEY'] %>

production:
  secret_key_base: <%= ENV['SECRET_KEY_BASE'] %>
  bugsnag_api_key: <%= ENV['BUGSNAG_API_KEY'] %>

一旦、ベタ書きにします。

development:
  secret_key_base: c4eeb5e80b2fbcc568efc7b8c2587a274330dfd7ce6b023d7049d61f682fcef88b7c9106b27bb7aa8d3750ea0a64008f94508ac45feaffc1ace638fa2a4c14ca

test:
  secret_key_base: 1d7a7dc6e551abe00bd1f8aa87f43cec198bcd0689a812d74c5344da9af89a965f29a4e00420c565a6f5b0908bde523ad08f6594f2878c44fc3321bf53b33f87

staging:
  secret_key_base: 955ea7c99a3069837ef818b1b962ced42a6c4d6d80d0537103a2b4c5cb9e0d1b0ea0bc32d772e1334c284d93787558564fcec2f8fbe7e4334dea6234b2ee27b1
  bugsnag_api_key: 0123456789

production:
  secret_key_base: 3fbeb3a538327484033ceaabc6454ed5a8d7dee9d5875b5b6b4c3cffc4bb461c13783ab9dd6a0cd78be310882649d116fb2b1276a9c324faa86ade594b69acb2
  bugsnag_api_key: 0123456789

以下のコマンドを実行します。

$ bundle exec yaml_vault encrypt config/secrets.yml \
-o config/encrypted_secrets.yml -k production,staging \
--cryptor=aws-kms --aws-kms-key-id=alias/hoge-rails

暗号化された config/encrypted_secrets.yml が作られます。

---
development:
  secret_key_base: c4eeb5e80b2fbcc568efc7b8c2587a274330dfd7ce6b023d7049d61f682fcef88b7c9106b27bb7aa8d3750ea0a64008f94508ac45feaffc1ace638fa2a4c14ca
test:
  secret_key_base: 1d7a7dc6e551abe00bd1f8aa87f43cec198bcd0689a812d74c5344da9af89a965f29a4e00420c565a6f5b0908bde523ad08f6594f2878c44fc3321bf53b33f87
staging:
  secret_key_base: AQECAHi181o2hUvlZ9UTXBtv1MzPPujmGDFezmSybnYV90TnAwAAAOwwgekGCSqGSIb3DQEHBqCB2zCB2AIBADCB0gYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAy3dSJNIu/qCeKnZpsCARCAgaRAnkrMBvl9uUHOIawv5JkjH7BhGQluET8XVzVfar6md9GC9x3WF55kW7+ZGeY5Y5I+LtLiOaghH/2rZfIw/bIdjU1nkflnGyQpTnD97sbqIzr6OcFLUH5lLv4WXkTk07hlzLERg9sSQ6rGUMgUCtWyP1cwKyb/2C3rl4DpZu9+gCwKU4hCGFeYUWEFV/MQ9dO/0RbetVUw/WZ+G3ySnB9AVqOVMA==
  bugsnag_api_key: AQECAHi181o2hUvlZ9UTXBtv1MzPPujmGDFezmSybnYV90TnAwAAAHEwbwYJKoZIhvcNAQcGoGIwYAIBADBbBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDMm0fS5bpOEx/elwkgIBEIAuCsJ365ViKogCNKFsrQmr5yh8KYgkWWulSFcAmGnf+y97/ZudS3JqDK7QbXSzTw==
production:
  secret_key_base: AQECAHi181o2hUvlZ9UTXBtv1MzPPujmGDFezmSybnYV90TnAwAAAOwwgekGCSqGSIb3DQEHBqCB2zCB2AIBADCB0gYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAxMSH3wGwI9iMEm/foCARCAgaTzl9w/NXy3bGSlmlilQffQkofaUNmG/eODW7cRoRlCEyYTSp5yZk0eLcLO6SU8AqC3lM5AfJyGtFY4/oXjQwVub3z/33ud/A9UKiEBXEHEODm0/kd4eldkLdna/e2st74XG5qsO9t7pmKlcKFPzZGG1x9rNetyuJGOmvEvz9ZpAyC2obYCl3itrVGlsrElX7VTYqVPLON/PwWSXdq+79zL4j6rzQ==
  bugsnag_api_key: AQECAHi181o2hUvlZ9UTXBtv1MzPPujmGDFezmSybnYV90TnAwAAAHEwbwYJKoZIhvcNAQcGoGIwYAIBADBbBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDBtD3T8V6xkOq9bdsQIBEIAu8s0QcAsrULVMdgdycg5u4rU02seGa1sszDBxxXnKQ3KoQPUB0HGcGNksZUFqlw==

※ この例では $AWS_ACCESS_KEY_ID, $AWS_SECRET_ACCESS_KEY,
$AWS_DEFAULT_REGION を direnv で設定しています。設定しない場合はそ
れぞれ –aws-access-key-id, –aws-secret-access-key, –aws-region
オプションが必要です。

今後は、作成された config/encrypted_secrets.yml を git で管理して
いきます。config/secrets.yml は git 管理下から外し、.gitignore に
追加しておきます。

以下のコマンドをデプロイ時の hook に仕掛ければ、Production と
Staging の Rails は環境変数を使うことなく config/secrets.yml を
参照することが出来ます。

$ bundle exec yaml_vault decrypt config/encrypted_secrets.yml \
-o config/secrets.yml -k production,staging \
--cryptor=aws-kms --aws-kms-key-id=alias/hoge-rails

※ EC2 インスタンスに IAM Role を付けることを忘れないようにしましょ
う。でないと、$AWS_ACCESS_KEY_ID, $AWS_SECRET_ACCESS_KEY,
$AWS_DEFAULT_REGION の設定が必要になり、本末転倒です。

この例では Development と Test 環境は単純コピーで良いです。

$ cp config/encrypted_secrets.yml config/secrets.yml

事前準備

Gemfile に以下を追記し、bundle install しておきます。

group :development do
  gem 'yaml_vault'
end

AWS IAM のコンソールから KMS の Encryption Key を作成します。
Region は前述の $AWS_DEFAULT_REGION と合わせておきます。

https://console.aws.amazon.com/iam/home#encryptionKeys

今回は hoge-rails という alias の Encryption Key を作りました。

最初に紹介した記事 では IAM Group が使える Encryption Key にしてい
ますが、数人規模のチームなら専用の IAM User を作っても良いかもしれ
ません。

あと、サーバではなくアプリが必要とするリソースなので、Terraform で
管理するかは議論の余地があると思います。

事前準備はこれだけでした・・・!

追記(2016-12-02):
https://github.com/joker1007/yaml_vault/pull/6 がマージされたので、
Gemfile の記述をアップデートしました。