了解 PostgreSQL 角色和权限 - Amazon Relational Database Service

了解 PostgreSQL 角色和权限

在使用 AWS Management Console 创建 RDS for PostgreSQL 数据库实例时,将同时创建管理员账户。默认情况下,其名称为 postgres,如以下屏幕截图所示:


        Create database(创建数据库)页面中凭据的默认登录身份是 postgres。

您可以选择其他名称,而不是接受默认值(postgres)。如果这样做,您选择的名称必须以字母开头,并且必须介于 1 到 16 个字母数字字符之间。为简单起见,在整个指南中,我们将使用默认值 (postgres) 来指代此主用户账户。

如果您使用 create-db-instance AWS CLI 而不是 AWS Management Console,则可以通过将名称传递给命令中的 master-username 参数来创建名称。有关更多信息,请参阅创建 Amazon RDS 数据库实例

无论您是使用 AWS Management Console、AWS CLI 还是 Amazon RDS API,也无论您是使用默认 postgres 名称还是选择其他名称,这第一个数据库用户账户都是 rds_superuser 组的成员并具有 rds_superuser 权限。

了解 rds_superuser 角色

在 PostgreSQL 中,角色可以针对数据库中的各种对象定义一个用户、一个组或一组授予组或用户的特定权限。PostgreSQL 命令 CREATE USERCREATE GROUP 已替换为更通用的 CREATE ROLE,并使用特定属性来区分数据库用户。数据库用户可以被视为具有 LOGIN 权限的角色。

注意

仍然可以使用 CREATE USERCREATE GROUP 命令。有关更多信息,请参阅 PostgreSQL 文档中的数据库角色

postgres 用户是您的 RDS for PostgreSQL 数据库实例上权限最高的数据库用户。它具有以下 CREATE ROLE 语句所定义的特征。

CREATE ROLE postgres WITH LOGIN NOSUPERUSER INHERIT CREATEDB CREATEROLE NOREPLICATION VALID UNTIL 'infinity'

属性 NOSUPERUSERNOREPLICATIONINHERITVALID UNTIL 'infinity' 是 CREATE ROLE 的默认选项,除非另有说明。

原定设置情况下,postgres 具有授予 rds_superuser 角色的权限。rds_superuser 角色允许 postgres 用户执行以下操作:

  • 添加可用于 Amazon RDS 的扩展。有关更多信息,请参阅 使用 Amazon RDS for PostgreSQL 支持的 PostgreSQL 功能

  • 为用户创建角色并向用户授予权限。有关更多信息,请参阅 PostgreSQL 文档中的 CREATE ROLEGRANT

  • 创建数据库。有关更多信息,请参阅 PostgreSQL 文档中的 CREATE DATABASE

  • rds_superuser 权限授予没有这些权限的用户角色,并根据需要撤销权限。我们建议您仅向执行超级用户任务的那些用户授予此角色。换句话说,您可以将此角色授予数据库管理员 (DBA) 或系统管理员。

  • 向没有 rds_superuser 角色的数据库用户授予(和撤销)rds_replication 角色。

  • 向没有 rds_superuser 角色的数据库用户授予(和撤销)rds_password 角色。

  • 通过使用 pg_stat_activity 视图获取有关所有数据库连接的状态信息。需要时,rds_superuser 可以通过使用 pg_terminate_backendpg_cancel_backend 停止任何连接。

CREATE ROLE postgres... 语句中,您可以看到 postgres 用户角色明确禁止 PostgreSQL superuser 权限。RDS for PostgreSQL 是一项托管服务,因此您无法访问主机操作系统,也无法使用 PostgreSQL superuser 账户进行连接。许多需要独立 PostgreSQL 上的 superuser 访问权限的任务都由 Amazon RDS 自动管理。

有关授权权限的更多信息,请参阅 PostgreSQL 文档中的 GRANT

rds_superuser 角色是 中的几个预定义角色之一。RDS for PostgreSQL 数据库实例。

注意

在 PostgreSQL 13 和更早版本中,预定义角色称为默认角色。

