Azure Database for PostgreSQL 的访问管理

管理对 Azure Database for PostgreSQL 资源的访问是维护安全性和符合性的重要组成部分。 本文介绍如何使用 PostgreSQL 角色和 Azure 功能来控制权限并实现访问管理的最佳做法。

角色管理

大规模管理 Azure Database for PostgreSQL 数据库访问权限的最佳方式是使用 角色的概念。 角色可以是数据库用户或一组数据库用户。 角色可以拥有数据库对象,并将这些对象的特权分配给其他角色,以控制谁有权访问哪些对象。 可以将角色中的成员身份授予另一个角色,该角色允许成员角色使用分配给另一个角色的权限。 使用 Azure Database for PostgreSQL,可以直接向数据库用户授予权限。 作为一种良好的安全做法,请根据最低应用程序和访问要求创建具有特定权限集的角色。 将相应的角色分配给每个用户。 使用角色强制实施 最低特权模型 来访问数据库对象。

除了 PostgreSQL 创建的内置角色外,Azure Database for PostgreSQL 实例还包括三个默认角色。 可以通过运行以下命令来查看这些角色:

SELECT rolname FROM pg_roles;

角色包括:

  • azure_pg_admin
  • azuresu
  • 管理员角色

创建 Azure Database for PostgreSQL 实例时,请提供 管理员角色的凭据。 使用此管理员角色创建更多 PostgreSQL 角色

例如,可以创建名为 demouser 的用户或角色。

CREATE USER demouser PASSWORD password123;

不要对应用程序使用 管理员角色

在基于云的 PaaS 环境中,只能由云操作员访问 Azure Database for PostgreSQL 超级用户帐户来控制平面作。 因此,该 azure_pg_admin 帐户作为伪超级用户帐户存在。 管理员角色是该 azure_pg_admin 角色的成员。 但是,服务器管理员帐户不是角色的 azuresu 一部分,该角色具有超级用户特权,用于执行控制平面作。 由于此服务是托管的 PaaS 服务,因此只有Microsoft是超级用户角色的一部分。

可以定期审核服务器中的角色列表。

例如,可以使用客户端进行连接 psql 并查询 pg_roles 表,该表列出了所有角色以及创建其他角色、创建数据库、复制等权限。

select * from pg_roles where rolname='demouser';
-[ RECORD 1 ]--+---------
rolname        | demouser
rolsuper       | f
rolinherit     | t
rolcreaterole  | f
rolcreatedb    | f
rolcanlogin    | f
rolreplication | f
rolconnlimit   | -1
rolpassword    | ********
rolvaliduntil  |
rolbypassrls   | f
rolconfig      |
oid            | 24827

重要

最近,Azure Database for PostgreSQL 启用了创建 CAST 命令的功能。 若要运行 CREATE CAST 语句,用户必须是 azure_pg_admin 组的成员。 目前,创建 CAST 后无法删除该 CAST。

Azure Database for PostgreSQL 仅支持使用和WITH FUNCTION选项的 WITH INOUT CAST 命令。 不支持此选项 WITHOUT FUNCTION

Azure Database for PostgreSQL 中的审核日志记录 也可用于 Azure Database for PostgreSQL 来跟踪数据库中的活动。

控制架构访问

在 Azure Database for PostgreSQL 中新建的数据库包括数据库公共架构中的一组默认特权,该权限授予所有数据库用户和角色创建对象的能力。 为了更好地限制对在 Azure Database for PostgreSQL 实例上创建的数据库的应用程序用户访问权限,请考虑撤销这些默认的公共特权。 撤消这些特权后,以更精细的方式向数据库用户授予特定权限。 例如:

  • public角色撤消对架构的创建权限public,以防止应用程序数据库用户在公共架构中创建对象。

    REVOKE CREATE ON SCHEMA public FROM PUBLIC;
    
  • 创建新的 数据库。

    CREATE DATABASE Test_db;
    
  • 从此新数据库的 PUBLIC 架构撤消所有特权。

    REVOKE ALL ON DATABASE Test_db FROM PUBLIC;
    
  • 为应用程序数据库用户创建自定义角色。

    CREATE ROLE Test_db_user;
    
  • 使具有此角色的数据库用户能够连接到数据库。

    GRANT CONNECT ON DATABASE Test_db TO Test_db_user;
    GRANT ALL PRIVILEGES ON DATABASE Test_db TO Test_db_user;
    
  • 创建数据库用户。

    CREATE USER user1 PASSWORD 'Password_to_change'
    
  • 向用户分配角色及其连接并选择权限。

    GRANT Test_db_user TO user1;
    

在此示例中,用户 用户 1 可以在 测试数据库中Test_db连接并拥有所有特权,但不能在服务器上拥有任何其他数据库。 不要为此数据库及其对象提供此用户或角色 ALL PRIVILEGES,而是考虑提供更具选择性的权限,例如SELECTINSERTEXECUTE和其他权限。 有关 PostgreSQL 数据库中的权限的详细信息,请参阅 PostgreSQL 文档中的 GRANTREVOKE 命令。

Azure Database for PostgreSQL 中的公共架构所有权更改

在 PostgreSQL 15 及更高版本中,公共架构的所有权更改为新 pg_database_owner 角色,该角色允许数据库所有者控制它。 有关详细信息,请参阅 PostgreSQL 发行说明。 但是,在 Azure Database for PostgreSQL 中,此更改不适用。 公共架构由 azure_pg_admin 所有受支持的 PostgreSQL 版本的角色拥有。 此托管服务行为提供安全性和一致性。

