From 3212405d36a4f8faa1f108d4a41c8831a4c0c950 Mon Sep 17 00:00:00 2001 From: Ian Ballou Date: Fri, 4 Oct 2024 16:03:03 -0400 Subject: [PATCH 1/4] Fixes #37883 - halt if remote DB does not own EVR --- .../42-evr_extension_permissions.rb | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 hooks/pre_commit/42-evr_extension_permissions.rb 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..ceca20db --- /dev/null +++ b/hooks/pre_commit/42-evr_extension_permissions.rb @@ -0,0 +1,30 @@ +# Managed databases will be handled automatically. +return if local_postgresql? + +database = param_value('foreman', 'db_database') || 'foreman' +username = param_value('foreman', 'db_username') || 'foreman' +password = param_value('foreman', 'db_password') +host = param_value('foreman', 'db_host') +port = param_value('foreman', 'db_port') || 5432 + +# If postgres is the owner of the DB, then the permissions will not matter. +return if username == 'postgres' + +check_evr_owner_sql = "SELECT CASE" \ + " WHEN r.rolname = 'postgres' THEN 1" \ + " ELSE 0" \ + " END AS evr_owned_by_postgres" \ + " FROM pg_extension e" \ + " JOIN pg_roles r ON e.extowner = r.oid" \ + " WHERE e.extname = 'evr';" + +command = "PGPASSWORD='#{password}' psql -U #{username} -h #{host} -p #{port} -d #{database} -t -c \"#{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) +unless output.nil? + if output.strip == '1' + fail_and_exit("The evr extension is owned by postgres and not the foreman DB owner. Please run the following command to fix it: " \ + "UPDATE pg_extension SET extowner = (SELECT oid FROM pg_authid WHERE rolname='#{username}');") + end +end + From 60b31b865e6696331660899849c3015367cdcfd6 Mon Sep 17 00:00:00 2001 From: Ian Ballou Date: Tue, 29 Oct 2024 17:40:53 -0400 Subject: [PATCH 2/4] Refs #37883 - connect to remote db for evr perms check via env vars --- hooks/boot/01-kafo-hook-extensions.rb | 44 +++++++++++++++++++ hooks/pre/10-reset_data.rb | 44 ------------------- .../42-evr_extension_permissions.rb | 31 ++++++------- 3 files changed, 60 insertions(+), 59 deletions(-) diff --git a/hooks/boot/01-kafo-hook-extensions.rb b/hooks/boot/01-kafo-hook-extensions.rb index 23abaa4b..f352f3f5 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 index ceca20db..85e89a46 100644 --- a/hooks/pre_commit/42-evr_extension_permissions.rb +++ b/hooks/pre_commit/42-evr_extension_permissions.rb @@ -2,29 +2,30 @@ return if local_postgresql? database = param_value('foreman', 'db_database') || 'foreman' -username = param_value('foreman', 'db_username') || 'foreman' -password = param_value('foreman', 'db_password') -host = param_value('foreman', 'db_host') -port = param_value('foreman', 'db_port') || 5432 +config = load_db_config(database) # If postgres is the owner of the DB, then the permissions will not matter. -return if username == 'postgres' +return if config[:username] == 'postgres' check_evr_owner_sql = "SELECT CASE" \ - " WHEN r.rolname = 'postgres' THEN 1" \ - " ELSE 0" \ + " 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 = "PGPASSWORD='#{password}' psql -U #{username} -h #{host} -p #{port} -d #{database} -t -c \"#{check_evr_owner_sql}\"" +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) -unless output.nil? - if output.strip == '1' - fail_and_exit("The evr extension is owned by postgres and not the foreman DB owner. Please run the following command to fix it: " \ - "UPDATE pg_extension SET extowner = (SELECT oid FROM pg_authid WHERE rolname='#{username}');") - end -end +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 #{database} 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 From 3c6ef7e472fa0507e468ca329a0f98edb7a2c05f Mon Sep 17 00:00:00 2001 From: Ian Ballou Date: Wed, 13 Nov 2024 14:38:40 -0500 Subject: [PATCH 3/4] Refs #37883 - skip if non-katello & always refer to foreman DB --- hooks/pre_commit/42-evr_extension_permissions.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hooks/pre_commit/42-evr_extension_permissions.rb b/hooks/pre_commit/42-evr_extension_permissions.rb index 85e89a46..e9254f73 100644 --- a/hooks/pre_commit/42-evr_extension_permissions.rb +++ b/hooks/pre_commit/42-evr_extension_permissions.rb @@ -1,8 +1,8 @@ # Managed databases will be handled automatically. return if local_postgresql? +return unless katello_enabled? -database = param_value('foreman', 'db_database') || 'foreman' -config = load_db_config(database) +config = load_db_config('foreman') # If postgres is the owner of the DB, then the permissions will not matter. return if config[:username] == 'postgres' @@ -24,7 +24,7 @@ # 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 #{database} DB owner. Please run the following command to fix it: " \ + 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.") From 3447f12cf8fa87507ed79d983b6340eeecae9d86 Mon Sep 17 00:00:00 2001 From: Ian Ballou Date: Fri, 15 Nov 2024 16:34:11 -0500 Subject: [PATCH 4/4] Refs #37883 - check if evr extension exists on remote DBs --- hooks/pre_commit/42-evr_extension_permissions.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hooks/pre_commit/42-evr_extension_permissions.rb b/hooks/pre_commit/42-evr_extension_permissions.rb index e9254f73..836d7cd9 100644 --- a/hooks/pre_commit/42-evr_extension_permissions.rb +++ b/hooks/pre_commit/42-evr_extension_permissions.rb @@ -7,6 +7,13 @@ # 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" \