PostgreSQL 16全部功能特性基本尘埃落定,本文与大家探讨新版本在权限管理方面的变化。
一、两个新增预置角色让普通用户后台管理更便捷
新版本增加的预置角色分别是:
二、初始用户权限优化
在PostgreSQL 16里,使用initdb工具初始化数据库时生成的初始用户不允许移除超级用户权限,示例如下:
postgres=# alter user postgres nosuperuser; ERROR: permission denied to alter role DETAIL: The bootstrap user must have the SUPERUSER attribute.
上面的代码对默认的postgres初始用户删除超级用户权限,该操作在PostgreSQL 16里会提示错误。初始用户仍然是许多重要系统对象的宿主,即便它没有超级用户权限也可以通过修改pg_catalog模式下的系统表来获得超级用户权限,之前的版本允许移除超级用户权限并不符合安全预期。
三、成员角色权限更安全
PostgreSQL 16对grant命令的语法进行了扩展,新增了with inherit和with set选项。
当对新建用户赋权系统预置角色时,可使用with inherit true选项,参考命令如下:
postgres=# grant pg_read_all_settings to a with inherit true; GRANT ROLE postgres=# \c - a You are now connected to database "postgres" as user "a". postgres=> show data_directory; data_directory ----------------- /opt/pgdata1600 (1 row)
使用with inherit true选项赋予成员角色后,不需要显式切换到成员角色即可进行相关的操作。
而自定义角色需要设置成员角色时,为了安全起见需要显式切换角色,此时可以设置with set true选项。
另外在PostgreSQL 16里使用带createrole属性创建新用户时,有如下变化:
下面进行代码演示:
postgres=# create role admin login createrole;
CREATE ROLE
postgres=# \c - admin
You are now connected to database "postgres" as user "admin".
postgres=> create role user1 login;
CREATE ROLE
postgres=> \du admin
List of roles
Role name | Attributes | Member of
-----------+-------------+-----------
admin | Create role | {user1}
postgres=> alter user user1 connection limit 10;
ALTER ROLE
上面第一行代码被创建的admin用户带有createrole属性,第四行代码可以看到admin用户自动变为user1的成员。
第五行代码可以看到admin用户可以对创建的user1用户设置连接限制进行权限管理,并且只能对自己创建的角色或者被赋予admin选项的角色进行管理。
使用createrole属性创建的用户管理其他用户的能力将受到一定程度的限制,示例如下:
postgres=> \c - postgres You are now connected to database "postgres" as user "postgres". postgres=# create role admin2 LOGIN CREATEROLE; CREATE ROLE postgres=# \c - admin2 You are now connected to database "postgres" as user "admin2". postgres=> alter user user1 connection limit -1; ERROR: permission denied to alter role DETAIL: Only roles with the CREATEROLE attribute and the ADMIN option on role "user1" may alter this role.
从上面的代码可以观察,同样拥有createrole属性的admin2用户并不能对admin创建的用户user1进行权限管理。
我们还可以从pg_auth_members系统表可以查看到如下变化:
postgres=> SELECT roleid::regrole,member::regrole,grantor::regrole, * FROM pg_auth_members WHERE roleid::regrole::text !~ '^pg_' \gx -[ RECORD 1 ]--+--------- roleid | user1 member | admin grantor | postgres oid | 49336 roleid | 49335 member | 49334 grantor | 10 admin_option | t inherit_option | f set_option | f
从上面的数据记录观察pg_auth_members系统表新增了两个字段:
上面的实验可以看到创建新用户后,默认只具有用户的管理权限而不能直接继承用户的权限以及不能直接切换用户。
PostgreSQL 16为了保持向下的兼容性,同时也新增了一个createrole_self_grant参数,它的参数值可以配置为inherit、set或者两者的组合,并使用逗号分割。
下面是createrole_self_grant参数使用的示例:
postgres=# \c - admin You are now connected to database "postgres" as user "admin". postgres=> set createrole_self_grant to 'set'; SET postgres=> create user user2; CREATE ROLE postgres=> set role user2; SET postgres=> select roleid::regrole,member::regrole,grantor::regrole, * from pg_auth_members where roleid::regrole::text = 'user2' and grantor::regrole::text = 'admin' \gx -[ RECORD 1 ]--+------ roleid | user2 member | admin grantor | admin oid | 49358 roleid | 49356 member | 49334 grantor | 49334 admin_option | f inherit_option | f set_option | t
由于createrole_self_grant参数的值设置为set选项,使用admin用户创建的用户user2可以被admin用户使用set命令进行切换,同时pg_auth_members系统表的set_option字段值也变为了t。
总结
从以上几个方面可以看到PostgreSQL 16对普通用户的日常管理、成员角色权限以及初始用户权限做了不少的优化提升。
最后也欢迎大家关注本人的新书:<<快速掌握PostgreSQL版本新特性>>,对本书感兴趣的朋友,可以加微信skypkmoon入群一起学习讨论。
