rails 5.1のEncrypted secretsを試す

Rails 5.1で出た機能Encrypted secretsを試しました。
secrets.ymlに素のまま置きたくないpasswordなどを暗号化して保存することができます。

暗号化したsecretsをgitにおき、鍵は別の方法で開発者間で共有します。
開発者は鍵を利用して`secrets.yml`を編集することで暗号化したymlをgitにあげます。

rails 5.1の他の変更点

http://weblog.rubyonrails.org/2017/4/27/Rails-5-1-final/

### 環境

- ruby 2.4.1
- rails 5.1.0

docker-compose上で試している

### 初期化する

```
-> % docker-compose run web rails secrets:setup
Adding config/secrets.yml.key to store the encryption key: deadbeaf

Save this in a password manager your team can access.

If you lose the key, no one, including you, can access any encrypted secrets.

      create  config/secrets.yml.key

Ignoring config/secrets.yml.key so it won't end up in Git history:

      append  .gitignore

Adding config/secrets.yml.enc to store secrets that needs to be encrypted.

      create  config/secrets.yml.enc

For now the file contains this but it's been encrypted with the generated key:

# See `secrets.yml` for tips on generating suitable keys.
# production:
#  external_api_key: 1466aac22e6a…

You can edit encrypted secrets with `bin/rails secrets:edit`.
Add this to your config/environments/production.rb:
config.read_encrypted_secrets = true
```

ファイルが2つできている

```
-> % cat config/secrets.yml.enc
SVbgmGN/kpgbDPFdpV0eWhCYoAx0Aot57ZAGkAa9wmR5KqiXvpkbn+7jlSeV/17ARNVoHz/ho5SnGoiAUujEH6sEqbQt1vl22sYd46mkZ9FUAosLY82Tac3iHUk5o/dZsUQbtGQeWiuBd4P8ZXs1yJJHZOlGjoYCR9+M1WoZzqoFDYA1ZqQ6GQQn1m4iYQ==--dbyevwPBti9LYDJF--rHtrj7H74h3bALjgdKM2Yg==%
-> % cat config/secrets.yml.key #編集しています
deadbeef
```

`secrets.yml.enc`は暗号化されたymlであり、こちらはgitに含める。
`secrets.yml.key`はマスターキーであり、gitに含めない。(`.gitignore`に登録される)

```
-> % cat .gitignore

...

# Ignore encrypted secrets key file.
config/secrets.yml.key
```

### secretsを追加する

#### 準備

適当なタスクを準備
`${Rails app名}::Application.secrets`によって`encrypted_secrets`にアクセスすることが出来る。

```rb
namespace :password do
  desc "hogehoge"
  task exec: :environment do
    unless Myapp::Application.secrets[:PASS]&.match "HOGE"
      puts "invalid password"
      next
    end
    puts "valid password!!"
  end
end
```

development環境でも`encypted_secrets`を読み込めるようにする

```diff
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 5187e22..782f65e 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -51,4 +51,5 @@ Rails.application.configure do
   # Use an evented file watcher to asynchronously detect changes in source code,
   # routes, locales, etc. This feature depends on the listen gem.
   config.file_watcher = ActiveSupport::EventedFileUpdateChecker
+  config.read_encrypted_secrets = true
 end
```

#### 実際に追加してみる

(dockerにエディタを入れないといけない)

```
-> % docker-compose run -e EDITOR=vim web rails secrets:edit
```

`secrets.yml`の編集画面になる

```yaml
# See `secrets.yml` for tips on generating suitable keys.
# production:
#  external_api_key: 1466aac22e6a869...

development:
  PASS: HOGE
```

保存すると`secrets.yml.enc`に更新が入る

```diff
diff --git a/config/secrets.yml.enc b/config/secrets.yml.enc
ndex 7d71232..83b1ba3 100644
-- a/config/secrets.yml.enc
++ b/config/secrets.yml.enc
@ -1 +1 @@
SVbgmGN/kpgbDPFdpV0eWhCYoAx0Aot57ZAGkAa9wmR5KqiXvpkbn+7jlSeV/17ARNVoHz/ho5SnGoiAUujEH6sEqbQt1vl22sYd46mkZ9FUAosLY82Tac3iHUk5o/dZsUQbtGQeWiuBd4P8ZXs1yJJHZOlGjoYCR9+M1WoZzqoFDYA1ZqQ6GQQn1m4iYQ==--dbyevwPBti9LYDJF--rHtrj7H74h3bALjgdKM2Yg==
 No newline at end of file
LQPWdUgL6dQELfbi4mXqSty2R+JUujiobQZRkPoHENEAKbOAOmYxo3+LgML1AWiNdzlHIsh8pLLfNIDPco4iFSNUcElPz1i5vQayZJLRDNUmA1DJvqiOpFwDqdm1SOW3m24d+HN/f7GZK1uU/yAg4JLcyOeb7pDpSIzOJfpgzizgv+olFabd+yJtndqG7AmKP2OFgRp9t56zBXrgCHUrytdhRI0tbkPOtw==--EkVRI7FweyPLNBfP--3gMfN2
X41SoVHFGcniAFQ==
 No newline at end of file
```

#### 実行

タスクを実行してみる

```
-> % docker-compose run web rails password:exec
valid password!!
```

鍵を移して再実行する

```
-> % mv config/secrets.yml.key .
-> % docker-compose run web rails password:exec
rails aborted!
Rails::Secrets::MissingKeyError: Missing encryption key to decrypt secrets with. Ask your team for your master key and put it in ENV["RAILS_MASTER_KEY"]
```

`RAILS_MASTER_KEY`を設定していないと怒られる
設定して再度実行する。

```
-> % docker-compose run -e RAILS_MASTER_KEY=deadbeef web rails password:exec
valid password!!
```

### 所感

passwordやAWSのcredentialを管理しなくてよいのはセキュリティ的に嬉しい。
運用すべきものが`secrets.yml.key`や`RAILS_MASTER_KEY`のみになるので運用コストも少し楽になる。
(しかし実際どうやって運用すべきかは要検討)

アクセス制限をかけたS3に置いてansibleなどからGETするのが簡単か？
vaultを利用しているのならそこから取得でも良さそうだけど、それなら全部vaultでよい？

### 参考にしたサイト

- http://qiita.com/kikunantoka/items/ab9d612abc213c734183
- http://www.starkandwayne.com/blog/rails-5-1-applications-can-be-a-lot-more-secretive-on-cloud-foundry-and-heroku/