Class: Airbrake::Filters::SqlFilter Private

Inherits:
Object
  • Object
show all
Defined in:
lib/airbrake-ruby/filters/sql_filter.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

SqlFilter filters out sensitive data from Query. Sensitive data is everything that is not table names or fields (e.g. column values and such).

Supports the following SQL dialects:

  • PostgreSQL

  • MySQL

  • SQLite

  • Cassandra

  • Oracle

Since:

  • v3.2.0

Constant Summary collapse

FILTERED =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns the label to replace real values of filtered query.

Returns:

  • (String)

    the label to replace real values of filtered query

Since:

  • v3.2.0

'?'.freeze
ERROR_MSG =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns the string that will replace the query in case we cannot filter it.

Returns:

  • (String)

    the string that will replace the query in case we cannot filter it

Since:

  • v3.2.0

'Error: Airbrake::Query was not filtered'.freeze
ALL_FEATURES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns matchers for certain features of SQL.

Returns:

  • (Hash{Symbol=>Regexp})

    matchers for certain features of SQL

Since:

  • v3.2.0

{
  # rubocop:disable Layout/LineLength
  single_quotes: /'(?:[^']|'')*?(?:\\'.*|'(?!'))/,
  double_quotes: /"(?:[^"]|"")*?(?:\\".*|"(?!"))/,
  dollar_quotes: /(\$(?!\d)[^$]*?\$).*?(?:\1|$)/,
  uuids: /\{?(?:[0-9a-fA-F]-*){32}\}?/,
  numeric_literals: /\b-?(?:[0-9]+\.)?[0-9]+([eE][+-]?[0-9]+)?\b/,
  boolean_literals: /\b(?:true|false|null)\b/i,
  hexadecimal_literals: /0x[0-9a-fA-F]+/,
  comments: /(?:#|--).*?(?=\r|\n|$)/i,
  multi_line_comments: %r{/\*(?:[^/]|/[^*])*?(?:\*/|/\*.*)},
  oracle_quoted_strings: /q'\[.*?(?:\]'|$)|q'\{.*?(?:\}'|$)|q'<.*?(?:>'|$)|q'\(.*?(?:\)'|$)/,
  # rubocop:enable Layout/LineLength
}.freeze
POST_FILTER =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns the regexp that is applied after the feature regexps were used.

Returns:

  • (Regexp)

    the regexp that is applied after the feature regexps were used

Since:

  • v3.2.0

/(?<=[values|in ]\().+(?=\))/i.freeze
DIALECT_FEATURES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns a set of features that corresponds to a certain dialect.

Returns:

  • (Hash{Symbol=>Array<Symbol>})

    a set of features that corresponds to a certain dialect

Since:

  • v3.2.0

{
  default: ALL_FEATURES.keys,
  mysql: %i[
    single_quotes double_quotes numeric_literals boolean_literals
    hexadecimal_literals comments multi_line_comments
  ].freeze,
  postgres: %i[
    single_quotes dollar_quotes uuids numeric_literals boolean_literals
    comments multi_line_comments
  ].freeze,
  sqlite: %i[
    single_quotes numeric_literals boolean_literals hexadecimal_literals
    comments multi_line_comments
  ].freeze,
  oracle: %i[
    single_quotes oracle_quoted_strings numeric_literals comments
    multi_line_comments
  ].freeze,
  cassandra: %i[
    single_quotes uuids numeric_literals boolean_literals
    hexadecimal_literals comments multi_line_comments
  ].freeze,
}.freeze
UNMATCHED_PAIR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns a set of regexps to check for unmatches quotes after filtering (should be none).

Returns:

  • (Hash{Symbol=>Regexp})

    a set of regexps to check for unmatches quotes after filtering (should be none)

Since:

  • v3.2.0

{
  mysql: %r{'|"|/\*|\*/},
  mysql2: %r{'|"|/\*|\*/},
  postgres: %r{'|/\*|\*/|\$(?!\?)},
  sqlite: %r{'|/\*|\*/},
  cassandra: %r{'|/\*|\*/},
  oracle: %r{'|/\*|\*/},
  oracle_enhanced: %r{'|/\*|\*/},
}.freeze
IGNORED_QUERIES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns the list of queries to be ignored.

Returns:

  • (Array<Regexp>)

    the list of queries to be ignored

Since:

  • v3.2.0

[
  /\ACOMMIT/i,
  /\ABEGIN/i,
  /\ASET/i,
  /\ASHOW/i,
  /\AWITH/i,
  /FROM pg_attribute/i,
  /FROM pg_index/i,
  /FROM pg_class/i,
  /FROM pg_type/i,
].freeze

Instance Method Summary collapse

Constructor Details

#initialize(dialect) ⇒ SqlFilter

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of SqlFilter.

Since:

  • v3.2.0



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/airbrake-ruby/filters/sql_filter.rb', line 95

def initialize(dialect)
  @dialect =
    case dialect
    when /mysql/i then :mysql
    when /postgres/i then :postgres
    when /sqlite/i then :sqlite
    when /oracle/i then :oracle
    when /cassandra/i then :cassandra
    else
      :default
    end

  features = DIALECT_FEATURES[@dialect].map { |f| ALL_FEATURES[f] }
  @regexp = Regexp.union(features)
end

Instance Method Details

#call(metric) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

Since:

  • v3.2.0



112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/airbrake-ruby/filters/sql_filter.rb', line 112

def call(metric)
  return unless metric.respond_to?(:query)

  query = metric.query
  if IGNORED_QUERIES.any? { |q| q =~ query }
    metric.ignore!
    return
  end

  q = query.gsub(@regexp, FILTERED)
  q.gsub!(POST_FILTER, FILTERED) if q =~ POST_FILTER
  q = ERROR_MSG if UNMATCHED_PAIR[@dialect] =~ q
  metric.query = q
end