在下面的列表中,您可以找到为新 自动创建的一些其他预定义角色。RDS for PostgreSQL 数据库实例。无法更改预定义角色及其权限。无法删除、重命名或修改这些预定义角色的权限。此类尝试会导致错误。

  • rds_password – 可以为数据库用户更改密码和设置密码限制的角色。默认情况下,rds_superuser 角色被授予此角色,并且可以将此角色授予数据库用户。有关更多信息,请参阅控制用户对 PostgreSQL 数据库的访问

  • rdsadmin – 具有 superuser 权限的管理员将对独立的 PostgreSQL 数据库执行许多管理任务,此角色专为处理这些管理任务而创建。此角色由 RDS for PostgreSQL 在内部用于许多管理任务。

  • rdstopmgr – Amazon RDS 在内部用于支持多可用区部署的角色。

要查看所有预定义角色,您可以连接到 您的 RDS for PostgreSQL 数据库实例,并使用 psq1 \du 元命令。输出如下所示:

List of roles Role name | Attributes | Member of --------------+-----------------------------------+------------------------------------ postgres | Create role, Create DB +| {rds_superuser} | Password valid until infinity | rds_superuser | Cannot login | {pg_monitor,pg_signal_backend, | +| rds_replication,rds_password} ...

在输出中,您可以看到 rds_superuser 不是数据库用户角色(无法登录),但它具有许多其他角色的权限。您还可以看到数据库用户 postgresrds_superuser 角色的成员。如前所述,postgres 是 Amazon RDS 控制台的 Create database(创建数据库)页面中的默认值。如果您选择了另一个名称,则该名称将显示在角色列表中。

控制用户对 PostgreSQL 数据库的访问

PostgreSQL 中的新数据库始终使用数据库 public 架构中的一组默认权限创建,允许所有数据库用户和角色创建对象。例如,这些权限使数据库用户能够连接数据库,并在连接后创建临时表格。

为了更好地控制用户对您在 RDS for PostgreSQL 数据库实例上创建的数据库实例的访问,我们建议您撤消这些默认 public 权限。撤消后,您可以更精确地为数据库用户授权,如以下过程中所示。

为新数据库实例设置角色和权限

假设您正在新创建的 RDS for PostgreSQL 数据库实例上设置数据库,以供几位研究人员使用,他们都需要对数据库的读写访问权限。

  1. 使用 psql(或 pgAdmin)连接到 RDS for PostgreSQL 数据库实例:

    psql --host=your-db-instance.666666666666.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password

    出现提示时请输入密码。psql 客户端会建立连接并显示默认的管理连接数据库 postgres=>,作为提示符。

  2. 要阻止数据库用户在 public 架构中创建对象,执行以下操作:

    postgres=> REVOKE CREATE ON SCHEMA public FROM PUBLIC; REVOKE
  3. 接下来,创建一个新数据库实例:

    postgres=> CREATE DATABASE lab_db; CREATE DATABASE
  4. 在这个新数据库上,撤消 PUBLIC 架构的所有权限。

    postgres=> REVOKE ALL ON DATABASE lab_db FROM public; REVOKE
  5. 为数据库用户创建角色。

    postgres=> CREATE ROLE lab_tech; CREATE ROLE
  6. 为具有此角色的数据库用户提供连接到数据库的能力。

    postgres=> GRANT CONNECT ON DATABASE lab_db TO lab_tech; GRANT
  7. 向具有 lab_tech 角色的所有用户授予对此数据库的所有权限。

    postgres=> GRANT ALL PRIVILEGES ON DATABASE lab_db TO lab_tech; GRANT
  8. 创建数据库用户,如下所示:

    postgres=> CREATE ROLE lab_user1 LOGIN PASSWORD 'change_me'; CREATE ROLE postgres=> CREATE ROLE lab_user2 LOGIN PASSWORD 'change_me'; CREATE ROLE
  9. 向这两个用户授予与 lab_tech 角色关联的权限:

    postgres=> GRANT lab_tech TO lab_user1; GRANT ROLE postgres=> GRANT lab_tech TO lab_user2; GRANT ROLE

此时,lab_user1lab_user2 可以连接到 lab_db 数据库。此示例未遵循企业使用的最佳实践,其中可能包括创建多个数据库实例、不同的架构和授予有限权限。有关更多完整信息和其他方案,请参阅管理 PostgreSQL 用户和角色

有关 PostgreSQL 数据库中特权的更多信息,请参阅 PostgreSQL 文档中的 GRANT 命令。

