1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Filter attributes in SQL logs

SQL queries are logged when :debug option is used.

Previously, filter attributes were not masked in the logs.
For e.g.
    select "foos".* from foos where "foos"."passw" = ?
      LIMIT ?  [["passw", "hello"]

`password` being one of the filter attributes is written to
disk.

With this change, filter attributes will be masked as
[FILTERED] in the logs.

    select "foos".* from foos where "foos"."passw" = ?
      "foos"."passw" = ? LIMIT ?  [["passw", "[FILTERED]"]
This commit is contained in:
Aishwarya Subramanian 2021-04-16 17:26:20 -05:00 committed by Aishwarya
parent 074c7f50c5
commit 17c7607167
3 changed files with 66 additions and 1 deletions

View file

@ -1,3 +1,19 @@
* Filter attributes in SQL logs
Previously, SQL queries in logs containing `ActiveRecord::Base.filter_attributes` were not filtered.
Now, the filter attributes will be masked `[FILTERED]` in the logs when `prepared_statement` is enabled.
```
# Before:
Foo Load (0.2ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "hello"], ["LIMIT", 1]]
# After:
Foo Load (0.5ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "[FILTERED]"], ["LIMIT", 1]]
```
*Aishwarya Subramanian*
* Add database config option `database_tasks`
If you would like to connect to an external database without any database

View file

@ -51,7 +51,10 @@ module ActiveRecord
binds = []
payload[:binds].each_with_index do |attr, i|
binds << render_bind(attr, casted_params[i])
attribute_name = attr.respond_to?(:name) ? attr.name : attr[i].name
filtered_params = filter(attribute_name, casted_params[i])
binds << render_bind(attr, filtered_params)
end
binds = binds.inspect
binds.prepend(" ")
@ -135,6 +138,10 @@ module ActiveRecord
def extract_query_source_location(locations)
backtrace_cleaner.clean(locations.lazy).first
end
def filter(name, value)
ActiveRecord::Base.inspection_filter.filter_param(name, value)
end
end
end

View file

@ -189,6 +189,16 @@ if ActiveRecord::Base.connection.prepared_statements
assert_predicate @connection, :prepared_statements?
end
def test_binds_with_filtered_attributes
ActiveRecord::Base.filter_attributes = [:auth]
binds = [Relation::QueryAttribute.new("auth_token", "abcd", Type::String.new)]
assert_filtered_log_binds(binds)
ActiveRecord::Base.filter_attributes = []
end
private
def assert_bind_params_to_sql
table = Author.quoted_table_name
@ -277,6 +287,38 @@ if ActiveRecord::Base.connection.prepared_statements
logger.sql(event)
assert_match %r(\[\["id", 10\]\]\z), logger.debugs.first
end
def assert_filtered_log_binds(binds)
payload = {
name: "SQL",
sql: "select * from users where auth_token = ?",
binds: binds,
type_casted_binds: @connection.send(:type_casted_binds, binds)
}
event = ActiveSupport::Notifications::Event.new(
"foo",
Time.now,
Time.now,
123,
payload)
logger = Class.new(ActiveRecord::LogSubscriber) {
attr_reader :debugs
def initialize
super
@debugs = []
end
def debug(str)
@debugs << str
end
}.new
logger.sql(event)
assert_match %r([[auth_token, [FILTERED]]]), logger.debugs.first
end
end
end
end