Postgresql小特性:为nosuper用户预留连接数

需求描述

场景

在某些场景下,希望保证某个nosuper用户必须能连上数据库。(superuser权限过大)

postgresql原生只可以给超级用户预留连接数,该特性可以使指定的某个用户(reserved_user_name)使用给超级用户预留的连接数。

功能说明

1、增加参数

reserved_user_name = ”

2、参数说明

指定的用户名与superuser共享superuser_reserved_connections预留的连接数。

测试结果

当前数据库服务器参数

max_connections = 5 
superuser_reserved_connections = 3 
reserved_user_name = 'tu1' 

当前用户情况

postgres=# select rolname,rolsuper from pg_authid;
      rolname      | rolsuper
-------------------+----------
 jackgo            | t
 pg_signal_backend | f
 tu1               | f
 tu2               | f

当前连接情况

postgres=# select datname,usename from pg_stat_activity;
 datname | usename ----------+---------
 postgres | jackgo
 postgres | jackgo
 postgres | jackgo
(3 rows)

使用超级用户连接结果

[jackgo@MiWiFi-R1CM-srv:~]<PG96-60>$psql
psql (9.6.2)
Type "help" for help.

postgres=#

使用指定用户tu1连接结果

[jackgo@MiWiFi-R1CM-srv:~]<PG96-60>$psql -U tu1
psql (9.6.2)
Type "help" for help.

postgres=>

使用其他用户连接结果

[jackgo@MiWiFi-R1CM-srv:~]<PG96-60>$psql -U tu2
psql: FATAL:  remaining connection slots are reserved for non-replication superuser connections

源码

diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
old mode 100644
new mode 100755
index 533252a..2cf0037
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -207,6 +207,7 @@ char       *ListenAddresses;
  * count against the limit.
  */
 int            ReservedBackends;
+char        *ReservedUserName = NULL;

 /* The socket(s) we're listening to. */
 #define MAXLISTEN 64
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
old mode 100644
new mode 100755
index 0a4295b..fb72bee
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -560,6 +560,7 @@ InitPostgres(const char *in_dbname,Oid dboid,const char *username,{
    bool        bootstrap = IsBootstrapProcessingMode();
    bool        am_superuser;
+    bool        am_reserveduser = false;
    char       *fullpath;
    char        dbname[NAMEDATALEN];

@@ -735,6 +736,PerformAuthentication(MyProcPort);
        InitializeSessionUserId(username,useroid);
        am_superuser = superuser();
+        am_reserveduser = reserveduser();
    }

    /* @@ -770,8 +772,12 @@ InitPostgres(const char *in_dbname,const char *username,* replication connections currently require superuser privileges,we * don't allow them to consume the reserved slots,which are intended for * interactive use. + * + * Put am_reserveduser in the AND logic.so am_reserveduser doesn't have to + * consider whether it's a super user. */
    if ((!am_superuser || am_walsender) &&
+        !am_reserveduser &&
        ReservedBackends > 0 &&
        !HaveNFreeProcs(ReservedBackends))
        ereport(FATAL,diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
old mode 100644
new mode 100755
index 4f1891f..250d18c
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3552,6 +3552,18 @@ static struct config_string ConfigureNamesstring[] =
        check_cluster_name,NULL,NULL
    },+    {
+        {"reserved_user_name",PGC_SIGHUP,CONN_AUTH_SETTINGS,+            gettext_noop("Sets the reserved user name."),+            NULL,+            GUC_SUPERUSER_ONLY
+        },+        &ReservedUserName,+        "",+        NULL,NULL
+    },+
+
    /* End-of-list marker */
    {
        {NULL,0,NULL},NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
old mode 100644
new mode 100755
index fa6c0ea..8676106
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -63,6 +63,7 @@
 #port = 5432 # (change requires restart)
 #max_connections = 100 # (change requires restart)
 #superuser_reserved_connections = 3 # (change requires restart)
+#reserved_user_name = '' # (change requires restart)
 #unix_socket_directories = '/tmp' # comma-separated list of directories
                    # (change requires restart)
 #unix_socket_group = '' # (change requires restart)
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
old mode 100644
new mode 100755
index dd70e02..0c3a252
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -24,7 +24,9 @@
 #include "catalog/pg_authid.h"
 #include "utils/inval.h"
 #include "utils/syscache.h"
+#include "utils/acl.h"
 #include "miscadmin.h"
+#include "postmaster/postmaster.h"


 /* @@ -96,6 +98,40 @@ superuser_arg(Oid roleid) return result; } + +bool +reserveduser(void) +{ + return reserveduser_arg(GetUserId()); +} + +bool +reserveduser_arg(Oid roleid) +{ + bool result; + Oid reservedoid; + + if (ReservedUserName && !(*ReservedUserName)) + { + result = false; + } + + reservedoid = get_role_oid(ReservedUserName,true); + + if (!OidisValid(reservedoid)) + { + result = false; + } + + if (roleid == reservedoid) + { + result = true; + } + + return result; +} + + /* * RoleidCallback * Syscache inval callback function diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h old mode 100644 new mode 100755 index 78545da..6399632 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -326,6 +326,8 @@ extern void SwitchBackToLocalLatch(void); /* in utils/misc/superuser.c */
 extern bool superuser(void);   /* current user is superuser */
 extern bool superuser_arg(Oid roleid); /* given user is superuser */
+extern bool reserveduser(void);    /* current user is reserveduser */
+extern bool reserveduser_arg(Oid roleid);  /* given user is reserveduser */


 /***************************************************************************** diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h old mode 100644 new mode 100755 index b2d7776..99edac8 --- a/src/include/postmaster/postmaster.h +++ b/src/include/postmaster/postmaster.h @@ -16,6 +16,8 @@ /* GUC options */
 extern bool EnableSSL;
 extern int ReservedBackends;
+extern char *ReservedUserName;
+
 extern int PostPortNumber;
 extern int Unix_socket_permissions;
 extern char *Unix_socket_group;

相关文章

项目需要,有个数据需要导入,拿到手一开始以为是mysql,结果...
本文小编为大家详细介绍“怎么查看PostgreSQL数据库中所有表...
错误现象问题原因这是在远程连接时pg_hba.conf文件没有配置正...
因本地资源有限,在公共测试环境搭建了PGsql环境,从数据库本...
wamp 环境 这个提示就是说你的版本低于10了。 先打印ph...
psycopg2.OperationalError: SSL SYSCALL error: EOF detect...