委托和控制用户密码管理

作为 DBA,您可能需要委托用户密码的管理。或者,您可能希望防止数据库用户更改其密码或重新配置密码限制,例如密码生命周期。要确保只有您选择的数据库用户才能更改密码设置,可以启用受限密码管理功能。激活此功能时,只有那些已被授予 rds_password 角色的数据库用户可以管理密码。

注意

要使用受限密码管理,您的 RDS for PostgreSQL 数据库实例必须运行 PostgreSQL 10.6 或更高版本。

默认情况下,此功能为 off,如下所示:

postgres=> SHOW rds.restrict_password_commands; rds.restrict_password_commands -------------------------------- off (1 row)

要启用此功能,请使用自定义参数组并将 rds.restrict_password_commands 的设置更改为 1。一定要重新启动 RDS for PostgreSQL 数据库实例,此设置才能生效。

激活此功能后,以下 SQL 命令需要 rds_password 权限:

CREATE ROLE myrole WITH PASSWORD 'mypassword'; CREATE ROLE myrole WITH PASSWORD 'mypassword' VALID UNTIL '2023-01-01'; ALTER ROLE myrole WITH PASSWORD 'mypassword' VALID UNTIL '2023-01-01'; ALTER ROLE myrole WITH PASSWORD 'mypassword'; ALTER ROLE myrole VALID UNTIL '2023-01-01'; ALTER ROLE myrole RENAME TO myrole2;

如果密码使用 MD5 哈希算法,重命名角色 (ALTER ROLE myrole RENAME TO newname) 也会受到限制。

激活此功能后,在没有 rds_password 角色权限的情况下尝试这些 SQL 命令中的任何一个都会生成以下错误:

ERROR: must be a member of rds_password to alter passwords

我们建议您仅将 rds_password 授予少数几个仅用于密码管理的角色。如果您将 rds_password 权限授予没有 rds_superuser 权限的数据库用户,则还需要授他们 CREATEROLE 属性。

请确保您验证了密码要求,例如客户端上的过期时间以及所需的复杂性。如果您使用自己的客户端实用程序进行与密码相关的更改,则该实用程序需要是 rds_password 的成员并具有 CREATE ROLE 权限。

使用 SCRAM 进行 PostgreSQL 密码加密

在对密码进行加密时,加盐质询响应身份验证机制(SCRAM)是 PostgreSQL 的原定设置消息摘要(MD5)算法的替代方案。―般认为 SCRAM 身份验证机制比 MD5 更安全。要了解有关这两种不同的密码保护方法的更多信息,请参阅 PostgreSQL 文档中的密码身份验证

我们建议您使用 SCRAM 而不是 MD5 作为您的 的密码加密方案。RDS for PostgreSQL 数据库实例中的所有数据库实例中重复此查询。这是一种加密质询-响应机制,它使用 scram-sha-256 算法进行密码身份验证和加密。

要支持 SCRAM,您可能需要更新客户端应用程序的库。例如,42.2.0 之前的 JDBC 版本不支持 SCRAM。有关更多信息,请参阅 PostgreSQL JDBC 驱动程序文档中的 PostgreSQL JDBC 驱动程序。有关其他 PostgreSQL 驱动程序和 SCRAM 支持的列表,请参阅 PostgreSQL 文档中的驱动程序列表

注意

RDS for PostgreSQL 版本 13.1 和更高版本支持 scram-sha-256。这些版本还可让您将数据库实例配置为需要 SCRAM,如以下过程所述。

设置 RDS for PostgreSQL 数据库实例以要求使用 SRAM

您可以要求 RDS for PostgreSQL 数据库实例仅接受使用 scram-sha-256 算法的密码。

在对系统进行更改之前,请务必了解完整的过程,如下所示:

  • 获取有关所有数据库用户的所有角色和密码加密的信息。

  • 仔细检查 RDS for PostgreSQL 数据库实例的参数设置,以了解用于控制密码加密的参数。

  • 如果您的 RDS for PostgreSQL 数据库实例使用原定设置参数组,您需要创建自定义数据库参数组,然后将其应用到您的 RDS for PostgreSQL 数据库实例,以便您可以在需要时修改参数。如果您的 RDS for PostgreSQL 数据库实例使用自定义参数组,您可以稍后根据需要在此过程中修改必要的参数。

  • password_encryption 参数更改为 scram-sha-256

  • 通知所有数据库用户他们需要更新密码。对您的 postgres 账户执行相同的操作。使用 scram-sha-256 算法对新密码进行加密和存储。

  • 验证是否使用加密类型对所有密码加密。

  • 如果所有密码都使用 scram-sha-256,您可以将 rds.accepted_password_auth_method 参数从 md5+scram 更改为 scram-sha-256

