Rails5.2から追加された credentials.yml.enc のキホン

# ポイント💡

とりあえず`credentials.yml.enc`の編集・書き方・読み取り方法を知りたい方はここだけをご覧になっていただければOKです。

## credentials.yml.enc を 編集する📝

```shell-session
$ EDITOR="vi" bin/rails credentials:edit
```

## credentials.yml.enc の 書き方 と 読み取り方法 📖

```yaml:credentials.yml.enc
aws:
  access_key_id: 123
  #=> Rails.application.credentials.aws[:access_key_id]

secret_key_base: 8be8e637d755f79c799048bed8be0c...
#=> Rails.application.credentials.secret_key_base
```

---
<br>

# secrets.yml はどこへ消えた？ 🤔

Rails5.2では新規アプリを作成した時に`config/secrets.yml`が生成されず、代わりに`config/credentials.yml.enc`が生成されるようになりました。

**credentials.yml.enc**の使い方について調べた内容を備忘録として投稿させていただきます。

---
<br>

# credentials.yml.enc の編集方法 📝


## ファイルを直接編集することはできない

**credentials.yml.enc**の内容は暗号化されてるため、エディタなどで直接ファイルを開いて編集することはできません。

```yaml:config/credentials.yml.enc
Q+GBLmbxagoirjyHWkJDdaMdg0cJR...
```

**credentials.yml.enc**を編集するためには`rails credentials:edit`コマンドを実行します。

## EDITORが未指定の場合は編集することができない

**credentials.yml.enc**の編集には**環境変数：EDITOR**に指定されてるエディタが利用されます。**環境変数：EDITOR**が未設定の状態で`rails credentials:edit`を実行した場合は以下のようなメッセージが表示されます。

```shell-session
$ rails credentials:edit

No $EDITOR to open file in. Assign one like this:

EDITOR="mate --wait" bin/rails credentials:edit

For editors that fork and exit immediately, it's important to pass a wait flag,
otherwise the credentials will be saved immediately with no chance to edit.
```

## EDITORを指定して編集する

`vi`を利用して**credentials.yml.enc**を編集する場合は、**環境変数：EDITOR**に**vi**を指定して`rails credentials:edit`コマンドを実行します。

```shell_session
$ EDITOR="vi" bin/rails credentials:edit
```

.bash_profileなどに**環境変数：EDITOR**を指定しておけば、`EDITOR="xxx"`の指定は不要になります。

```shell-session
# .bash_profileに環境変数 EDITOR を設定する
$ echo 'export EDITOR="vi"' >> ~/.bash_profile
$ source ~/.bash_profile
$ echo $EDITOR
  #=> vi

$ bin/rails credentials:edit
```

```yaml:credentials.yml.enc
# 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: 8be8e637d755f79c799048bed8be0c...
```

---
<br>

# credentials.yml.enc の読み取り方法 📖

**credentials.yml.enc**に設定した資格情報を取り出すには**Rails.application.credentials.xxx**を指定します。

```yaml:credentials.yml.enc
aws:
  access_key_id: 123
  #=> Rails.application.credentials.aws[:access_key_id]
  secret_access_key: 345
  #=> Rails.application.credentials.aws[:secret_access_key]

secret_key_base: 8be8e637d755f79c799048bed8be0c...
#=> Rails.application.credentials.secret_key_base
```

例：rails consoleを利用したcredentials.yml.encの読み取り

```shell-session
$ rails c

irb(main):001:0> Rails.application.credentials.aws[:access_key_id]
=> 123

irb(main):002:0> Rails.application.credentials.aws[:secret_access_key]
=> 345

irb(main):003:0> Rails.application.credentials.secret_key_base
=> "8be8e637d755f79c799048bed8be0c..."

irb(main):004:0> exit
```

---
<br>

# credentials.yml.enc の暗号化・復号 🔑

## config/master.key

`credentials.yml.enc`は**master key**を利用して暗号化・復号されます。
デフォルトの**master key**の値は`config/master.key`に記載されてます。

```text:config/master.key
cee513823adb2cda09b6c08b2b5508..
```

Rails5.2が生成する**.gitignore**では`/config/master.key`が標準で指定されており、**master key**がGitリポジトリに含まれないように配慮されてます。

```text:.gitignore
# Ignore master key for decrypting credentials and more.
/config/master.key
```

`/config/master.key`が存在しない状態で**rails credentials:edit**コマンドを実行した場合、`/config/master.key`が生成されます。

```shell-session
$ bin/rails credentials:edit

Adding config/master.key to store the master encryption key: 0c31e7f7da70866fe43d4f2cb93a56c2

Save this in a password manager your team can access.

If you lose the key, no one, including you, can access anything encrypted with it.

      create  config/master.key
```

## 環境変数：RAILS_MASTER_KEY

`/config/master.key`が共有できない環境では**master key**を**環境変数：RAILS_MASTER_KEY**で指定します。

`/config/master.key`が存在せず、**環境変数：RAILS_MASTER_KEY**で**master key**が設定されてない場合は**credentials.yml.enc**内のデータは読み取れません。


```shell-session
$ rails c

irb(main):001:0> Rails.application.credentials.secret_key_base
=> nil
```

/config/master.key`が存在しなくても、**環境変数：RAILS_MASTER_KEY**で**master key**を設定した場合は**credentials.yml.enc**内のデータが読み取れるようになります。

```shell-session
$ export RAILS_MASTER_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$ rails c

irb(main):001:0> Rails.application.credentials.secret_key_base
=> cee513823adb2cda09b6c08b2b5508..
```

---
<br>

# config.require_master_key設定 ⚙️

本番環境では**master key**の指定漏れを防ぐために`config/environments/production.rb`で**config.require_master_key = true**を有効化することが推奨されてるようです。

```ruby:config/environments/production.rb
config.require_master_key = true
```

上記オプションが有効の場合、**master key**が指定されてない状態でサーバ起動を実行しようとするとエラーが発生します。

```shell-session
$ rails s

=> Booting Puma
=> Rails 5.2.0 application starting in development
=> Run `rails server -h` for more startup options
Missing encryption key to decrypt file with. Ask your team for your master key and write it to /xxx/my-app/config/master.key or put it in the ENV['RAILS_MASTER_KEY'].
Exiting
```

---
<br>

# 参考 🗂
[Rails Encrypted Credentials on Rails 5\.2](https://www.engineyard.com/blog/rails-encrypted-credentials-on-rails-5.2)