使用 AD 安全组进行 Aurora PostgreSQL 访问控制 - Amazon Aurora
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

使用 AD 安全组进行 Aurora PostgreSQL 访问控制

从 Aurora PostgreSQL 14.10 和 15.5 版本起,可以使用 Amazon Directory Service for Microsoft Active Directory(AD)安全组来管理 Aurora PostgreSQL 访问控制。早期版本的 Aurora PostgreSQL 仅支持单个用户使用 AD 进行基于 Kerberos 的身份验证。每个 AD 用户都必须显式预调配到数据库集群,才能获得访问权限。

您可以按如下所述利用 AD 安全组,而不是根据业务需求将每个 AD 用户显式预调配到数据库集群:

  • AD 用户是 Active Directory 中不同 AD 安全组的成员。这些不是由数据库集群管理员决定,而是基于业务要求,并由 AD 管理员处理。

  • 数据库集群管理员根据业务需求在数据库实例中创建数据库角色。这些数据库角色可能具有不同的权限或特权。

  • 数据库集群管理员根据每个数据库集群配置从 AD 安全组到数据库角色的映射。

  • 数据库用户可以使用其 AD 凭证访问数据库集群。访问权限基于 AD 安全组成员资格。AD 用户根据其 AD 组成员资格自动获得或失去访问权限。

先决条件

在为 AD 安全组设置扩展之前,请确保您具备以下条件:

设置 pg_ad_mapping 扩展

Aurora PostgreSQL 现在提供 pg_ad_mapping 扩展来管理 Aurora PostgreSQL 集群中 AD 安全组和数据库角色之间的映射。有关 pg_ad_mapping 提供的函数的更多信息,请参阅使用 pg_ad_mapping 扩展中的函数

要在 Aurora PostgreSQL 数据库集群上设置 pg_ad_mapping 扩展,首先要将 pg_ad_mapping 添加到 Aurora PostgreSQL 数据库集群的自定义数据库集群参数组上的共享库中。有关创建自定义数据库集群参数组的信息,请参阅使用参数组。接下来,安装 pg_ad_mapping 扩展。本部分中的过程向您展示如何操作。您可以使用 Amazon Web Services Management Console或 Amazon CLI。

您必须拥有 rds_superuser 角色的权限才能执行所有这些任务。

以下步骤假设 Aurora PostgreSQL 数据库集群与自定义数据库集群参数组相关联。

设置 pg_ad_mapping 扩展
  1. 登录 Amazon Web Services Management Console 并通过以下网址打开 Amazon RDS 控制台:https://console.aws.amazon.com/rds/

  2. 在导航窗格中,选择 Aurora PostgreSQL 数据库集群的写入器实例。

  3. 打开 Aurora PostgreSQL 数据库集群写入器实例的配置选项卡。在实例详细信息中,找到 Parameter group(参数组)链接。

  4. 选择此链接以打开与 Aurora PostgreSQL 数据库集群关联的自定义参数。

  5. Parameters(参数)搜索字段中,键入 shared_pre 以查找 shared_preload_libraries 参数。

  6. 选择 Edit parameters(编辑参数)以访问属性值。

  7. pg_ad_mapping 添加到 Values(值)字段的列表中。使用逗号分隔值列表中的项目。

    添加了 pgAudit 的 shared_preload_libaries 参数的图像。
  8. 重启 Aurora PostgreSQL 数据库集群的写入器实例,以使对 shared_preload_libraries 参数的更改生效。

  9. 当实例可用时,验证 pg_ad_mapping 是否已初始化。使用 psql 连接到 Aurora PostgreSQL 数据库集群的写入器实例,然后运行以下命令。

    SHOW shared_preload_libraries; shared_preload_libraries -------------------------- rdsutils,pg_ad_mapping (1 row)
  10. 初始化 pg_ad_mapping 后,您现在可以创建扩展了。您需要在初始化库之后创建扩展,才能开始使用此扩展提供的函数。

    CREATE EXTENSION pg_ad_mapping;
  11. 关闭 psql 会话。

    labdb=> \q
设置 pg_ad_mapping

要使用 Amazon CLI 设置 pg_ad_mapping,您可以调用 modify-db-parameter-group 操作来在自定义参数组中添加此参数,如以下过程所示。

  1. 使用以下 Amazon CLI 命令向 shared_preload_libraries 参数中添加 pg_ad_mapping

    aws rds modify-db-parameter-group \ --db-parameter-group-name custom-param-group-name \ --parameters "ParameterName=shared_preload_libraries,ParameterValue=pg_ad_mapping,ApplyMethod=pending-reboot" \ --region aws-region
  2. 使用以下 Amazon CLI 命令重启 Aurora PostgreSQL 数据库集群的写入器实例,以便初始化 pg_ad_mapping。

    aws rds reboot-db-instance \ --db-instance-identifier writer-instance \ --region aws-region
  3. 当实例可用时,您可以验证 pg_ad_mapping 是否已初始化。使用 psql 连接到 Aurora PostgreSQL 数据库集群的写入器实例,然后运行以下命令。

    SHOW shared_preload_libraries; shared_preload_libraries -------------------------- rdsutils,pg_ad_mapping (1 row)

    初始化 pg_ad_mapping 后,您现在可以创建扩展了。

    CREATE EXTENSION pg_ad_mapping;
  4. 关闭 psql 会话以便您可以使用 Amazon CLI。

    labdb=> \q

