针对数据库的特定角色成员资格提案

来自 PostgreSQL wiki
跳转至导航跳转至搜索

概述

这是针对数据库的特定角色成员资格作为对现有群集范围角色成员资格系统的一个补充而提出的一个实现建议。

讨论

可在以下 pgsql-hackers 中找到有关此功能建议的讨论

实现

在以下修补程序列表中可跟踪此建议的实现

修补程序 日期 说明
poc-database-role-membership-v1.patch 2021-10-09 提供基线实现(无测试或文档)
database-role-memberships-v2.patch 2021-10-24 完整实现(含测试和文档)
database-role-memberships-v3.patch 2021-11-28 重新归基
database-role-memberships-v4.patch 2021-12-01 重新归基,省略 catversion.h
database-role-memberships-v5.patch 2022-01-21 重新归基以解决之前提交确认中的冲突
database-role-memberships-v5-alternate.patch 2022-01-22 文档更新,含抽象的 acl.c 修改
database-role-memberships-v6.patch 2022-01-22 修复文件指针段错误
database-role-memberships-v7.patch 2022-03-23 修复 dumpRoleMembership() 所生成查询的问题
database-role-memberships-v8.patch 2022-04-02 重新归基以解决合并冲突
database-role-memberships-v9.patch 2022-07-01 重新归基以解决合并冲突
database-role-memberships-v10.patch 2022-07-17 重新归基以解决合并冲突
database-role-memberships-v11.patch 2022-07-24 添加澄清文档

背景

来自 第 22 章。数据库角色文档(v14)

PostgreSQL 使用角色的概念来管理数据库访问权限。角色可以被理解为数据库用户或一组数据库用户,具体取决于角色的设置方式。角色可以拥有数据库对象(例如,表和函数),并且可以将这些对象上的权限分配给其他角色来控制谁可以访问哪些对象。此外,可以将某个角色的成员资格授予另一个角色,从而允许成员角色使用分配给另一个角色的权限。角色的概念包含了“用户”和“组”的概念。在 8.1 版本之前的 PostgreSQL 中,用户和组是不同类型的实体,但现在只有角色。任何角色都可以充当用户、组或两者。

摘自 第 22.5 章 预定义角色 文档(v14)

PostgreSQL 提供了一组预定义角色,这些角色可以访问某些常见所需的特权功能和信息。管理员(包括具有 CREATEROLE 权限的角色)可以将这些角色授予其环境中的用户和/或其他角色,从而为这些用户提供访问指定功能和信息的权限。

问题

角色可以被授予另一个角色的成员资格,但这只能在群集范围内进行。目前,没有机制可以在单个数据库的上下文中授予角色成员资格。这使得难以实现类似于“db_datareader”和“db_datawriter”(SQL Server 中的数据库级角色,分别授予特定数据库内的读写访问权)的权限方案。

如果没有基于每个数据库的角色成员抽象,PostgreSQL 管理员需要为每个数据库创建具有自己特定权限授予的多角色作为解决方法。当涉及到企业身份验证时,这变得更加混乱。

拟议的解决方案

角色成员资格系统将被扩展以允许群集范围特定于数据库的角色成员资格。将在 pg_auth_members 中添加一个列,以跟踪仅在指定数据库中有效的角色成员资格。

语法

GRANT / REVOKE 语法将被扩展以允许特定于数据库的角色成员资格

GRANT role_name [, ...] TO role_specification [, ...]
    [ IN DATABASE database_name | IN CURRENT DATABASE ] -- new clause
    [ WITH ADMIN OPTION ]
    [ GRANTED BY role_specification ]
REVOKE [ ADMIN OPTION FOR ]
    role_name [, ...] FROM role_specification [, ...]
    [ IN DATABASE database_name | IN CURRENT DATABASE ] -- new clause
    [ GRANTED BY role_specification ]
    [ CASCADE | RESTRICT ]

然后,将按如下方式处理 GRANT / REVOKE 角色成员资格语句

条款 效果
<未指定> 该语句适用于群集范围角色成员资格。这是它现在的运作方式。
IN DATABASE database_name 该语句仅适用于指定数据库内的角色成员资格。
IN CURRENT DATABASE 该语句仅适用于当前连接的数据库内的角色成员资格。

角色成员资格算法

将使用以下算法计算角色成员资格(和后续权限)

  1. 检查群集范围的角色成员资格(当前的运作方式)
  2. 根据当前连接的数据库检查与数据库相关的角色关系成员资格

示例用法

CREATE DATABASE accounting;
CREATE DATABASE sales;

CREATE ROLE alice;
CREATE ROLE bob;

-- Alice is granted read-all privileges cluster-wide (nothing new here)
GRANT pg_read_all_data TO alice;

-- Bob is granted read-all privileges to just the accounting database
GRANT pg_read_all_data TO bob IN DATABASE accounting;

实现细节

  • 系统目录中添加了一列 (pg_auth_members.dbid)。对于集群范围内的成员资格,该列将设置为 InvalidOid,而对于特定数据库的成员资格,该列将设置为指定数据库的 oid。
  • 授予/撤消角色关系的语法已扩展(见上文)。
  • 更新了 DROP DATABASE,以便清理与正在删除的数据库相关的所有特定数据库的角色成员资格。
  • pg_dump_all 仍将使用 IN CURRENT DATABASE 语法转儲特定数据库的角色成员资格。未修改 pg_dump
  • C API
    • is_admin_of_role() 的签名已更新,包括正在作为第三个参数检查的数据库的 oid。如果成员在全局或所给数据库中具有有管理选项,那么现在将返回真。
    • roles_is_member_of() 还将包含在正在检查的数据库的任何特定数据库的角色成员资格中。