Skip to content

Latest commit

 

History

History
205 lines (162 loc) · 8.88 KB

20230111_01.md

File metadata and controls

205 lines (162 loc) · 8.88 KB

PostgreSQL 16 preview - 增加GUC createrole_self_grant, nonsuperuser创建用户支持inherit和set role自动反向赋予

作者

digoal

日期

2023-01-11

标签

PostgreSQL , PolarDB , createrole_self_grant , 反向赋予inherit和set role


背景

当superuser创建用户时, superuser可以直接set role切换成被创建的用户, 也可以inherit继承被创建用户的privilege:

  • The INHERIT attribute governs inheritance of grantable privileges (that is, access privileges for database objects and role memberships). It does not apply to the special role attributes set by CREATE ROLE and ALTER ROLE. For example, being a member of a role with CREATEDB privilege does not immediately grant the ability to create databases, even if INHERIT is set; it would be necessary to become that role via SET ROLE before creating a database.

而nonsuperuser创建用户时, 不可以直接set role切换成被创建的用户, 也不可以inherit继承被创建用户的privilege.

PostgreSQL 16开始, 通过createrole_self_grant参数, 可以配置nonsuperuser是否也可以在创建用户时, 可以直接set role切换成被创建的用户, 或者可以inherit继承被创建用户的privilege.

createrole_self_grant=''  
createrole_self_grant='set'  
createrole_self_grant='inherit'  
createrole_self_grant='set,inherit'  

安全问题注意: 如果a创建了b, 并且createrole_self_grant='set,inherit', 未来b如果获得了其它权限, 也会被间接赋予给a. 所以小心使用.

https://www.postgresql.org/docs/devel/runtime-config-client.html#GUC-CREATEROLE-SELF-GRANT

createrole_self_grant (string)

If a user who has CREATEROLE but not SUPERUSER creates a role, and if this is set to a non-empty value, the newly-created role will be granted to the creating user with the options specified. The value must be set, inherit, or a comma-separated list of these.

The purpose of this option is to allow a CREATEROLE user who is not a superuser to automatically inherit, or automatically gain the ability to SET ROLE to, any created users. Since a CREATEROLE user is always implicitly granted ADMIN OPTION on created roles, that user could always execute a GRANT statement that would achieve the same effect as this setting. However, it can be convenient for usability reasons if the grant happens automatically. A superuser automatically inherits the privileges of every role and can always SET ROLE to any role, and this setting can be used to produce a similar behavior for CREATEROLE users for users which they create.

相关代码

src/backend/commands/user.c

  72 typedef struct  
  73 {  
  74     unsigned    specified;  
  75     bool        admin;  -- with admin   
  76     bool        inherit;  -- inherit  
  77     bool        set;  -- set role  
  78 } GrantRoleOptions;  
  79   
  80 #define GRANT_ROLE_SPECIFIED_ADMIN          0x0001  
  81 #define GRANT_ROLE_SPECIFIED_INHERIT        0x0002  
  82 #define GRANT_ROLE_SPECIFIED_SET            0x0004  

https://git.postgresql.org/gitweb/?p=postgresql.git;a=blobdiff;f=src/backend/commands/user.c;h=4d193a6f9a4e77e07cd44eb95ce29a2acc996aed;hp=1ae2d0a66fb191653b7d4be46324dbd39862eefe;hb=e5b8a4c098ad6add39626a14475148872cd687e0;hpb=cf5eb37c5ee0cc54c80d95c1695d7fca1f7c68cb

+       /*  
+        * Because of the implicit grant above, a CREATEROLE user who creates  
+        * a role has the ability to grant that role back to themselves with  
+        * the INHERIT or SET options, if they wish to inherit the role's  
+        * privileges or be able to SET ROLE to it. The createrole_self_grant  
+        * GUC can be used to make this happen automatically. This has no  
+        * security implications since the same user is able to make the same  
+        * grant using an explicit GRANT statement; it's just convenient.  
+        */  
+       if (createrole_self_grant_enabled)  
+           AddRoleMems(currentUserId, stmt->role, roleid,  
+                       memberSpecs, memberIds,  
+                       currentUserId, &createrole_self_grant_options);  
  
