aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimon Riggs <simon@2ndQuadrant.com>2017-03-30 14:18:53 -0400
committerSimon Riggs <simon@2ndQuadrant.com>2017-03-30 14:18:53 -0400
commit25fff40798fc4ac11a241bfd9ab0c45c085e2212 (patch)
tree3c2e3eb741f814bba8eaa593d17811b86b8d2a00 /src
parente984ef5861df4bc9733b36271d05763e82de7c04 (diff)
downloadpostgresql-25fff40798fc4ac11a241bfd9ab0c45c085e2212.tar.gz
postgresql-25fff40798fc4ac11a241bfd9ab0c45c085e2212.zip
Default monitoring roles
Three nologin roles with non-overlapping privs are created by default * pg_read_all_settings - read all GUCs. * pg_read_all_stats - pg_stat_*, pg_database_size(), pg_tablespace_size() * pg_stat_scan_tables - may lock/scan tables Top level role - pg_monitor includes all of the above by default, plus others Author: Dave Page Reviewed-by: Stephen Frost, Robert Haas, Peter Eisentraut, Simon Riggs
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/system_views.sql6
-rw-r--r--src/backend/replication/walreceiver.c3
-rw-r--r--src/backend/utils/adt/dbsize.c20
-rw-r--r--src/backend/utils/adt/pgstatfuncs.c6
-rw-r--r--src/backend/utils/misc/guc.c21
-rw-r--r--src/include/catalog/pg_authid.h8
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 */