Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/logtail-rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def self.integrate!
ActionView.integrate!
ActiveRecord.integrate!
RackLogger.integrate!
filter_parameters_in_urls(::Rails.application.config.filter_parameters)
end

def self.enabled=(value)
Expand All @@ -71,6 +72,16 @@ def self.middlewares
@middlewares ||= [Logtail::Integrations::Rack::HTTPContext, SessionContext, Logtail::Integrations::Rack::UserContext,
Logtail::Integrations::Rack::HTTPEvents, Logtail::Integrations::Rails::ErrorEvent].select(&:enabled?)
end

# Filters the app's filter_parameters from the query strings and the Referer and Location
# URLs that Rack::HTTPEvents logs, unless the app customised its query_string_filters.
# Procs are left out: they rewrite values, while query string filters match names.
def self.filter_parameters_in_urls(filter_parameters)
http_events = Logtail::Integrations::Rack::HTTPEvents
return if http_events.query_string_filters != http_events::DEFAULT_QUERY_STRING_FILTERS

http_events.query_string_filters = filter_parameters.reject { |filter| filter.is_a?(Proc) }
end
end
end
end
63 changes: 63 additions & 0 deletions spec/logtail-rails/http_events_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,69 @@ def method_for_action(action_name)
end
end

describe "query string filters" do
around(:each) do |example|
class RackHttpRedirectController < ActionController::Base
layout nil

def index
redirect_to "/next?email=jane%40example.com&step=2"
end

def method_for_action(action_name)
action_name
end
end

::RailsApp.routes.draw do
get '/rack_http_redirect' => 'rack_http_redirect#index'
end

example.run

Object.send(:remove_const, :RackHttpRedirectController)
end

it "should filter the app's filter_parameters from the query string, the Referer and the Location" do
dispatch_rails_request("/rack_http_redirect?email=jane%40example.com&page=2&password=hunter2",
"HTTP_REFERER" => "https://example.com/signup?email=jane%40example.com&ref=ad")

rows = io.string.split("\n").map { |line| JSON.parse(line) }
http_request_received = rows.map { |row| row.dig("event", "http_request_received") }.compact.first
expect(http_request_received["query_string"]).to eq("email=[FILTERED]&page=2&password=[FILTERED]")
expect(JSON.parse(http_request_received["headers_json"])["Referer"]).to eq("https://example.com/signup?email=[FILTERED]&ref=ad")

http_response_sent = rows.map { |row| row.dig("event", "http_response_sent") }.compact.first
_name, location = JSON.parse(http_response_sent["headers_json"]).find { |name, _value| name.casecmp("location").zero? }
expect(location).to eq("http://example.org/next?email=[FILTERED]&step=2")
end

it "should use the app's filter_parameters without Procs, when query_string_filters are rack's default" do
with_query_string_filters(described_class::DEFAULT_QUERY_STRING_FILTERS) do
Logtail::Integrations::Rails.filter_parameters_in_urls([:email, /\Apin\z/, ->(_key, value) { value.replace("[FILTERED]") }])

expect(described_class.query_string_filters).to eq([:email, /\Apin\z/])
end
end

it "should keep query_string_filters that the app customised" do
with_query_string_filters(described_class::DEFAULT_QUERY_STRING_FILTERS + ["code"]) do
Logtail::Integrations::Rails.filter_parameters_in_urls([:email])

expect(described_class.query_string_filters).to eq(described_class::DEFAULT_QUERY_STRING_FILTERS + ["code"])
end
end

def with_query_string_filters(filters)
previous = described_class.query_string_filters
described_class.query_string_filters = filters

yield
ensure
described_class.query_string_filters = previous
end
end

# Remove blank lines since Rails does this to space out requests in the logs
def clean_lines(lines)
lines.select { |line| !line.start_with?(" @metadat") }
Expand Down
2 changes: 2 additions & 0 deletions spec/support/rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class RailsApp < Rails::Application
config.active_support.deprecation = :stderr
config.eager_load = false
config.hosts = nil
# What config/initializers/filter_parameter_logging.rb sets in new Rails 8 apps
config.filter_parameters += [:passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn, :cvv, :cvc]
end

RailsApp.initialize!
Expand Down
Loading