# 今週何知った? week:21 [![hackmd-github-sync-badge](https://hackmd.io/CFlTER5rRHy37AW44sisZw/badge)](https://hackmd.io/CFlTER5rRHy37AW44sisZw) > [name=ken3ypa] ## 秘匿情報の出力どうしてますか - ログに意図せず秘匿情報が出てしまうこともある - SentryやDatadogなどでうっかり見えてしまうことも - これを防ぎたい ### Railsで用意してくれている機能 - `ActiveSupport::ParameterFilter` ### Rails5.2まで application.rb に下記の設定を追加することで、内部的に `ActionDispatch::Http::ParameterFilter` を利用してフィルタしてくれていた ``` > config.filter_parameters += [:password', :code] ``` ``` Started POST "/hoge.json" for 127.0.0.1 at 2022-01-01 10:00:00 +0900 Processing by HogeController#create as JSON Parameters: {"email"=>"hoge@example.com", "password"=>"[FILTERED]", "transaction_code"=>"[FILTERED]"} Completed 201 Created in 17ms (Views: 0.2ms | ActiveRecord: 7.4ms) ``` しかしあくまでもリクエストパラメータの値だけマスクをするので、自分で、logger.info(params) とかした場合はマスクされない。 ### Rails6.0から - ActiveSupport::ParameterFilter が導入 - Rails 6.x から、ActionDispatch::Http::ParameterFilter は Deprecated になり ActiveSupport::ParameterFilter に移動された - https://github.com/rails/rails/blob/6-0-stable/actionpack/lib/action_dispatch/http/parameter_filter.rb #### 特定のパラメータをフィルタする場合 ```ruby $ rails c > params = {hoge: "fuga", password: "verysecretpassowrd"} => {:hoge=>"fuga", :password=>"verysecretpassowrd"} > ActiveSupport::ParameterFilter.new(["password"]).filter(params) => {:hoge=>"fuga", :password=>"[FILTERED]"} ``` #### Modelの属性をフィルタリングする場合 - `filter_attributes` を使う - https://api.rubyonrails.org/classes/ActiveRecord/Core/ClassMethods.html - https://github.com/rails/rails/pull/33756 ``` diff --git a/app/models/user.rb b/app/models/user.rb index 8324f48..cca7059 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -11,4 +11,5 @@ class User < ApplicationRecord validates :name, presence: true validates :email, presence: true + self.filter_attributes = [:email] end ``` ```ruby irb(main):018:0> User.create(name: "hoge", email: "hoge@example.com") TRANSACTION (0.2ms) BEGIN User Create (2.7ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["name", "hoge"], ["email", "hoge@example.com"], ["created_at", "2022-06-25 06:30:49.220644"], ["updated_at", "2022-06-25 06:30:49.220644"]] TRANSACTION (0.6ms) COMMIT => #<User:0x000000010c0be188 id: 1, name: "hoge", email: "[FILTERED]", created_at: Sat, 25 Jun 2022 06:30:49.220644000 UTC +00:00, updated_at: Sat, 25 Jun 2022 06:30:49.220644000 UTC +00:00> irb(main):019:0> User.last User Load (6.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1 [["LIMIT", 1]] => #<User:0x000000010c6cf2c0 id: 1, name: "hoge", email: "[FILTERED]", created_at: Sat, 25 Jun 2022 06:30:49.220644000 UTC +00:00, updated_at: Sat, 25 Jun 2022 06:30:49.220644000 UTC +00:00> ``` また、正規表現を指定することも可能。そのため、フィルタ漏れを防ぐために ActiveRecord::Base へ秘匿情報にあたりそうな単語を部分一致で 定義しておく方法も可能 ```ruby class ApplicationRecord < ActiveRecord::Base primary_abstract_class self.filter_attributes = [/password/] end ```