Ruby on Rails 7から導入されたActive Record Encryptionを使ってみたところ大分良さそうだったので使い方とかをメモしてきます🗒
Active Record Encryptionとは?
Active Record Encryptionは、Rails 7から導入されたActive Recordの新機能です。
特定の属性値をシンプルなDSLで暗号化して扱うことができます。
Active Record Encryptionを使ってみる
Active Record Encryptionの初期設定
Active Record Encryptionで暗号化を行うのに必要な秘密情報を以下のコマンドで生成しcredentialsに設定します。
bin/rails app:db:encryption:init Add this entry to the credentials of the target environment: active_record_encryption: primary_key: EGY8WhulUOXixybod7ZWwMIL68R9o5kC deterministic_key: aPA5XyALhf75NNnMzaspW7akTfZp0lPY key_derivation_salt: xEY0dt6TZcAMg52K7O84wYzkjvbA62Hz
これだけで使う準備はOKです🙆♂️
Active Record Encryptionで暗号化してみる
例えばユーザー作成後にトークンを送信して存在確認したい時に以下のような実装を行なったとします。
class Account::ConfirmationToken < ApplicationRecord belongs_to :account validates :token, presence: true validates :expired_at, presence: true scope :active, ->(now: Time.current) { where("expired_at >= ?", now) } after_initialize do |record| record.token ||= SecureRandom.urlsafe_base64(32) record.expired_at ||= 1.day.ago end end
今回の例ではトークンの有効期限は1日でありハッシュ化は行わないという判断をしていますが、 DBに存在する値が何かしらの理由により漏れた場合に不正に存在確認がされてしまう恐れがあります。
このようなリスクを軽減するために以下のようにencrypts :name
のような形式で記載するだけで暗号化して保存することができます。
※deterministic: true
は決定論的暗号化を使用するフラグ値です。一意制約をDBに設定するケース等、同一の値を常に同一の暗号化結果とするためにはdeterministic: true
を設定します。
class Account::ConfirmationToken < ApplicationRecord belongs_to :account validates :token, presence: true validates :expired_at, presence: true encrypts :token, deterministic: true scope :active, ->(now: Time.current) { where("expired_at >= ?", now) } after_initialize do |record| record.token ||= SecureRandom.urlsafe_base64(32) record.expired_at ||= 1.day.ago end end
以下のように${name}_before_type_cast
で実際にDBに保存されている値を閲覧できますが、アプリケーション内で使う分には暗号化されていることを気にせず利用することができます。
Account::ConfirmationToken.create(account: @account, token: "generated_token_1") token = Account::ConfirmationToken.find_by(token: "generated_token_1") token.token # => "generated_token_1" token.token_before_type_cast # => "{\"p\":\"4P8OBmTH31wihhJq++M1iuU=\",\"h\":{\"iv\":\"Wox4jyGiHXpaaEXN\",\"at\":\"4FZ5dHQFKGnBJacTK0PttA==\"}}"
1行追加するだけで利用できて非常に便利ですね✨
Tips: 暗号化に必要な秘密情報をconfigで管理する
Active Record Encryptionは非常に便利なのですがcredentialsに暗号化に必要な秘密情報を格納する方式ではテスト環境等で少し扱いが困るかなと思ったのですが、 以下のようにconfigでも管理できるのでテスト環境とか開発環境ではconfingの値を使ってcredencialsは修正しなくても使えるようにも出来ます。
module Dummy class Application < Rails::Application config.active_record.encryption.primary_key = "foo" config.active_record.encryption.deterministic_key = "bar" config.active_record.encryption.key_derivation_salt = "baz" end end
6 Configuration
- primary_key: The key or lists of keys used to derive root data-encryption keys. The way they are used depends on the key provider configured. It's preferred to configure it via a credential > active_record_encryption.primary_key.
- deterministic_key: The key or list of keys used for deterministic encryption. It's preferred to configure it via a credential active_record_encryption.deterministic_key.
- key_derivation_salt: The salt used when deriving keys. It's preferred to configure it via a credential active_record_encryption.key_derivation_salt. Active Record Encryption — Ruby on Rails Guides