こんにちは、以前は広告技術部でエンジニアをしていましたが、最近社内転職でメディア事業部のサービスPM/POになった、サンドバーグです。最近は仕事でコードを書く機会がHTMLとJSだけになってしまったので、PM/PO関連の記事を書くと思いきや、普通にRailsについて書こうと思います!
この記事はGunosy Advent Calendar 2024 - Adventarの20日目の記事です。昨日の記事はmtjuneさんの『ECS で動く Web サーバーを安全に終了させる話』でした。 今回の記事では、開発の現場から離れたことで逆に個人で一からRailsアプリを作る機会が増え、よく直面するMaster Keyと、プロダクションリリース時のassets:precompileの問題についてお伝えします。
はじめに
このエラーメッセージ見たことあります?
Missing encryption key to decrypt file with. Ask your team for your master key and write it to config/master.key or put it in the ENV['RAILS_MASTER_KEY'].
もしくはこちら、
ArgumentError: Missing
secret_key_base
for 'production' environment, set this string withrails credentials:edit
今回記事のタイトルには Rails 7 と記載しましたが、この話自体はRails 5.2から始まっている認識です。上記のエラーは至って単純で、5.2から導入された credentials.yml.encをデコードするための Master Key が無いと怒られています。
そもそも、rails credentials:edit で機密情報などを登録していればローカル環境では何も考えずに動くはずです。master.keyは自動で用意されますし、意識しなくともアプリ起動までは行けるはず...なんですが、大体の問題は以下のissueに集約されています。
2018からissueが上げられ、DHH本人がコメントする程に長く、クローズされた後も度々オープンされ直されていて、正直綺麗な解決策が完全に確立されているとは言えない問題な気がしています。
そもそも Master Key とは
以下はChatGPTがシンプルにまとめてくれた内容です。
Railsのmaster.keyとcredentials.yml.encは、アプリケーションの秘密情報を安全に管理するための仕組みです。
credentials.yml.encは、アプリケーションの秘密情報(APIキー、データベースのパスワードなど)を暗号化して保存するためのファイルです。このファイルは暗号化されているため、そのままでは中身を読むことはできません。
一方、master.keyは、credentials.yml.encの暗号化を解除するためのキーを保存するファイルです。このキーを使用することで、credentials.yml.encの中身を読み取ることができます。
Railsアプリケーションを運用する際には、master.keyは公開リポジトリにはアップロードせず、秘密に保つ必要があります。なぜなら、このキーが漏洩すると、credentials.yml.encに保存された秘密情報が第三者に読み取られる可能性があるからです。
これらの仕組みを使用することで、秘密情報をソースコードから分離し、安全に管理することができます。
特に変な話ではなく、今までsecrets.ymlという機密情報の管理場所をエンコードしたのがcredentials.yml.encであって、それを開けるために必要なのがmaster.keyです。
問題になるのが、今までデコードを意識した本番デプロイが不要だったのと、想定外の処理でこのmaster.keyが必要とされてしまっていることです。
Docker、クラウドサービスとRailsでのMaster Key管理の課題・問題
元々貼っていたissueにもあるように、そもそもこの問題が上がったのは、Railsアプリ起動時ではなくDockerでのrails assets:precompile実行時です。
今までであれば、Railsアプリ起動時のコンテナ内で機密情報読み込みだけを意識すればよかったところ、コンテナをビルドする際のassets:precompileという機密情報が本来不要な箇所で怒られるようになってしまいました。Issueでの回答は、「タスクは関係なく、常にmaster.keyが期待されるため、想定どおりの挙動」や、「assets:precompileと一緒にrakeコマンドで生成してしまえば良い」、「ダミーを入れれば行ける」など、ワークアラウンドがメインで、結果としても以下のような対処法になっています。
普通に、タスクベースでmaster.keyの強制を解除しつつ、ダミーキーを設定して実行するという方法です。
解決策とベストプラクティス...?
結論として、master.keyが本来不要なタスクに関してはダミーの設定とmaster.keyの強制を外せば物は動きます。直近GCPのcloud buildとcloud runで作ったいくつかのアプリでも、無事ビルド・デプロイを実施できていますし、GCPのsecret managerを使ってsecret_key_baseをも渡せています。
ただ、Out-of-the-box experienceとしては毎度ここを見落としてコードをいじっている気がしているため、これが解決策だとはわかりつつも常に悩みの種になっています。
まとめ
当たり前ですが、credentials.yml.encやmaster.key自体悪い物ではないですし、機密情報をエンコードすることで事前に防げる問題も多々あると思います。Rails 7.1からDockerでの開発がほぼ前提となる方向でも進んでいますし、今後こういったちょっとした不便・悩みが解消されて行くことは楽しみです。
明日の記事は marice0819 さんの『AIニュースコメンテーターの作りました (コメント評価)』話です。お楽しみに!