警告

仅将 rds.accepted_password_auth_method 更改为 scram-sha-256 之后,使用 md5 加密的密码的任何用户(角色)都将无法连接。

做好准备,以要求 RDS for PostgreSQL 数据库实例使用 SCRAM

在对 RDS for PostgreSQL 数据库实例进行任何更改之前,检查所有现有的数据库用户账户。另外,请检查用于密码的加密类型。您可以使用 rds_tools 扩展来执行这些任务。 RDS for PostgreSQL 13.1 及更高版本支持此扩展。

获取数据库用户(角色)和密码加密方法的列表
  1. 使用 psql 连接到 RDS for PostgreSQL 数据库实例,如下所示。

    psql --host=db-name.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
  2. 安装 rds_tools 扩展。

    postgres=> CREATE EXTENSION rds_tools; CREATE EXTENSION
  3. 获取角色和加密的列表。

    postgres=> SELECT * FROM rds_tools.role_password_encryption_type();

    您将看到类似以下内容的输出。

    rolname | encryption_type ----------------------+----------------- pg_monitor | pg_read_all_settings | pg_read_all_stats | pg_stat_scan_tables | pg_signal_backend | lab_tester | md5 user_465 | md5 postgres | md5 (8 rows)

创建自定义数据库参数组

注意

如果您的 RDS for PostgreSQL 数据库实例已使用自定义参数组,您不需要创建新参数组。

有关 Amazon RDS 的参数组的概述,请参阅在 RDS for PostgreSQL 数据库实例上使用参数

用于密码的密码加密类型在一个参数(即 password_encryption)中设置。 RDS for PostgreSQL 数据库实例允许的加密在另一个参数 rds.accepted_password_auth_method 中设置。更改其中任何一个的原定设置值都要求您创建自定义数据库参数组,然后将其应用到您的实例

也可以使用 AWS Management Console 或 RDS API 创建自定义数据库参数组。有关更多信息,请参阅 。

现在可以将自定义参数组与数据库实例关联。

创建自定义数据库参数组
  1. 使用 CLI 命令 create-db-parameter-group 创建自定义数据库参数组。此示例使用 postgres13 作为此自定义参数组的来源。

    对于 Linux、macOS 或 Unix:

    aws rds create-db-parameter-group --db-parameter-group-name 'docs-lab-scram-passwords' \ --db-parameter-group-family postgres13 --description 'Custom parameter group for SCRAM'

    对于 Windows:

    aws rds create-db-parameter-group --db-parameter-group-name "docs-lab-scram-passwords" ^ --db-parameter-group-family postgres13 --description "Custom DB parameter group for SCRAM"
  2. 使用 CLI 命令 modify-db-instance 将此自定义参数组应用于 RDS for PostgreSQL 数据库集群。

    对于 Linux、macOS 或 Unix:

    aws rds modify-db-instance --db-instance-identifier 'your-instance-name' \ --db-parameter-group-name "docs-lab-scram-passwords

    对于 Windows:

    aws rds modify-db-instance --db-instance-identifier "your-instance-name" ^ --db-parameter-group-name "docs-lab-scram-passwords

    要将 RDS for PostgreSQL 数据库实例与您的自定义数据库参数组重新同步,您需要重启集群的主实例和所有其他实例。为了尽量减少对用户的影响,请安排在常规维护时段内执行此操作。

配置密码加密以使用 SCRAM

RDS for PostgreSQL 数据库实例使用的密码加密机制在数据库参数组password_encryption 参数中设置。允许的值为未设置、md5scram-sha-256。原定设置值取决于 RDS for PostgreSQL 版本,如下所示:

  • RDS for PostgreSQL 14 – 没有原定设置值(未设置)

  • RDS for PostgreSQL 13 – 原定设置为 md5

