From 7c453650600a237a7e6c2669d48559917f8c8631 Mon Sep 17 00:00:00 2001 From: Ian Ballou Date: Wed, 20 Nov 2024 09:18:01 -0500 Subject: [PATCH] Fixes #37883 - halt if remote DB does not own EVR (#984) * Fixes #37883 - halt if remote DB does not own EVR * Refs #37883 - connect to remote db for evr perms check via env vars * Refs #37883 - skip if non-katello & always refer to foreman DB * Refs #37883 - check if evr extension exists on remote DBs --- hooks/boot/01-kafo-hook-extensions.rb | 44 +++++++++++++++++++ hooks/pre/10-reset_data.rb | 44 ------------------- .../42-evr_extension_permissions.rb | 38 ++++++++++++++++ 3 files changed, 82 insertions(+), 44 deletions(-) create mode 100644 hooks/pre_commit/42-evr_extension_permissions.rb diff --git a/hooks/boot/01-kafo-hook-extensions.rb b/hooks/boot/01-kafo-hook-extensions.rb index 0b3d2c32..21c596fe 100644 --- a/hooks/boot/01-kafo-hook-extensions.rb +++ b/hooks/boot/01-kafo-hook-extensions.rb @@ -101,6 +101,50 @@ def log_and_say(level, message, do_say = true, do_log = true) Kafo::KafoConfigure.logger.send(level, message) if do_log end + def load_db_config(db) + case db + when 'foreman' + module_name = 'foreman' + user_param = 'username' + db_param = 'database' + param_prefix = 'db_' + when 'candlepin' + module_name = 'katello' + user_param = 'user' + db_param = 'name' + param_prefix = 'candlepin_db_' + when 'pulpcore' + module_name = 'foreman_proxy_content' + user_param = 'user' + db_param = 'db_name' + param_prefix = 'pulpcore_postgresql_' + else + raise "installer module unknown for db: #{db}" + end + + { + host: param_value(module_name, "#{param_prefix}host") || 'localhost', + port: param_value(module_name, "#{param_prefix}port") || 5432, + database: param_value(module_name, "#{param_prefix}#{db_param}") || db, + username: param_value(module_name, "#{param_prefix}#{user_param}"), + password: param_value(module_name, "#{param_prefix}password"), + } + end + + def pg_env(config) + { + 'PGHOST' => config.fetch(:host, 'localhost'), + 'PGPORT' => config.fetch(:port, '5432').to_s, + 'PGUSER' => config[:username], + 'PGPASSWORD' => config[:password], + 'PGDATABASE' => config[:database], + } + end + + def pg_sql_statement(statement) + "psql -t -c \"#{statement}\"" + end + def execute!(command, do_say = true, do_log = true, extra_env = {}) stdout_stderr, status = execute_command(command, do_say, do_log, extra_env) diff --git a/hooks/pre/10-reset_data.rb b/hooks/pre/10-reset_data.rb index bb3db431..67906016 100644 --- a/hooks/pre/10-reset_data.rb +++ b/hooks/pre/10-reset_data.rb @@ -10,36 +10,6 @@ def reset reset_pulpcore if pulpcore_enabled? end -def load_db_config(db) - case db - when 'foreman' - module_name = 'foreman' - user_param = 'username' - db_param = 'database' - param_prefix = 'db_' - when 'candlepin' - module_name = 'katello' - user_param = 'user' - db_param = 'name' - param_prefix = 'candlepin_db_' - when 'pulpcore' - module_name = 'foreman_proxy_content' - user_param = 'user' - db_param = 'db_name' - param_prefix = 'pulpcore_postgresql_' - else - raise "installer module unknown for db: #{db}" - end - - { - host: param_value(module_name, "#{param_prefix}host") || 'localhost', - port: param_value(module_name, "#{param_prefix}port") || 5432, - database: param_value(module_name, "#{param_prefix}#{db_param}") || db, - username: param_value(module_name, "#{param_prefix}#{user_param}"), - password: param_value(module_name, "#{param_prefix}password"), - } -end - def empty_db_in_postgresql(db) logger.notice "Dropping #{db} database!" @@ -56,20 +26,6 @@ def reset_candlepin empty_db_in_postgresql('candlepin') end -def pg_env(config) - { - 'PGHOST' => config.fetch(:host, 'localhost'), - 'PGPORT' => config.fetch(:port, '5432').to_s, - 'PGUSER' => config[:username], - 'PGPASSWORD' => config[:password], - 'PGDATABASE' => config[:database], - } -end - -def pg_sql_statement(statement) - "psql -t -c \"#{statement}\"" -end - # WARNING: deletes all the data owned by the user. No warnings. No confirmations. def empty_database!(config) delete_statement = 'DROP OWNED BY CURRENT_USER CASCADE;' diff --git a/hooks/pre_commit/42-evr_extension_permissions.rb b/hooks/pre_commit/42-evr_extension_permissions.rb new file mode 100644 index 00000000..836d7cd9 --- /dev/null +++ b/hooks/pre_commit/42-evr_extension_permissions.rb @@ -0,0 +1,38 @@ +# Managed databases will be handled automatically. +return if local_postgresql? +return unless katello_enabled? + +config = load_db_config('foreman') + +# If postgres is the owner of the DB, then the permissions will not matter. +return if config[:username] == 'postgres' + +evr_existence_command = pg_sql_statement("SELECT 1 FROM pg_extension WHERE extname = 'evr';") +logger.debug "Checking if the evr extension exists via #{evr_existence_command}" +evr_existence_output, = execute_command(evr_existence_command, false, true, pg_env(config)) + +# If the evr extension does not exist, then we can skip this check. +return if evr_existence_output&.strip != '1' + +check_evr_owner_sql = "SELECT CASE" \ + " WHEN r.rolname = '#{config[:username]}' THEN 0" \ + " ELSE 1" \ + " END AS evr_owned_by_postgres" \ + " FROM pg_extension e" \ + " JOIN pg_roles r ON e.extowner = r.oid" \ + " WHERE e.extname = 'evr';" + +command = pg_sql_statement(check_evr_owner_sql) +logger.debug "Checking if the evr extension is owned by the postgres user via #{command}" +output, = execute_command(command, false, true, pg_env(config)) + +case output&.strip +when '0' + # The evr extension is owned by the foreman DB owner, so we can skip this check. + return +when '1' + fail_and_exit("The evr extension is not owned by the foreman DB owner. Please run the following command to fix it: " \ + "UPDATE pg_extension SET extowner = (SELECT oid FROM pg_authid WHERE rolname='#{config[:username]}') WHERE extname='evr';") +else + fail_and_exit("Failed to check the ownership of the evr extension.") +end