From ca6bada86f76943e732db66aee9cf02c565d22f8 Mon Sep 17 00:00:00 2001 From: Mark Dilger Date: Wed, 20 Oct 2021 07:52:49 -0700 Subject: [PATCH v1 11/12] Adding role pg_manage_recovery_settings This new role can SET or ALTER SYSTEM SET any GUC variable which controls crash recovery settings. --- doc/src/sgml/user-manag.sgml | 13 ++-- src/backend/utils/misc/guc.c | 20 +++--- src/include/catalog/pg_authid.dat | 5 ++ src/include/utils/guc.h | 1 + src/test/regress/expected/guc_privs.out | 89 +++++++++++++++++++++++++ src/test/regress/sql/guc_privs.sql | 59 ++++++++++++++++ 6 files changed, 175 insertions(+), 12 deletions(-) diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml index 548ece3acb..c97350ee92 100644 --- a/doc/src/sgml/user-manag.sgml +++ b/doc/src/sgml/user-manag.sgml @@ -618,6 +618,10 @@ DROP ROLE doomed_role; pg_manage_stats_settings Allow changing settings which control collection of statistics. + + pg_manage_recovery_settings + Allow changing settings which control or are generally used for recovery. + @@ -670,10 +674,11 @@ DROP ROLE doomed_role; pg_manage_replication_settings, pg_manage_connection_settings, pg_manage_wal_settings, - pg_manage_query_tuning_settings and - pg_manage_stats_settings roles are intended to - allow administrators to have trusted, but non-superuser, roles to configure - the server. + pg_manage_query_tuning_settings, + pg_manage_stats_settings and + pg_manage_recovery_settings roles are intended to allow + administrators to have trusted, but non-superuser, roles to configure the + server. diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index a676c4af09..5e52b5544d 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -1287,7 +1287,7 @@ static struct config_bool ConfigureNamesBool[] = "(but still report a warning), and continue processing. This " "behavior could cause crashes or other serious problems. Only " "has an effect if checksums are enabled."), - GUC_SUPERUSER_ONLY, + GUC_MANAGE_RECOVERY_SETTINGS, GUC_NOT_IN_SAMPLE }, &ignore_checksum_failure, @@ -1302,7 +1302,7 @@ static struct config_bool ConfigureNamesBool[] = "zero_damaged_pages to true causes the system to instead report a " "warning, zero out the damaged page, and continue processing. This " "behavior will destroy data, namely all the rows on the damaged page."), - GUC_SUPERUSER_ONLY, + GUC_MANAGE_RECOVERY_SETTINGS, GUC_NOT_IN_SAMPLE }, &zero_damaged_pages, @@ -1322,7 +1322,7 @@ static struct config_bool ConfigureNamesBool[] = "crashes, data loss, propagate or hide corruption, " "or other serious problems. Only has an effect " "during recovery or in standby mode."), - GUC_SUPERUSER_ONLY, + GUC_MANAGE_RECOVERY_SETTINGS, GUC_NOT_IN_SAMPLE }, &ignore_invalid_pages, @@ -1447,7 +1447,7 @@ static struct config_bool ConfigureNamesBool[] = {"restart_after_crash", PGC_SIGHUP, ERROR_HANDLING_OPTIONS, gettext_noop("Reinitialize server after backend crash."), NULL, - GUC_SUPERUSER_ONLY + GUC_MANAGE_RECOVERY_SETTINGS }, &restart_after_crash, true, @@ -1457,7 +1457,7 @@ static struct config_bool ConfigureNamesBool[] = {"remove_temp_files_after_crash", PGC_SIGHUP, DEVELOPER_OPTIONS, gettext_noop("Remove temporary files after backend crash."), NULL, - GUC_SUPERUSER_ONLY, + GUC_MANAGE_RECOVERY_SETTINGS, GUC_NOT_IN_SAMPLE }, &remove_temp_files_after_crash, @@ -2032,7 +2032,7 @@ static struct config_bool ConfigureNamesBool[] = {"allow_system_table_mods", PGC_SUSET, DEVELOPER_OPTIONS, gettext_noop("Allows modifications of the structure of system tables."), NULL, - GUC_SUPERUSER_ONLY, + GUC_MANAGE_RECOVERY_SETTINGS, GUC_NOT_IN_SAMPLE }, &allowSystemTableMods, @@ -2045,7 +2045,7 @@ static struct config_bool ConfigureNamesBool[] = gettext_noop("Disables reading from system indexes."), gettext_noop("It does not prevent updating the indexes, so it is safe " "to use. The worst consequence is slowness."), - GUC_SUPERUSER_ONLY, + GUC_MANAGE_RECOVERY_SETTINGS, GUC_NOT_IN_SAMPLE }, &IgnoreSystemIndexes, @@ -5337,7 +5337,7 @@ static struct config_enum ConfigureNamesEnum[] = {"recovery_init_sync_method", PGC_SIGHUP, ERROR_HANDLING_OPTIONS, gettext_noop("Sets the method for synchronizing the data directory before crash recovery."), NULL, - GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES + GUC_MANAGE_RECOVERY_SETTINGS }, &recovery_init_sync_method, RECOVERY_INIT_SYNC_METHOD_FSYNC, recovery_init_sync_method_options, @@ -7667,6 +7667,10 @@ role_has_privileges(Oid roleid, int privileges) ! has_privs_of_role(roleid, ROLE_PG_MANAGE_STATS_SETTINGS)) return false; + if ((privileges & GUC_MANAGE_RECOVERY_SETTINGS) && + ! has_privs_of_role(roleid, ROLE_PG_MANAGE_RECOVERY_SETTINGS)) + return false; + return true; } diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat index 3f80cbd59b..05ac06ccc9 100644 --- a/src/include/catalog/pg_authid.dat +++ b/src/include/catalog/pg_authid.dat @@ -124,5 +124,10 @@ rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f', rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1', rolpassword => '_null_', rolvaliduntil => '_null_' }, +{ oid => '9288', oid_symbol => 'ROLE_PG_MANAGE_RECOVERY_SETTINGS', + rolname => 'pg_manage_recovery_settings', rolsuper => 'f', rolinherit => 't', + rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f', + rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1', + rolpassword => '_null_', rolvaliduntil => '_null_' }, ] diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 3e91f13cb8..fe1e4b0c4c 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -211,6 +211,7 @@ typedef enum #define GUC_MANAGE_WAL_SETTINGS 0x0080 #define GUC_MANAGE_QUERY_TUNING_SETTINGS 0x0200 /* 0x0100 = superuser */ #define GUC_MANAGE_STATS_SETTINGS 0x0400 +#define GUC_MANAGE_RECOVERY_SETTINGS 0x0800 /* * bit values in "flags" of a GUC variable diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out index 4b8d50d93c..91f28d4b75 100644 --- a/src/test/regress/expected/guc_privs.out +++ b/src/test/regress/expected/guc_privs.out @@ -1009,3 +1009,92 @@ ERROR: parameter "ssl_renegotiation_limit" cannot be changed RESET statement_timeout; RESET SESSION AUTHORIZATION; DROP ROLE regress_stats_full_admin; +-- Test role pg_manage_recovery_settings +-- Non-superuser with privileges to configure recovery +CREATE ROLE regress_recovery_admin NOSUPERUSER; +GRANT pg_manage_recovery_settings TO regress_recovery_admin; +-- Perform all operations as user 'regress_recovery_admin' -- +SET SESSION AUTHORIZATION regress_recovery_admin; +-- PGC_BACKEND +SET ignore_system_indexes = OFF; -- fail, cannot be set after connection start +ERROR: parameter "ignore_system_indexes" cannot be set after connection start +RESET ignore_system_indexes; -- fail, cannot be set after connection start +ERROR: parameter "ignore_system_indexes" cannot be set after connection start +ALTER SYSTEM SET ignore_system_indexes = OFF; -- ok +ALTER SYSTEM RESET ignore_system_indexes; -- ok +ALTER SYSTEM SET post_auth_delay = 50; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "post_auth_delay" +ALTER SYSTEM RESET post_auth_delay; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "post_auth_delay" +-- PGC_INTERNAL +SET block_size = 50; -- fail, cannot be changed +ERROR: parameter "block_size" cannot be changed +RESET block_size; -- fail, cannot be changed +ERROR: parameter "block_size" cannot be changed +ALTER SYSTEM SET block_size = 50; -- fail, cannot be changed +ERROR: parameter "block_size" cannot be changed +ALTER SYSTEM RESET block_size; -- fail, cannot be changed +ERROR: parameter "block_size" cannot be changed +-- PGC_POSTMASTER +SET autovacuum_freeze_max_age = 1000050000; -- fail, requires restart +ERROR: parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server +RESET autovacuum_freeze_max_age; -- fail, requires restart +ERROR: parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server +ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "autovacuum_freeze_max_age" +ALTER SYSTEM RESET autovacuum_freeze_max_age; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "autovacuum_freeze_max_age" +ALTER SYSTEM SET ignore_invalid_pages = OFF; -- ok +ALTER SYSTEM RESET ignore_invalid_pages; -- ok +ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf'; -- fail, cannot be changed +ERROR: parameter "config_file" cannot be changed +ALTER SYSTEM RESET config_file; -- fail, cannot be changed +ERROR: parameter "config_file" cannot be changed +-- PGC_SIGHUP +SET autovacuum = OFF; -- fail, requires reload +ERROR: parameter "autovacuum" cannot be changed now +RESET autovacuum; -- fail, requires reload +ERROR: parameter "autovacuum" cannot be changed now +ALTER SYSTEM SET autovacuum = OFF; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "autovacuum" +ALTER SYSTEM RESET autovacuum; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "autovacuum" +ALTER SYSTEM SET remove_temp_files_after_crash = OFF; -- ok +ALTER SYSTEM RESET remove_temp_files_after_crash; -- ok +-- PGC_SUSET +SET lc_messages = 'en_US.UTF-8'; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "lc_messages" +RESET lc_messages; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "lc_messages" +ALTER SYSTEM SET lc_messages = 'en_US.UTF-8'; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "lc_messages" +ALTER SYSTEM RESET lc_messages; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "lc_messages" +SET allow_system_table_mods = OFF; -- ok +RESET allow_system_table_mods; -- ok +ALTER SYSTEM SET allow_system_table_mods = OFF; -- ok +ALTER SYSTEM RESET allow_system_table_mods; -- ok +-- PGC_SU_BACKEND +SET jit_debugging_support = OFF; -- fail, cannot be set after connection start +ERROR: parameter "jit_debugging_support" cannot be set after connection start +RESET jit_debugging_support; -- fail, cannot be set after connection start +ERROR: parameter "jit_debugging_support" cannot be set after connection start +ALTER SYSTEM SET jit_debugging_support = OFF; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "jit_debugging_support" +ALTER SYSTEM RESET jit_debugging_support; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "jit_debugging_support" +-- PGC_USERSET +SET DateStyle = 'ISO, MDY'; -- ok +RESET DateStyle; -- ok +ALTER SYSTEM SET DateStyle = 'ISO, MDY'; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "datestyle" +ALTER SYSTEM RESET DateStyle; -- fail, regress_recovery_admin has insufficient privileges +ERROR: permission denied to set parameter "datestyle" +ALTER SYSTEM SET ssl_renegotiation_limit = 0; -- fail, cannot be changed +ERROR: parameter "ssl_renegotiation_limit" cannot be changed +ALTER SYSTEM RESET ssl_renegotiation_limit; -- fail, cannot be changed +ERROR: parameter "ssl_renegotiation_limit" cannot be changed +-- Finished testing role pg_manage_recovery_settings +RESET statement_timeout; +RESET SESSION AUTHORIZATION; +DROP ROLE regress_recovery_admin; diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql index 78b6df76cf..bb25b00e2a 100644 --- a/src/test/regress/sql/guc_privs.sql +++ b/src/test/regress/sql/guc_privs.sql @@ -663,3 +663,62 @@ ALTER SYSTEM RESET ssl_renegotiation_limit; -- fail, cannot be changed RESET statement_timeout; RESET SESSION AUTHORIZATION; DROP ROLE regress_stats_full_admin; +-- Test role pg_manage_recovery_settings +-- Non-superuser with privileges to configure recovery +CREATE ROLE regress_recovery_admin NOSUPERUSER; +GRANT pg_manage_recovery_settings TO regress_recovery_admin; +-- Perform all operations as user 'regress_recovery_admin' -- +SET SESSION AUTHORIZATION regress_recovery_admin; +-- PGC_BACKEND +SET ignore_system_indexes = OFF; -- fail, cannot be set after connection start +RESET ignore_system_indexes; -- fail, cannot be set after connection start +ALTER SYSTEM SET ignore_system_indexes = OFF; -- ok +ALTER SYSTEM RESET ignore_system_indexes; -- ok +ALTER SYSTEM SET post_auth_delay = 50; -- fail, regress_recovery_admin has insufficient privileges +ALTER SYSTEM RESET post_auth_delay; -- fail, regress_recovery_admin has insufficient privileges +-- PGC_INTERNAL +SET block_size = 50; -- fail, cannot be changed +RESET block_size; -- fail, cannot be changed +ALTER SYSTEM SET block_size = 50; -- fail, cannot be changed +ALTER SYSTEM RESET block_size; -- fail, cannot be changed +-- PGC_POSTMASTER +SET autovacuum_freeze_max_age = 1000050000; -- fail, requires restart +RESET autovacuum_freeze_max_age; -- fail, requires restart +ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000; -- fail, regress_recovery_admin has insufficient privileges +ALTER SYSTEM RESET autovacuum_freeze_max_age; -- fail, regress_recovery_admin has insufficient privileges +ALTER SYSTEM SET ignore_invalid_pages = OFF; -- ok +ALTER SYSTEM RESET ignore_invalid_pages; -- ok +ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf'; -- fail, cannot be changed +ALTER SYSTEM RESET config_file; -- fail, cannot be changed +-- PGC_SIGHUP +SET autovacuum = OFF; -- fail, requires reload +RESET autovacuum; -- fail, requires reload +ALTER SYSTEM SET autovacuum = OFF; -- fail, regress_recovery_admin has insufficient privileges +ALTER SYSTEM RESET autovacuum; -- fail, regress_recovery_admin has insufficient privileges +ALTER SYSTEM SET remove_temp_files_after_crash = OFF; -- ok +ALTER SYSTEM RESET remove_temp_files_after_crash; -- ok +-- PGC_SUSET +SET lc_messages = 'en_US.UTF-8'; -- fail, regress_recovery_admin has insufficient privileges +RESET lc_messages; -- fail, regress_recovery_admin has insufficient privileges +ALTER SYSTEM SET lc_messages = 'en_US.UTF-8'; -- fail, regress_recovery_admin has insufficient privileges +ALTER SYSTEM RESET lc_messages; -- fail, regress_recovery_admin has insufficient privileges +SET allow_system_table_mods = OFF; -- ok +RESET allow_system_table_mods; -- ok +ALTER SYSTEM SET allow_system_table_mods = OFF; -- ok +ALTER SYSTEM RESET allow_system_table_mods; -- ok +-- PGC_SU_BACKEND +SET jit_debugging_support = OFF; -- fail, cannot be set after connection start +RESET jit_debugging_support; -- fail, cannot be set after connection start +ALTER SYSTEM SET jit_debugging_support = OFF; -- fail, regress_recovery_admin has insufficient privileges +ALTER SYSTEM RESET jit_debugging_support; -- fail, regress_recovery_admin has insufficient privileges +-- PGC_USERSET +SET DateStyle = 'ISO, MDY'; -- ok +RESET DateStyle; -- ok +ALTER SYSTEM SET DateStyle = 'ISO, MDY'; -- fail, regress_recovery_admin has insufficient privileges +ALTER SYSTEM RESET DateStyle; -- fail, regress_recovery_admin has insufficient privileges +ALTER SYSTEM SET ssl_renegotiation_limit = 0; -- fail, cannot be changed +ALTER SYSTEM RESET ssl_renegotiation_limit; -- fail, cannot be changed +-- Finished testing role pg_manage_recovery_settings +RESET statement_timeout; +RESET SESSION AUTHORIZATION; +DROP ROLE regress_recovery_admin; -- 2.21.1 (Apple Git-122.3)