使用附加到 RDS for PostgreSQL 数据库实例的自定义数据库参数组,您可以修改密码加密参数的值。


          接下来,RDS 控制台显示 RDS for PostgreSQL 的 password_encryption 参数的原定设置值。
将密码加密设置更改为 scram-sha-256
  • 将密码加密的值更改为 scram-sha-256,如下所示。可以立即应用更改,因为参数是动态的,这样,无需重新启动即可使更改生效。

    对于 Linux、macOS 或 Unix:

    aws rds modify-db-parameter-group --db-parameter-group-name \ 'docs-lab-scram-passwords' --parameters 'ParameterName=password_encryption,ParameterValue=scram-sha-256,ApplyMethod=immediate'

    对于 Windows:

    aws rds modify-db-parameter-group --db-parameter-group-name ^ "docs-lab-scram-passwords" --parameters "ParameterName=password_encryption,ParameterValue=scram-sha-256,ApplyMethod=immediate"

将用户角色的密码迁移到 SCRAM

您可以将用户角色的密码迁移到 SCRAM,如下所述。

将数据库用户(角色)密码从 MD5 迁移到 SCRAM
  1. 以管理员用户身份(原定设置用户名 postgres)登录,如下所示。

    psql --host=db-name.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password
  2. 通过使用以下命令,在 RDS for PostgreSQL 数据库实例上检查 password_encryption 参数的设置。

    postgres=> SHOW password_encryption; password_encryption --------------------- md5 (1 row)
  3. 将此参数的值更改为 scram-sha-256。这是一个动态参数,因此您不需要在进行此更改后重新启动该实例。再次检查该值,以确保它现在已设置为 scram-sha-256,如下所示。

    postgres=> SHOW password_encryption; password_encryption --------------------- scram-sha-256 (1 row)
  4. 通知所有数据库用户更改其密码。请确保还要更改您自己的用于 postgres 账户的密码(具有 rds_superuser 权限的数据库用户)。

    labdb=> ALTER ROLE postgres WITH LOGIN PASSWORD 'change_me'; ALTER ROLE
  5. 对于您的 RDS for PostgreSQL 数据库实例上的所有数据库重复此过程。

更改参数以要求使用 SCRAM

这是该过程的最后一步。在以下过程中进行更改后,任何仍对密码使用 md5 加密的用户账户(角色)都将无法登录到 RDS for PostgreSQL 数据库实例

rds.accepted_password_auth_method 指定 RDS for PostgreSQL 数据库实例在登录过程中接受的用户密码加密方法。原定设置值为 md5+scram,这意味着可以接受任一种方法。在下面的图中,您可以找到此参数的原定设置。


        RDS 控制台显示 rds.accepted_password_auth_method 参数的原定设置值和允许的值。

此参数允许的值仅为 md5+scramscram。如果将此参数值更改为 scram,则必须使用这种方法。

更改参数值以要求对密码进行 SCRAM 身份验证
  1. 验证 RDS for PostgreSQL 数据库实例上所有数据库的所有数据库用户密码是否使用 scram-sha-256 进行密码加密。为此,查询 rds_tools 以获得角色(用户)和加密类型,如下所示。

    postgres=> SELECT * FROM rds_tools.role_password_encryption_type(); rolname | encryption_type ----------------------+----------------- pg_monitor | pg_read_all_settings | pg_read_all_stats | pg_stat_scan_tables | pg_signal_backend | lab_tester | scram-sha-256 user_465 | scram-sha-256 postgres | scram-sha-256 ( rows)
  2. 在您的 RDS for PostgreSQL 数据库实例中的所有数据库实例中重复此查询。

    如果所有密码都使用 scram-sha-256,您可以继续操作。

  3. 将接受的密码身份验证的值更改为 scram-sha-256,如下所示。

    对于 Linux、macOS 或 Unix:

    aws rds modify-db-parameter-group --db-parameter-group-name 'docs-lab-scram-passwords' \ --parameters 'ParameterName=rds.accepted_password_auth_method,ParameterValue=scram,ApplyMethod=immediate'

    对于 Windows:

    aws rds modify-db-parameter-group --db-parameter-group-name "docs-lab-scram-passwords" ^ --parameters "ParameterName=rds.accepted_password_auth_method,ParameterValue=scram,ApplyMethod=immediate"