Module: OneApm::Agent::Database::ObfuscationHelpers

Included in:
Obfuscator
Defined in:
lib/one_apm/agent/database/obfuscation_helpers.rb

Constant Summary collapse

OA_REVERSE_SINGLE_QUOTES_REGEX =

Note that the following two regexes are applied to a reversed version of the query. This is why the backslash escape sequences (' and ") appear reversed within them.

Note that some database adapters (notably, PostgreSQL with standard_conforming_strings on and MySQL with NO_BACKSLASH_ESCAPES on) do not apply special treatment to backslashes within quoted string literals. We don’t have an easy way of determining whether the database connection from which a query was captured was operating in one of these modes, but the obfuscation is done in such a way that it should not matter.

Reversing the query string before obfuscation allows us to get around the fact that a ' appearing within a string may or may not terminate the string, because we know that a string cannot start with a '.

/'(?:''|'\\|[^'])*'/
OA_REVERSE_ANY_QUOTES_REGEX =
/'(?:''|'\\|[^'])*'|"(?:""|"\\|[^"])*"/
OA_NUMERICS_REGEX =
/\b\d+\b/
OA_SQL_COMMENT_REGEX =

We take a conservative, overly-aggressive approach to obfuscating comments, and drop everything from the query after encountering any character sequence that could be a comment initiator. We do this after removal of string literals to avoid accidentally over-obfuscating when a string literal contains a comment initiator.

Regexp.new('(?:/\*|--|#).*', Regexp::MULTILINE).freeze
OA_LITERAL_SINGLE_QUOTE =

We use these to check whether the query contains any quote characters after obfuscation. If so, that’s a good indication that the original query was malformed, and so our obfuscation can’t reliabily find literals. In such a case, we’ll replace the entire query with a placeholder.

"'".freeze
OA_LITERAL_DOUBLE_QUOTE =
'"'.freeze
OA_PLACEHOLDER =
'?'.freeze

Instance Method Summary collapse

Instance Method Details

#contains_quotes?(str) ⇒ Boolean

Returns:

  • (Boolean)


70
71
72
# File 'lib/one_apm/agent/database/obfuscation_helpers.rb', line 70

def contains_quotes?(str)
  str.include?(OA_LITERAL_SINGLE_QUOTE) || str.include?(OA_LITERAL_DOUBLE_QUOTE)
end

#contains_single_quotes?(str) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
# File 'lib/one_apm/agent/database/obfuscation_helpers.rb', line 66

def contains_single_quotes?(str)
  str.include?(OA_LITERAL_SINGLE_QUOTE)
end

#obfuscate_numeric_literals(sql) ⇒ Object



58
59
60
# File 'lib/one_apm/agent/database/obfuscation_helpers.rb', line 58

def obfuscate_numeric_literals(sql)
  sql.gsub(OA_NUMERICS_REGEX, OA_PLACEHOLDER)
end

#obfuscate_quoted_literals(sql) ⇒ Object



51
52
53
54
55
56
# File 'lib/one_apm/agent/database/obfuscation_helpers.rb', line 51

def obfuscate_quoted_literals(sql)
  obfuscated = sql.reverse
  obfuscated.gsub!(OA_REVERSE_ANY_QUOTES_REGEX, OA_PLACEHOLDER)
  obfuscated.reverse!
  obfuscated
end

#obfuscate_single_quote_literals(sql) ⇒ Object



44
45
46
47
48
49
# File 'lib/one_apm/agent/database/obfuscation_helpers.rb', line 44

def obfuscate_single_quote_literals(sql)
  obfuscated = sql.reverse
  obfuscated.gsub!(OA_REVERSE_SINGLE_QUOTES_REGEX, OA_PLACEHOLDER)
  obfuscated.reverse!
  obfuscated
end

#remove_comments(sql) ⇒ Object



62
63
64
# File 'lib/one_apm/agent/database/obfuscation_helpers.rb', line 62

def remove_comments(sql)
  sql.gsub(OA_SQL_COMMENT_REGEX, OA_PLACEHOLDER)
end