在 PowerShell 中检索 Active Directory 组 SID

安全标识符(SID)用于唯一标识安全主体或安全组。每当在 Active Directory 中创建安全组或账户时,都会为其分配一个 SID。要从 Active Directory 获取 AD 安全组 SID,可以从加入该 Active Directory 域的 Windows 客户端计算机中使用 Get-ADGroup cmdlet。Identity 参数指定用于获取相应 SID 的 Active Directory 组名称。

以下示例返回 AD 组 adgroup1 的 SID。

C:\Users\Admin> Get-ADGroup -Identity adgroup1 | select SID SID ----------------------------------------------- S-1-5-21-3168537779-1985441202-1799118680-1612

映射数据库角色与 AD 安全组

您需要将数据库中的 AD 安全组显式预调配为 PostgreSQL 数据库角色。属于至少一个预调配 AD 安全组的 AD 用户将获得数据库的访问权限。您不应该向基于 AD 组安全性的数据库角色授予 rds_ad role。安全组的 Kerberos 身份验证将通过使用域名后缀(例如 user1@example.com)来触发。此数据库角色无法使用密码或 IAM 身份验证来访问数据库。

注意

在数据库中具有相应数据库角色并获得 rds_ad 角色的 AD 用户不能作为 AD 安全组的一部分登录。他们将以单个用户身份通过数据库角色获得访问权限。

例如,accounts-group 是 AD 中的一个安全组,您希望在 Aurora PostgreSQL 中将该安全组预调配为 accounts-role。

AD 安全组 PosgreSQL 数据库角色
accounts-group accounts-role

将数据库角色与 AD 安全组映射时,必须确保该数据库角色设置了 LOGIN 属性并且具有访问所需登录数据库的 CONNECT 权限。

postgres => alter role accounts-role login; ALTER ROLE postgres => grant connect on database accounts-db to accounts-role;

管理员现在可以继续创建 AD 安全组和 PostgreSQL 数据库角色之间的映射。

admin=>select pgadmap_set_mapping('accounts-group', 'accounts-role', <SID>, <Weight>);

有关检索 AD 安全组的 SID 的信息,请参阅在 PowerShell 中检索 Active Directory 组 SID

在某些情况下,AD 用户可能属于多个组,在这种情况下,AD 用户将继承预调配了最高权重的数据库角色的权限。如果两个角色的权重相同,则 AD 用户将继承与最近添加的映射相对应的数据库角色的权限。建议指定权重,以反映各个数据库角色的相对权限/特权。数据库角色的权限或特权越高,应与映射条目关联的权重就越高。这将避免两个具有相同权重的映射产生歧义。

下表显示了从 AD 安全组到 Aurora PostgreSQL 数据库角色的映射示例。

AD 安全组 PosgreSQL 数据库角色 权重
accounts-group accounts-role 7
sales-group sales-role 10
dev-group dev-role 7

在以下示例中,user1 将继承 sales-role 的权限,因为它的权重更高;而 user2 将继承 dev-role 的权限,因为该角色的映射是在 accounts-role 后创建的,它们的权重与 accounts-role 相同。

用户名 安全组成员资格
user1 accounts-group sales-group
user2 accounts-group dev-group

用于建立、列出和清除映射的 psql 命令如下所示。目前,无法修改单个映射条目。需要删除现有条目并重新创建映射。

admin=>select pgadmap_set_mapping('accounts-group', 'accounts-role', 'S-1-5-67-890', 7); admin=>select pgadmap_set_mapping('sales-group', 'sales-role', 'S-1-2-34-560', 10); admin=>select pgadmap_set_mapping('dev-group', 'dev-role', 'S-1-8-43-612', 7); admin=>select * from pgadmap_read_mapping(); ad_sid | pg_role | weight | ad_grp -------------+----------------+--------+--------------- S-1-5-67-890 | accounts-role | 7 | accounts-group S-1-2-34-560 | sales-role | 10 | sales-group S-1-8-43-612 | dev-role | 7 | dev-group (3 rows)

AD 用户身份日志记录/审计

使用以下命令确定当前用户或会话用户继承的数据库角色:

postgres=>select session_user, current_user; session_user | current_user -------------+-------------- dev-role | dev-role (1 row)

