Techioz Blog

カスタム プロシージャを使用すると、Airbrake::Filters::KeysBlacklist のパターンの 1 つが無効であるというエラーがスローされます

概要

私たちのアプリケーションでは、特定のパラメータを使用状況に応じて異なる方法でフィルタリングしたいと考えています。たとえば、パスワードは常に完全にフィルタリングする必要がありますが、電子メールと名前については、デバッグとサポートのために値の一部を保持したいと考えています。

これを行うために、カスタム proc を使用してそれらをフォーマットしました。

1_filter_parameter_logging.rb:

Rails.application.config.filter_parameters += [
  :password
]

Rails.application.config.filter_parameters << proc do |param_name, value|
  if %w[email name].include?(param_name)
    if param_name.to_s == 'email'
      value.gsub!(/(?<=^.{2}).*?(?=@)/, '*') # test partial filter
    else
      value.replace('[FILTERED_CUSTOM]') # test custom filter
    end
  end
end

次に、2_airbrake.rb でこれらの設定を次のように使用します。

c.blacklist_keys = Rails.application.config.filter_parameters

この理論をテストするために、次のサンプル コントローラー アクションを使用してアプリで意図的に例外をスローします。

class ExampleController
  def show
    raise StandardError, 'Testing Filter Parameter Logging'
  end
end

次に、そのエンドポイントに簡単なリクエストを送信します。

http://localhost:3000/example?name=cameron&[email protected]&password=test

ログには次のことが記録されています。

Processing by ExampleController#show as HTML
  Parameters: {"name"=>"[FILTERED_CUSTOM]", "email"=>"ca*@test.com", "password"=>"[FILTERED]"}

そして、Airbake からのエラー:

**Airbrake: one of the patterns in Airbrake::Filters::KeysBlacklist is invalid. Known patterns: [:password, nil]

そして、Airbrake のエラーを見ると、フィルタリングされていないことがわかります。

{
  "action" => "show",
  "controller" => "example",
  "email" => "[email protected]",
  "name" => "cameron",
  "password" => "[Filtered]"
}

Airbrake がそのエラーをスローするのはなぜですか。Rails はログに基づいてその proc を使用してパラメータをフィルタリングできるようですが、Airbrake はフィルタリングに失敗し、通過を許可します。

Airbrake は、パターンの何が無効なのかを正確に説明しません。ただ、それが有効であると認識されないだけで、あまり役に立ちません。

解決策

Rails が提供する param フィルタリングは Airbrake とは異なります。

Rails では、複雑なパラメータのフィルタリングが可能です。パラメータのキーと値を引数として受け取り、フィルタリングされた値を返すプロシージャを定義できます。プロシージャの実行は、ここ ActiveSupport::ParameterFilter#value_for_key で行われます。

エアブレーキはさらに限定的です。パラメーター名を文字列、記号、または正規表現と比較することによってのみフィルターできます。ドキュメントには、proc を定義できるが、最初の通知時に 1 回しか実行されないことが記載されています。

ここでprocが実行されます。引数なしで呼び出されます。サンプルのプロシージャが引数なしで呼び出された場合、nil が返されます。これは文字列、シンボル、または正規表現に一致しないため、ここで例外が発生します。

Airbrake は should_filter を使用しますか? param キーのみを受け取るメソッド。そのメソッドが true を返した場合、「[Filtered]」文字列が値を置き換えます。この既存の構造をすぐにオーバーライドして必要な動作を得るのは簡単ではありません。ただし、Airbrake::Filters::KeysBlocklist クラスと Airbrake::Filters::KeysFilter モジュールを完全にオーバーライドしてみることもできます。

ここの情報とすべてのリンクは airbrake-ruby の現在のバージョンのものであることに注意してください。 blacklist_keys は数年前に blocklist_keys に置き換えられました。そして、KeysBlacklist のようなクラスは KeysBlocklist に置き換えられました。ただし、これらは単なる名前の変更であり、機能は時間が経っても比較的同じままです。

標準の Airbrake パラメータ フィルタリングをオーバーライドするよりも、カスタム フィルタを追加してみる方がよいでしょう。以下は、アプリの初期化子に何を含めることができるかの例です。

Airbrake.add_filter do |notice|
  notice[:params].each do |key, value|
    if key == :email
      value.gsub!(/(?<=^.{2}).*?(?=@)/, '*')  # test partial filter
    elsif key == :name
      value.replace('[FILTERED_CUSTOM]')  # test custom filter
    end
  end
end