diff options
Diffstat (limited to 'lib/gitlab/database/query_analyzers')
4 files changed, 22 insertions, 19 deletions
diff --git a/lib/gitlab/database/query_analyzers/base.rb b/lib/gitlab/database/query_analyzers/base.rb index 9c2c228f869..9a52a4f6e23 100644 --- a/lib/gitlab/database/query_analyzers/base.rb +++ b/lib/gitlab/database/query_analyzers/base.rb @@ -53,10 +53,6 @@ module Gitlab Thread.current[self.context_key] end - def self.raw? - false - end - def self.enabled? raise NotImplementedError end diff --git a/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection.rb b/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection.rb index 3de9e8011fb..c966ae0e105 100644 --- a/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection.rb +++ b/lib/gitlab/database/query_analyzers/gitlab_schemas_validate_connection.rb @@ -22,13 +22,16 @@ module Gitlab return unless allowed_schemas invalid_schemas = table_schemas - allowed_schemas - if invalid_schemas.any? - message = "The query tried to access #{tables} (of #{table_schemas.to_a}) " - message += "which is outside of allowed schemas (#{allowed_schemas}) " - message += "for the current connection '#{Gitlab::Database.db_config_name(parsed.connection)}'" - raise CrossSchemaAccessError, message - end + return if invalid_schemas.empty? + + schema_list = table_schemas.sort.join(',') + + message = "The query tried to access #{tables} (of #{schema_list}) " + message += "which is outside of allowed schemas (#{allowed_schemas}) " + message += "for the current connection '#{Gitlab::Database.db_config_name(parsed.connection)}'" + + raise CrossSchemaAccessError, message end end end diff --git a/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb index dd10e0d7992..713e1f772e3 100644 --- a/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb +++ b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb @@ -87,15 +87,15 @@ module Gitlab return if tables == ['schema_migrations'] context[:modified_tables_by_db][database].merge(tables) - all_tables = context[:modified_tables_by_db].values.map(&:to_a).flatten + all_tables = context[:modified_tables_by_db].values.flat_map(&:to_a) schemas = ::Gitlab::Database::GitlabSchema.table_schemas(all_tables) schemas += ApplicationRecord.gitlab_transactions_stack if schemas.many? message = "Cross-database data modification of '#{schemas.to_a.join(", ")}' were detected within " \ - "a transaction modifying the '#{all_tables.to_a.join(", ")}' tables. " \ - "Please refer to https://docs.gitlab.com/ee/development/database/multiple_databases.html#removing-cross-database-transactions for details on how to resolve this exception." + "a transaction modifying the '#{all_tables.to_a.join(", ")}' tables. " \ + "Please refer to https://docs.gitlab.com/ee/development/database/multiple_databases.html#removing-cross-database-transactions for details on how to resolve this exception." if schemas.any? { |s| s.to_s.start_with?("undefined") } message += " The gitlab_schema was undefined for one or more of the tables in this transaction. Any new tables must be added to lib/gitlab/database/gitlab_schemas.yml ." diff --git a/lib/gitlab/database/query_analyzers/query_recorder.rb b/lib/gitlab/database/query_analyzers/query_recorder.rb index b54f3442512..63b4fbb8c1d 100644 --- a/lib/gitlab/database/query_analyzers/query_recorder.rb +++ b/lib/gitlab/database/query_analyzers/query_recorder.rb @@ -5,21 +5,19 @@ module Gitlab module QueryAnalyzers class QueryRecorder < Base LOG_PATH = 'query_recorder/' + LIST_PARAMETER_REGEX = %r{\$\d+(?:\s*,\s*\$\d+)+}.freeze + SINGLE_PARAMETER_REGEX = %r{\$\d+}.freeze class << self - def raw? - true - end - def enabled? # Only enable QueryRecorder in CI on database MRs or default branch ENV['CI_MERGE_REQUEST_LABELS']&.include?('database') || (ENV['CI_COMMIT_REF_NAME'].present? && ENV['CI_COMMIT_REF_NAME'] == ENV['CI_DEFAULT_BRANCH']) end - def analyze(sql) + def analyze(parsed) payload = { - sql: sql + normalized: normalize_query(parsed.sql) } log_query(payload) @@ -42,6 +40,12 @@ module Gitlab File.write(log_file, log_line, mode: 'a') end + + def normalize_query(query) + query + .gsub(LIST_PARAMETER_REGEX, '?,?,?') # Replace list parameters with ?,?,? + .gsub(SINGLE_PARAMETER_REGEX, '?') # Replace single parameters with ? + end end end end |