要确定 AD 安全主体身份,请使用以下命令:

postgres=>select principal from pg_stat_gssapi where pid = pg_backend_pid(); principal ------------------------- user1@example.com (1 row)

目前,AD 用户身份在审计日志中不可见。可以启用 log_connections 参数来记录数据库会话建立。有关更多信息,请参阅 log_connections。其输出包括 AD 用户身份,如下所示。然后,与此输出关联的后端 PID 有助于将操作归因回实际 AD 用户。

pgrole1@postgres:[615]:LOG: connection authorized: user=pgrole1 database=postgres application_name=psql GSS (authenticated=yes, encrypted=yes, principal=Admin@EXAMPLE.COM)

限制

  • 不支持称为 Azure Active Directory 的 Microsoft Entra ID。

使用 pg_ad_mapping 扩展中的函数

pg_ad_mapping 扩展为以下函数提供了支持:

pgadmap_set_mapping

此函数在 AD 安全组与具有关联权重的数据库角色之间建立映射。

语法

pgadmap_set_mapping( ad_group, db_role, ad_group_sid, weight)

参数

参数 描述
ad_group AD 组的名称。值不能为 null 或空字符串。
db_role 要映射到指定 AD 组的数据库角色。值不能为 Null 或空字符串。
ad_group_sid 用于唯一标识 AD 组的安全标识符。值以“S-1-”开头,不能为 null 或空字符串。有关更多信息,请参阅 在 PowerShell 中检索 Active Directory 组 SID
weight 与数据库角色关联的权重。当用户是多个组的成员时,权重最高的角色优先。权重的默认值为 1。

返回类型

None

使用说明

此函数添加了从 AD 安全组到数据库角色的新映射。它只能由具有 rds_superuser 权限的用户在数据库集群的主数据库实例上执行。

示例

postgres=> select pgadmap_set_mapping('accounts-group','accounts-role','S-1-2-33-12345-67890-12345-678',10); pgadmap_set_mapping (1 row)

pgadmap_read_mapping

此函数列出使用 pgadmap_set_mapping 函数设置的 AD 安全组和数据库角色之间的映射。

语法

pgadmap_read_mapping()

参数

None

返回类型

参数 描述
ad_group_sid 用于唯一标识 AD 组的安全标识符。值以“S-1-”开头,不能为 Null 或空字符串。有关更多信息,请参阅在 PowerShell 中检索 Active Directory 组 SID。accounts-role@example.com
db_role 要映射到指定 AD 组的数据库角色。值不能为 Null 或空字符串。
weight 与数据库角色关联的权重。当用户是多个组的成员时,权重最高的角色优先。权重的默认值为 1。
ad_group AD 组的名称。值不能为 Null 或空字符串。

使用说明

调用此函数以列出 AD 安全组和数据库角色之间的所有可用映射。

示例

postgres=> select * from pgadmap_read_mapping(); ad_sid | pg_role | weight | ad_grp ------------------------------------+---------------+--------+------------------ S-1-2-33-12345-67890-12345-678 | accounts-role | 10 | accounts-group (1 row) (1 row)

pgadmap_reset_mapping

此函数重置使用 pgadmap_set_mapping 函数设置的一个或所有映射。

语法

pgadmap_reset_mapping( ad_group_sid, db_role, weight)

参数

参数 描述
ad_group_sid 用于唯一标识 AD 组的安全标识符。
db_role 要映射到指定 AD 组的数据库角色。
weight 与数据库角色关联的权重。

如果未提供任何参数,则将重置 AD 组到数据库角色的所有映射。要么需要提供所有参数,要么不提供任何参数。

返回类型

None

使用说明

调用此函数以删除 AD 组到数据库角色的特定映射或重置所有映射。此函数只能由具有 rds_superuser 权限的用户在数据库集群的主数据库实例上执行。

示例

postgres=> select * from pgadmap_read_mapping(); ad_sid | pg_role | weight | ad_grp --------------------------------+--------------+-------------+------------------- S-1-2-33-12345-67890-12345-678 | accounts-role| 10 | accounts-group S-1-2-33-12345-67890-12345-666 | sales-role | 10 | sales-group (2 rows) postgres=> select pgadmap_reset_mapping('S-1-2-33-12345-67890-12345-678', 'accounts-role', 10); pgadmap_reset_mapping (1 row) postgres=> select * from pgadmap_read_mapping(); ad_sid | pg_role | weight | ad_grp --------------------------------+--------------+-------------+--------------- S-1-2-33-12345-67890-12345-666 | sales-role | 10 | sales-group (1 row) postgres=> select pgadmap_reset_mapping(); pgadmap_reset_mapping (1 row) postgres=> select * from pgadmap_read_mapping(); ad_sid | pg_role | weight | ad_grp --------------------------------+--------------+-------------+-------------- (0 rows)