Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduce AR::Encryption

Ecad9d801d79f6c6e5df93094690685e?s=47 Takumi Shotoku
September 02, 2021

Introduce AR::Encryption

Ecad9d801d79f6c6e5df93094690685e?s=128

Takumi Shotoku

September 02, 2021
Tweet

Transcript

  1. Introduce AR::Encryption Omotesando.rb #66 2021/09/02 1

  2. 自己紹介 • 名前: 神速 • 会社: メドピア株式会社 • 所属: CTO室SRE

    • GitHub: @sinsoku (画像右上) • Twitter: @sinsoku_listy (画像右下) 2
  3. AR::Encryption の使い方1 1 https://edgeguides.rubyonrails.org/activerecordencryption.html 3

  4. 4

  5. 5

  6. 属性にアクセスすると平文を返す 復号は自動的に行われる。 Article.last.title # => "Encrypt it all!" 6

  7. 基本的な挙動 1. 暗号化の種を用意 2. モデルに encrypts :attr_name を定義 3. SQLの値は自動的に暗号化

    serialize と同じ挙動だと考えると分かりやすい。 7
  8. ユースケースの紹介 8

  9. 暗号化したカラムでの find 9

  10. deterministic: true は同じ文字になる Author.create(email: 'foo@example.com') # TRANSACTION (0.0ms) begin transaction

    # Author Create (1.1ms) INSERT INTO "authors" ("email", "created_at", "updated_at") VALUES (?, ?, ?) \ # [["email", "{\"p\":\"zicjhoOToWeYJ8SLsHr0\",\"h\":{\"iv\":\"er70ewKN9j8AAd1m\",\"at\":\"BuSV3TSxAZkM8t/uD0UvtA==\"}}"], \ # ["created_at", "2021-07-09 06:39:53.651449"], ["updated_at", "2021-07-09 06:39:53.651449"]] # TRANSACTION (0.9ms) commit transaction #=> #<Author:0x00007fe1e11d51f8 id: 2, email: "foo@example.com", created_at: Fri, 09 Jul 2021 06:39:53.651449000 UTC +00:00, \ # updated_at: Fri, 09 Jul 2021 06:39:53.651449000 UTC +00:00> Author.create(email: 'foo@example.com') # TRANSACTION (0.0ms) begin transaction # Author Create (0.4ms) INSERT INTO "authors" ("email", "created_at", "updated_at") VALUES (?, ?, ?) \ # [["email", "{\"p\":\"zicjhoOToWeYJ8SLsHr0\",\"h\":{\"iv\":\"er70ewKN9j8AAd1m\",\"at\":\"BuSV3TSxAZkM8t/uD0UvtA==\"}}"], \ # ["created_at", "2021-07-09 06:39:54.587980"], ["updated_at", "2021-07-09 06:39:54.587980"]] # TRANSACTION (1.1ms) commit transaction #=> #<Author:0x00007fe1c1143a20 id: 3, email: "foo@example.com", created_at: Fri, 09 Jul 2021 06:39:54.587980000 UTC +00:00, \ # updated_at: Fri, 09 Jul 2021 06:39:54.587980000 UTC +00:00> 10
  11. ユニークバリデーションをつける 11

  12. ユニーク制約をつける 12

  13. 既存のカラムを暗号化する 暗号化していない文字列も扱えるように設定を変更する。 config.active_record.encryption.support_unencrypted_data = true モデルに encrypts を定義した後に encrypt メソッドを呼ぶ。

    Article.find_each(&:encrypt) 13
  14. 既存のカラムを暗号化する 2 レコードが多い場合は upsert_all を使う方が良さそう。 type = Article.attribute_types["title"] Article.find_in_batches do

    |group| attributes = group.pluck(:id, :title).map do |id, title| { id: id, title: type.serialize(title) } end Article.upsert_all(attributes, unique_by: :id) end 14
  15. non-deterministic -> deterministic サービス運用が始まってから「やっぱりfindしたい」となった場 合の対応方法。 class Article < ApplicationRecord encrypts

    :title, deterministic: true, previous: { deterministic: false } end 15
  16. 16

  17. Viewでの復号を禁止する # TODO: ௐ͕ࠪؒʹ߹Θͳ͔ͬͨ 17

  18. バックポート 1 関連するコードをRailsのリポジトリからコピペする。 $ mkdir lib/active_record $ cp -r ~/ghq/github.com/rails/rails/activerecord/lib/active_record/encryption*

    \ lib/active_record 18
  19. バックポート 2 # config/application.rb require 'active_record/encryption' ActiveRecord::Railtie.initializer "active_record_encryption.configuration" do |app|

    # config.active_record.encryption ૬౰ͷม਺ config_encryption = ActiveSupport::OrderedOptions.new ActiveRecord::Encryption.configure \ primary_key: app.credentials.dig(:active_record_encryption, :primary_key), deterministic_key: app.credentials.dig(:active_record_encryption, :deterministic_key), key_derivation_salt: app.credentials.dig(:active_record_encryption, :key_derivation_salt), **config_encryption # ҎԼུ end 19