Slide 1

Slide 1 text

© 2024 Wantedly, Inc. Active Record Encryption と AWS KMS でエンベロープ暗号化 Dec. 18 2024 - Ryota Egusa Wantedly Tech Night #6

Slide 2

Slide 2 text

© 2024 Wantedly, Inc. Ryota Egusa @gedorinku Quality Control Squad https://www.wantedly.com/companies/ wantedly/post_articles/459966

Slide 3

Slide 3 text

© 2024 Wantedly, Inc. モチベーション データにアクセスできる範囲を制限したい ● 万が一の漏洩時の被害を抑える 1. アクセスに対して監査ログを残したい ● KMS のようなキーマネージメントサービスの機能 ● DB レベルで行うこともできる (例: pgAudit) 2.

Slide 4

Slide 4 text

© 2024 Wantedly, Inc. エンベロープ暗号化 Root Key Data Key Data 暗号化 暗号化 データごとに⽣成

Slide 5

Slide 5 text

© 2024 Wantedly, Inc. AWS KMS + エンベロープ暗号化 Root Key Data Key Data 暗号化 暗号化 AWS KMS Data Key の暗号化‧復号は KMS の中で⾏う ここは各アプリケーション 内で⾏う

Slide 6

Slide 6 text

© 2024 Wantedly, Inc. AWS KMS のメリット キーの使用時にログが残る ● Root key が AWS KMS の外に出ないので必ずログが残る 1. Root key 自体は AWS が保護してくれる ● AWS のアクセスキーが漏れることはあっても Root key が漏れる心配はなさそう 2.

Slide 7

Slide 7 text

© 2024 Wantedly, Inc. Active Record Encryption class User encrypts :foo end user = User.create(foo: "hoge") user.foo # => "hoge"

Slide 8

Slide 8 text

© 2024 Wantedly, Inc. 標準のKeyProvider DerivedSecretKeyProvider ● デフォルト ● アプリケーション全体で単一のキーを使って暗号化 1. EnvelopeEncryptionKeyProvider ● 暗号化毎にデータキーを生成、指定した Root key で暗号化 ● 暗号化されたデータキーと暗号化されたデータを一緒に保存 2.

Slide 9

Slide 9 text

© 2024 Wantedly, Inc. Active Record Encryption class CustomKeyProvider def encryption_key end def decryption_keys(encrypted_message) end end 暗号化⽤のData Keyを返す

Slide 10

Slide 10 text

© 2024 Wantedly, Inc. Active Record Encryption class CustomKeyProvider def encryption_key end def decryption_keys(encrypted_message) end end 復号⽤のData Keyを返す

Slide 11

Slide 11 text

© 2024 Wantedly, Inc. Active Record Encryption class CustomKeyProvider def encryption_key end def decryption_keys(encrypted_message) end end ドキュメントに詳しい説明はないが デフォルトの実装が参考になる https://github.com/rails/rails/blob/main/activerecord/lib/ active_record/encryption/envelope_encryption_key_prov ider.rb

Slide 12

Slide 12 text

© 2024 Wantedly, Inc. CustomKeyProvider#encryption_key resp = kms_client.generate_data_key( key_id: ENV.fetch('AWS_KMS_KEY_ID'), key_spec: 'AES_256', ) ActiveRecord::Encryption::Key.new(resp.plaintext).tap do |key| key.public_tags.encrypted_data_key = resp.ciphertext_blob end 暗号化されずに保存される

Slide 13

Slide 13 text

© 2024 Wantedly, Inc. CustomKeyProvider#decryption_keys encrypted_data_key = encrypted_message.headers.encrypted_data_key response = kms_client.decrypt({ ciphertext_blob: encrypted_data_key, key_id: ENV.fetch('AWS_KMS_KEY_ID') }) [ActiveRecord::Encryption::Key.new(response.plaintext)]

Slide 14

Slide 14 text

© 2024 Wantedly, Inc. まとめ アプリケーションレベルの暗号化によって被害を抑えログを残す ● データにアクセスできる範囲を限定し、ログを残すことができる 1. Rails と AWS KMS などを組み合わせて透過的に暗号化できる ● 暗号化キーをRailsに渡す部分だけ作る必要がある ● 暗号化処理はRailsやKMSがやってくれる 2.