具有基于角色的安全性的 PostgreSQL 16 更改

在 PostgreSQL 中,数据库角色可以具有定义其权限的许多属性。 其中一个属性是 CREATEROLE 属性,这对 PostgreSQL 数据库管理用户和角色非常重要。 在 PostgreSQL 16 中,对此属性进行了重大更改。

在 PostgreSQL 16 中,具有 CREATEROLE 属性的用户不再能够向任何人分发任何角色的成员身份。 相反,与没有此属性的其他用户一样,他们只能分发其拥有 ADMIN OPTION的角色的成员身份。 此外,在 PostgreSQL 16 中, CREATEROLE 属性仍允许非监督程序预配新用户。 但是,他们只能删除自己创建的用户。 尝试删除用户会导致用户在未使用 CREATEROLE 属性创建用户时出错。

PostgreSQL 16 还引入了新的和改进的内置角色。 PostgreSQL 16 中的新 pg_use_reserved_connections 角色允许使用通过 reserved_connections 保留的连接槽。 pg_create_subscription角色允许超级用户创建订阅。

改进了对azure_pg_admin的控制

在 PostgreSQL 16 中,使用 CREATEROLE 特权的用户实现了严格的角色层次结构,特别是与授予角色相关的。 为了提高管理灵活性并解决 PostgreSQL 16 中引入的限制,Azure Database for PostgreSQL 增强了所有 PostgreSQL 版本中 azure_pg_admin 角色的功能。 通过此更新, azure_pg_admin 角色的成员可以管理任何非限制角色拥有的角色和访问对象,即使这些角色也是 azure_pg_admin的成员。 此增强功能可确保管理用户保持对角色和权限管理的一致和全面控制,从而提供无缝且可靠的体验,而无需超级用户访问。

重要

Azure Database for PostgreSQL 不允许向用户授予pg_write_all_data属性,该属性允许用户写入所有数据(表、视图、序列),就像对这些对象拥有INSERTUPDATEDELETE权限一样,以及所有架构的 USAGE 权限,即使未显式授予它。 作为一种解决方法,建议为每个数据库和对象授予更有限的级别的类似权限。

行级安全性

行级别安全性(RLS) 是一项 Azure Database for PostgreSQL 安全功能,它使数据库管理员能够定义策略,控制数据的特定行如何显示和作一个或多个角色。 行级别安全性向 Azure Database for PostgreSQL 数据库表添加额外的筛选器。 当用户尝试对表执行作时,会在查询条件或其他筛选之前应用此筛选器,并且数据会根据安全策略缩小或拒绝范围。 可以为特定命令(例如SELECTINSERTUPDATEDELETE)创建行级安全策略,或为所有命令指定该策略。 行级别安全性的用例包括符合 PCI 的实现、分类的环境以及共享托管或多租户应用程序。

只有具有权限的用户 SET ROW SECURITY 才能将行安全权限应用于表。 表所有者可以对表设置行安全性。 类似于 OVERRIDE ROW SECURITY,此权限当前是隐式权限。 行级别安全性不会替代现有 GRANT 权限。 它增加了精细的控制级别。 例如,如果 ROW SECURITY FOR SELECT 给定用户对列或表具有 SELECT 权限,则设置为允许给定用户访问行仅授予该用户访问权限。

以下示例演示如何创建一个策略,确保只有自定义创建的 管理器角色 的成员才能访问特定帐户的行。 以下示例中的代码在 PostgreSQL 文档中共享。

CREATE TABLE accounts (manager text, company text, contact_email text);

ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;

CREATE POLICY account_managers ON accounts TO managers
  USING (manager = current_user);

USING子句隐式添加一个WITH CHECK子句,确保经理角色的成员不能对属于其他经理的行执行SELECTDELETEUPDATE作,并且不能INSERT对属于另一个管理器的新行执行作。

可以使用命令删除行安全策略 DROP POLICY ,如以下示例所示:

DROP POLICY account_managers ON accounts;

尽管可能会删除策略,但角色管理器仍无法查看属于任何其他经理的任何数据。 存在此限制,因为行级别安全策略仍在帐户表上启用。 如果默认启用行级别安全性,PostgreSQL 将使用默认拒绝策略。

可以禁用行级别安全性,如以下示例所示:

ALTER TABLE accounts DISABLE ROW LEVEL SECURITY;

绕过行级别安全性

PostgreSQL 具有 BYPASSRLSNOBYPASSRLS 权限,你可以将其分配给角色。 默认情况下分配 NOBYPASSRLS。 在 Azure Database for PostgreSQL 中 新预配的服务器 时,将按如下所示实现行级安全特权(BYPASSRLS):

  • 对于 Postgres 16 和更高版本的服务器,我们遵循 标准 PostgreSQL 16 行为azure_pg_admin管理员角色创建的非管理员用户允许根据需要使用 BYPASSRLS 属性或特权创建角色。

  • 对于 Postgres 15 和更低版本的服务器,可以使用 azure_pg_admin 用户执行需要 BYPASSRLS 权限的管理任务。 但是,无法使用 BypassRLS 特权创建非admin 用户,因为管理员角色没有超级用户特权,这在基于云的 PaaS PostgreSQL 服务中很常见。