RailsのCredentialsの作り方

Rails触った事ないけどある日突然production.keyを作成する事になり四苦八苦したので記録。

#Railsのproduction.keyとは

production環境の暗号化されたファイル**production.yml**を復号するためのキー。

http://www.code-magagine.com/?p=7889

暗号化されたファイルにはプロジェクトの機密情報が含まれ、暗号化されたファイルをバージョン管理し、キーはバージョン管理から外す。
production.ymlというのは作成時に環境を指定したからこの名前になっており、基本的にはcredentials.ymlというのが暗号化されたファイルの名称。

#Credentialsの作り方（基本）

####既存のキーの確認方法
下記のような感じで確認する

```shell
$ EDITOR="vi" bin/rails credentials:show
# 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: xxx
aa_bank:
  secret: yyy
  aeskey: zzz
```
例えばaa_bankのシークレット情報を暗号化したい場合は下記で編集。
暗号化するファイル名はcredential.ymlになる。
キーはmaster.keyという名前になる。

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

暗号化するファイルにproduction.ymlと名付けたい場合は下記のようにする。
`production`の部分を環境名に変える事で、環境毎にファイルとキーを作成できる。

```shell
EDITOR="vi" bin/rails credentials:edit -e production
```

　できあがるファイルは下記のような構成。

```shell
$ ls -ltr config/credentials
total 16
-rw------- 1 user user  32 Sep 16 18:38 production.key
-rw-rw-r-- 1 user user 672 Sep 16 19:26 production.yml.enc
```

#アプリからのシークレット情報呼び出し

こんな感じで呼び出すらしい。

```rb
pry(main)> Rails.application.credentials.config
=> {:aa_bank=>{:secret=>yyy, :aeskey=>zzz}}

```

https://zenn.dev/banrih/articles/f22f0a70bbead2a02110

#Rails６からの仕様ではまった
`EDITOR="vi" bin/rails credentials:edit`して作成したmaster.keyをRails6から環境変数`RAILS_MASTER_KEY`に入れておけばmaster.keyのファイル自体は不要、という仕様がある。

https://saku.hatenadiary.com/entry/2019/11/05/093755

それ自体は便利な仕様だけど、例えばアプリ担当とインフラ担当が明確に分かれていて、アプリ担当の開発環境にはmaster.keyが存在、`appname/.env`に環境変数でキーを追記してその形で受け取ったインフラ担当がRailsの仕様を知らない場合などはまる事案が発生する（自分）

具体的には、`.env`に環境変数でキーが存在する場合、`credentials:edit`しても新たに`master.key`や`-e`で指定して作成するproduction.keyなどキーが全て新たに作られない、という動きになり、作られるはずのものが作られず、でもアプリ側ではシークレットの読み込みに問題がない、という不思議状態に陥る。

###対処について

**確認方法：`RAILS_MASTER_KEY`を削除、master.keyを配置する**
これを試す時、`.env`から環境変数の記載を削除した後、サーバ上から環境変数が削除されていない事に気づかずはまった。

詳細は不明だが、railsの実行ユーザーには`.env`に記載した環境変数が追加される、という仕様っぽい。
下記はrailsでの環境変数の参照の仕方。`rails c`すら知らんかった。

```rb
$ ./bin/rails c
[fog][DEPRECATION] Fog::Storage::AWS is deprecated, please use Fog::AWS::Storage.
[fog][WARNING] Unrecognized arguments: aws_access_key_id, aws_secret_access_key, aws_session_token, aws_credentials_expire_at, region, use_iam_profile
Loading staging environment (Rails 6.1.3.2)
irb(main):001:0> ENV["RAILS_MASTER_KEY"]
=> "bbb"
irb(main):002:0>
```

環境変数を削除

```shell
export -n RAILS_MASTER_KEY
````

この状態で`credentials:edit`すると、、

```shell
$ EDITOR="vi" bin/rails credentials:edit -e test
Adding config/credentials/test.key to store the encryption key: ccc

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/credentials/test.key

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

      append  .gitignore
```

キーができた！

#上記を踏まえた実運用手順
production.keyを新たに作りたいけど、もし`.env`に`RAILS_MASTER_KEY`が存在している環境でアプリケーションを動かしているなら、下記の手順で作業をする。

```shell
#.envに記載のRAILS_MASTER_KEYの値xxxをコピペしmaster.keyを作成
cd appname
vim config/master.key
more config/master.key
xxx

# RAILS_MASTER_KEYの削除
sed -i '/^"RAILS_MASTER_KEY/d' .env
export -n RAILS_MASTER_KEY

# 削除確認
bin/rails c
ENV["RAILS_MASTER_KEY"]

# secretとキーを作成
EDITOR="vi" bin/rails credentials:edit -e production
```

出来上がったキーを`.env`の`RAILS_MASTER_KEY`に追記するのが基本的な取り扱い方らしい。
master.keyは名前のイメージとは違いdevelop用のようなものなのですね。
キーの名前だけRails5のmaster.keyの名残なのでは、との事でした。
（Rails5知りませんが）