credentials.yml.enc を使ってGmailのアプリパスワードを安全に管理する

# 前提

- バージョンは `Rails 5.2.3` です。
- `credentials.yml.enc` は 5.2 から追加されたようです。

```
$ rails -v
Rails 5.2.3
```

# 経緯

先日私が書いた記事で、Gmailと連携してRailsにメール送信の機能を実装しました。

- [Railsでメール送信機能を実装する手順を結構丁寧に(development環境編)](https://qiita.com/Tsubasa_Shida/items/7866b54f13fb0ce01462)

この記事にもあるように、Gmailと連携するためにはGmailのメールアドレスとアプリパスワードを設定する必要があります。

```config/environments/development.rb
Rails.application.configure do

  #...(中略)...

  # コメントアウトすることでdevelop環境からもメールを送信する設定になる
  # config.action_mailer.raise_delivery_errors = false

  config.action_mailer.delivery_method = :smtp

  config.action_mailer.smtp_settings = {
      :enable_starttls_auto => true,
      :address => 'smtp.gmail.com',
      :port => 587,
      :domain => 'gmail.com',
      :authentication => :plain,
      # メールアドレス
      :user_name => 'xxxxx@gmail.com',
      # アプリパスワード
      :password => 'aaaabbbbccccdddd'
  }
end
```

ただ、メールアドレスとアプリパスワードについては外部には公開したくない情報となるため、例えば `config/environments/development.rb` などにハードコーディングしてGitHubなどにpushすることは避けたいものです。

また、このような情報は複数人で開発している場合は、「ハードコーディングでpushしたくないけど、全員で共有したいもの」となります。

このような機密情報を、安全に、かつチーム内で共有できるように管理するために、Railsには `credentials.yml.enc` というファイルが用意されています。

# 使い方

実際に使いながら、説明していきます。

## 機密情報を記述する

- 機密情報などは、`config/credentials.yml.enc` に記述し、これをpushしてチーム内で共有します。
- ただ、`config/credentials.yml.enc` は暗号化されているため、エディタで開くことはできても、何が書いてあるかさっぱりわからないのでそのまま編集することはできません(だからpushしても安全なのですが)。
- そんな `config/credentials.yml.enc` を編集するためには、以下のコマンドを使います。

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

- このコマンドを打つことで以下のようにエディタが開くので、機密情報を入力して `:wq` で保存します。
- 入力例として `aws:` がすでに記述されていますので、これを参考にして同じようなインデント構成で打ちます。

```
# aws:
#   access_key_id: 123
#   secret_access_key: 345

# ここから
gmail:
  mail_address: xxxxx@gmail.com
  app_password: aaaabbbbccccdddd
# ここまで

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: *******************************************************************************
```

## 機密情報を参照させる

- 上記で設定した機密情報をソース内で参照させるようにするには、以下のように記述します。

```config/environments/development.rb
Rails.application.configure do

  #...(中略)...

  # コメントアウトすることでdevelop環境からもメールを送信する設定になる
  # config.action_mailer.raise_delivery_errors = false

  config.action_mailer.delivery_method = :smtp

  config.action_mailer.smtp_settings = {
      :enable_starttls_auto => true,
      :address => 'smtp.gmail.com',
      :port => 587,
      :domain => 'gmail.com',
      :authentication => :plain,
      # メールアドレス(参照している)
      :user_name => Rails.application.credentials.gmail[:mail_address],
      # アプリパスワード(参照している)
      :password => Rails.application.credentials.gmail[:app_password]
  }
end
```

これでハードコーディングを避けることができました。実装自体はとても簡単ですね。

# 復号化について

- コマンドを打って機密情報を編集したり、ソース内で参照することができたりするのは、内部で `config/credentials.yml.enc` を復号化しているからです。復号化に必要な鍵が `/config/master.key` です。
- つまり、各々のローカル環境に同じ `/config/master.key` を持つようにする(もちろんGitHubなどを使わずに、ですが)ことで、チーム全員が機密情報を編集することができるようになります。

## 鍵をバージョン管理外にする

- Rails 5.2 からは、以下のように `.gitignore` にあらかじめ `/config/master.key` をバージョン管理外にする設定が記述されています。
- それ以前のバージョンからアップデートした場合は、`.gitignore` への手動記述が必要です。

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

## 鍵の内容を環境変数に設定する

- `/config/master.key` を共有できない場合は、環境変数 `RAILS_MASTER_KEY` に `/config/master.key` の内容を設定することで、同じように復号化できるようになります。
- 本番環境や検証環境のサーバ内では`/config/master.key` を持たずに環境変数を設定することになるのかなと思います。
- 本番環境にて、`/config/master.key` の内容を設定していない場合に、サーバ起動をできなくする設定があります。`config/environments/production.rb` に一行記述するだけです。推奨されている設定とのことなので、ぜひやっておきましょう。
- あらかじめコメントアウトされた状態で記述されているバージョンもありますので、その場合はコメントアウトを外すだけでOKです。


```config/environments/production.rb
  # 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 # コメントアウトをはずす
```

# 参考

- [Rails5.2から追加された credentials.yml.enc のキホン](https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39)