For query log masks [this code](https://qiita.com/calorie/items/426fb4c23ab850122f93#activerecordlogsubscriber%E3%81%AB%E3%83%91%E3%83%83%E3%83%81 Patch ʻActiveRecord :: LogSubscriber` with% E3% 82% 92% E3% 81% 82% E3% 81% A6% E3% 82% 8B)
It refers to replacing confidential information such as personal information on the log with a specific character string to hide it. Masking is important because it reduces the risk of leaking sensitive information.
When it comes to masking logs in Rails, there is config.filter_parameters
.
This is a convenient function that masks the parameters on the request log by specifying the parameters you want to mask.
However, as mentioned in this issue, the mask of the query log is not covered. Also, Rails has a log level of debug even in production by default, so Even in production, the query log will flow and confidential information will be exposed.
Rails 6 has released filter_attribute
to prevent the issue of being inspected and exposing sensitive information in the log.
However, I couldn't mask the query log here either.
(It may be possible to mask depending on how Active Record is implemented)
Here are some solutions for query log masking.
In the first place, setting config.log_level =: info
to prevent the query log from being output will solve the problem.
However, you may not want to use this method if possible because you will not be able to see all the query logs.
There is a gem called blouson, which is a great gem with the ability to mask the query log for a particular table.
However, the prefix of the name of the table you want to mask must be secure_
, and it will mask the entire query log that is caught in the condition.
Therefore, it is a little difficult to use in my environment, and I wanted to mask only specific columns like filter_parameters
.
I think this is the closest solution to the behavior of filter_attribute
.
As shown below, in the part that outputs the log of ʻActiveRecord :: LogSubscriber`, For query logs that bind columns with a specific string, try to mask the bound value.
Add mask processing before render_bind
by the method presented in here.
config/initializers/sql_log_filter.rb
module SqlLogFilter
FILTERS = Set.new(%w(email password))
def render_bind(attr, value)
value = '[FILTERED]' if FILTERS.include?(attr.name)
super(attr, value)
end
end
ActiveRecord::LogSubscriber.prepend SqlLogFilter
Since the parameters are directly embedded in the sql log, the relevant part is omitted with a regular expression and replaced.
config/initializers/sql_log_filter.rb
module SqlLogFilter
FILTER_REGEX = /email|password/i
def sql(event)
binds = event.payload[:binds]
return super(event) if binds.blank?
binds.each_with_index do |bind, index|
next unless bind.name.match?(FILTER_REGEX)
event.payload[:sql] = event.payload[:sql].gsub(/@#{index} = (N?'(.*?)'|\d+)/) do |_|
"@#{index} = [FILTERED]"
end
end
super(event)
end
end
ActiveRecord::LogSubscriber.prepend SqlLogFilter
Have a good mask life!
Recommended Posts