diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/system_views.sql | 6 | ||||
-rw-r--r-- | src/backend/replication/walreceiver.c | 3 | ||||
-rw-r--r-- | src/backend/utils/adt/dbsize.c | 20 | ||||
-rw-r--r-- | src/backend/utils/adt/pgstatfuncs.c | 6 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 21 | ||||
-rw-r--r-- | src/include/catalog/pg_authid.h | 8 |
6 files changed, 48 insertions, 16 deletions
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index d357c8b8fdb..0217f3992f3 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -1148,3 +1148,9 @@ REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_function_counters(oid) FROM publ REVOKE EXECUTE ON FUNCTION pg_ls_logdir() FROM public; REVOKE EXECUTE ON FUNCTION pg_ls_waldir() FROM public; +GRANT EXECUTE ON FUNCTION pg_ls_logdir() TO pg_monitor; +GRANT EXECUTE ON FUNCTION pg_ls_waldir() TO pg_monitor; + +GRANT pg_read_all_settings TO pg_monitor; +GRANT pg_read_all_stats TO pg_monitor; +GRANT pg_stat_scan_tables TO pg_monitor; diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index 771ac305c34..df93265c20e 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -50,6 +50,7 @@ #include "access/timeline.h" #include "access/transam.h" #include "access/xlog_internal.h" +#include "catalog/pg_authid.h" #include "catalog/pg_type.h" #include "funcapi.h" #include "libpq/pqformat.h" @@ -1421,7 +1422,7 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS) /* Fetch values */ values[0] = Int32GetDatum(walrcv->pid); - if (!superuser()) + if (!is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS)) { /* * Only superusers can see details. Other users only get the pid value diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index 58923912eb7..6d56638208b 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -17,6 +17,7 @@ #include "access/htup_details.h" #include "catalog/catalog.h" #include "catalog/namespace.h" +#include "catalog/pg_authid.h" #include "catalog/pg_tablespace.h" #include "commands/dbcommands.h" #include "commands/tablespace.h" @@ -88,11 +89,17 @@ calculate_database_size(Oid dbOid) char pathname[MAXPGPATH]; AclResult aclresult; - /* User must have connect privilege for target database */ + /* + * User must have connect privilege for target database + * or be a member of pg_read_all_stats + */ aclresult = pg_database_aclcheck(dbOid, GetUserId(), ACL_CONNECT); - if (aclresult != ACLCHECK_OK) + if (aclresult != ACLCHECK_OK && + !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS)) + { aclcheck_error(aclresult, ACL_KIND_DATABASE, get_database_name(dbOid)); + } /* Shared storage in pg_global is not counted */ @@ -172,11 +179,12 @@ calculate_tablespace_size(Oid tblspcOid) AclResult aclresult; /* - * User must have CREATE privilege for target tablespace, either - * explicitly granted or implicitly because it is default for current - * database. + * User must be a member of pg_read_all_stats or have CREATE privilege for + * target tablespace, either explicitly granted or implicitly because + * it is default for current database. */ - if (tblspcOid != MyDatabaseTableSpace) + if (tblspcOid != MyDatabaseTableSpace && + !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS)) { aclresult = pg_tablespace_aclcheck(tblspcOid, GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK) diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index dd2b924d0af..e0cae1ba1e8 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -15,6 +15,7 @@ #include "postgres.h" #include "access/htup_details.h" +#include "catalog/pg_authid.h" #include "catalog/pg_type.h" #include "common/ip.h" #include "funcapi.h" @@ -658,8 +659,9 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) nulls[19] = nulls[20] = nulls[21] = nulls[22] = nulls[23] = true; } - /* Values only available to role member */ - if (has_privs_of_role(GetUserId(), beentry->st_userid)) + /* Values only available to role member or pg_read_all_stats */ + if (has_privs_of_role(GetUserId(), beentry->st_userid) || + is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS)) { SockAddr zero_clientaddr; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index e9d561b185e..8b5f064d4eb 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -34,6 +34,7 @@ #include "access/xact.h" #include "access/xlog_internal.h" #include "catalog/namespace.h" +#include "catalog/pg_authid.h" #include "commands/async.h" #include "commands/prepare.h" #include "commands/user.h" @@ -6689,10 +6690,11 @@ GetConfigOption(const char *name, bool missing_ok, bool restrict_superuser) } if (restrict_superuser && (record->flags & GUC_SUPERUSER_ONLY) && - !superuser()) + !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to examine \"%s\"", name))); + errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"", + name))); switch (record->vartype) { @@ -6737,10 +6739,12 @@ GetConfigOptionResetString(const char *name) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("unrecognized configuration parameter \"%s\"", name))); - if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser()) + if ((record->flags & GUC_SUPERUSER_ONLY) && + !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to examine \"%s\"", name))); + errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"", + name))); switch (record->vartype) { @@ -8027,10 +8031,12 @@ GetConfigOptionByName(const char *name, const char **varname, bool missing_ok) errmsg("unrecognized configuration parameter \"%s\"", name))); } - if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser()) + if ((record->flags & GUC_SUPERUSER_ONLY) && + !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to examine \"%s\"", name))); + errmsg("must be superuser or a member of pg_read_all_settings to examine \"%s\"", + name))); if (varname) *varname = record->name; @@ -8056,7 +8062,8 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow) if (noshow) { if ((conf->flags & GUC_NO_SHOW_ALL) || - ((conf->flags & GUC_SUPERUSER_ONLY) && !superuser())) + ((conf->flags & GUC_SUPERUSER_ONLY) && + !is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS))) *noshow = true; else *noshow = false; diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h index def71edaa89..a6c5c02cebd 100644 --- a/src/include/catalog/pg_authid.h +++ b/src/include/catalog/pg_authid.h @@ -99,10 +99,18 @@ typedef FormData_pg_authid *Form_pg_authid; * ---------------- */ DATA(insert OID = 10 ( "POSTGRES" t t t t t t t -1 _null_ _null_)); +DATA(insert OID = 3373 ( "pg_monitor" f t f f f f f -1 _null_ _null_)); +DATA(insert OID = 3374 ( "pg_read_all_settings" f t f f f f f -1 _null_ _null_)); +DATA(insert OID = 3375 ( "pg_read_all_stats" f t f f f f f -1 _null_ _null_)); +DATA(insert OID = 3377 ( "pg_stat_scan_tables" f t f f f f f -1 _null_ _null_)); DATA(insert OID = 4200 ( "pg_signal_backend" f t f f f f f -1 _null_ _null_)); #define BOOTSTRAP_SUPERUSERID 10 +#define DEFAULT_ROLE_MONITOR 3373 +#define DEFAULT_ROLE_READ_ALL_SETTINGS 3374 +#define DEFAULT_ROLE_READ_ALL_STATS 3375 +#define DEFAULT_ROLE_STAT_SCAN_TABLES 3377 #define DEFAULT_ROLE_SIGNAL_BACKENDID 4200 #endif /* PG_AUTHID_H */ |