+/*  
+ * GUC check_hook for createrole_self_grant  
+ */  
+bool  
+check_createrole_self_grant(char **newval, void **extra, GucSource source)  
+{  
+   char       *rawstring;  
+   List       *elemlist;  
+   ListCell   *l;  
+   unsigned    options = 0;  
+   unsigned   *result;  
+  
+   /* Need a modifiable copy of string */  
+   rawstring = pstrdup(*newval);  
+  
+   if (!SplitIdentifierString(rawstring, ',', &elemlist))  
+   {  
+       /* syntax error in list */  
+       GUC_check_errdetail("List syntax is invalid.");  
+       pfree(rawstring);  
+       list_free(elemlist);  
+       return false;  
+   }  
+  
+   foreach(l, elemlist)  
+   {  
+       char       *tok = (char *) lfirst(l);  
+  
+       if (pg_strcasecmp(tok, "SET") == 0)  
+           options |= GRANT_ROLE_SPECIFIED_SET;  
+       else if (pg_strcasecmp(tok, "INHERIT") == 0)  
+           options |= GRANT_ROLE_SPECIFIED_INHERIT;  
+       else  
+       {  
+           GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);  
+           pfree(rawstring);  
+           list_free(elemlist);  
+           return false;  
+       }  
+   }  
+  
+   pfree(rawstring);  
+   list_free(elemlist);  
+  
+   result = (unsigned *) guc_malloc(LOG, sizeof(unsigned));  
+   *result = options;  
+   *extra = result;  
+  
+   return true;  
+}  
+  
+/*  
+ * GUC assign_hook for createrole_self_grant  
+ */  
+void  
+assign_createrole_self_grant(const char *newval, void *extra)  
+{  
+   unsigned    options = * (unsigned *) extra;  
+  
+   createrole_self_grant_enabled = (options != 0);  
+   createrole_self_grant_options.specified = GRANT_ROLE_SPECIFIED_ADMIN  
+       | GRANT_ROLE_SPECIFIED_INHERIT  
+       | GRANT_ROLE_SPECIFIED_SET;  
+   createrole_self_grant_options.admin = false;  
+   createrole_self_grant_options.inherit =  
+       (options & GRANT_ROLE_SPECIFIED_INHERIT) != 0;  
+   createrole_self_grant_options.set =  
+       (options & GRANT_ROLE_SPECIFIED_SET) != 0;  
+}  

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=cf5eb37c5ee0cc54c80d95c1695d7fca1f7c68cb

Restrict the privileges of CREATEROLE users.
author	Robert Haas <rhaas@postgresql.org>	
Tue, 10 Jan 2023 17:44:30 +0000 (12:44 -0500)
committer	Robert Haas <rhaas@postgresql.org>	
Tue, 10 Jan 2023 17:44:30 +0000 (12:44 -0500)
commit	cf5eb37c5ee0cc54c80d95c1695d7fca1f7c68cb
tree	9b0d157501c5d0aebf1bac2db0fe83e30576440e	tree
parent	f026c16a2c5a3ee5d7aa6f85333ec80c905913ba	commit | diff
Restrict the privileges of CREATEROLE users.

Previously, CREATEROLE users were permitted to make nearly arbitrary
changes to roles that they didn't create, with certain exceptions,
particularly superuser roles.  Instead, allow CREATEROLE users to make such
changes to roles for which they possess ADMIN OPTION, and to
grant membership only in roles for which they possess ADMIN OPTION.

When a CREATEROLE user who is not a superuser creates a role, grant
ADMIN OPTION on the newly-created role to the creator, so that they
can administer roles they create or for which they have been given
privileges.

With these changes, CREATEROLE users still have very significant
powers that unprivileged users do not receive: they can alter, rename,
drop, comment on, change the password for, and change security labels
on roles.  However, they can now do these things only for roles for
which they possess appropriate privileges, rather than all
non-superuser roles; moreover, they cannot grant a role such as
pg_execute_server_program unless they themselves possess it.

Patch by me, reviewed by Mark Dilger.

Discussion: https://postgr.es/m/CA+TgmobN59ct+Emmz6ig1Nua2Q-_o=r6DSD98KfU53kctq_kQw@mail.gmail.com

digoal's wechat