🔐

[Rails 7.1アップグレード] Active Record 暗号化されたカラムを安全に移行する

2024/12/09に公開

はじめに

私たちが開発するRYDE PASSで使用しているRuby on Rails を7.0から7.1にアップグレードする過程で、Active Recordの暗号化機能を使用したモデルで思わぬ問題が発生しました。
本記事では、その詳細と私たちが採用した安全でスムーズな移行手順をご紹介します。

RYDE PASSの詳細はこちらをご覧ください

https://zenn.dev/ryde/articles/5c2ba40d930577

概要

Rails 7.0で導入されたActive Recordの暗号化機能は、データベース内の機密データを簡単に暗号化できる非常に便利な機能です。

しかし、Rails 7.0の時点ではSHA-256で暗号化されるべきところが、SHA-1が使用されるというバグが生じていました。
Rails7.0の時点で保存された値はSHA-1で暗号化されていますが、Rails7.1でバグが修正されSHA-256で復号しようとするとエラーが発生するようになりました。

この記事では、当社がRails 7.0から7.1へのアップグレードで上記を解消するために行った手順と、対応の背景について述べていきたいと思います。

バグの詳細と解決方法

Rails 7.1にアップグレード後にAR暗号化を使用しているモデルを呼び出すと以下のエラーが出るようになります。

ActiveRecord::Encryption::Errors::Decryption 

この問題に対処するため、Rails 7.1ではSHA-1サポート用のオプション config.active_record.encryption.support_sha1_for_non_deterministic_encryption が用意されました。この設定をtrueにすると、SHA-1で暗号化された既存データの復号が可能になります。

移行の流れ

1. SHA-1サポート設定の適用

Rails 7.1でSHA-1データが復号できるよう、まずは
config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true
をconfig/application.rbに追加します。この設定により、アプリケーションを一時的にSHA-1とSHA-256の両方の暗号化方式で動作させ、移行作業中のエラーを防止します。

2. データの再暗号化

次に新しいSHA-256形式で暗号化するために、各モデルの暗号化カラムを再暗号化する必要があります。以下のコマンドを実行し、全レコードの暗号化カラムをSHA-256で再暗号化します:

YourModel.find_each(&:encrypt)

これにより、SHA-1で暗号化されていたデータがすべてSHA-256形式に変換され、データベース内の暗号化形式が統一されます。

3. SHA-1サポート設定の削除

すべてのデータをSHA-256で暗号化し終えたら、config.active_record.encryption.support_sha1_for_non_deterministic_encryption
の設定を削除します。この設定を削除することで、SHA-1形式のデータは復号できなくなりますが、すべてのデータがSHA-256で統一されているため問題は発生しません。

まとめ

Rails 7.1へのアップデートでの暗号化方式の変更は、アプリケーションのセキュリティ向上に繋がる重要なステップです。しかし、既存データの扱いを慎重に行わないと、データの復号エラーが発生するリスクもあります。今回のように、一時的な設定でSHA-1のサポートを有効にしつつ、データを再暗号化することで、安全かつ確実にSHA-256形式への移行が可能です。

この手順を実施することで、Rails 7.1の暗号化方式にスムーズに移行でき、今後のセキュリティ更新にも対応しやすくなると思います。Railsエンジニアの皆様の参考になれば幸いです。

エンジニア募集中!

最後まで読んでいただきありがとうございます!

RYDE社では、プロダクト RYDE PASS を一緒に育ててくれる仲間を探しています。
「技術が好き」「プロダクト作りにワクワクする」そんな方、ぜひ気軽にお話ししませんか?

まずはカジュアルにお話しましょう!ぜひお気軽にご連絡ください😊

https://rydeinc.notion.site/RYDE-99302bd5277c4582975d358e9cce4c6c

RYDE株式会社

Discussion