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_adminazuresu- 管理员角色
创建 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 后无法将其删除。
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;
在此示例中,用户 user1 可以连接测试数据库 Test_db 并拥有对该数据库的所有权限,但不包括服务器上任何其他数据库的权限。 不要为此数据库及其对象提供此用户或角色 ALL PRIVILEGES,而是考虑提供更具选择性的权限,例如 SELECT、INSERT、EXECUTE 和其他权限。 有关 PostgreSQL 数据库中权限的详细信息,请参阅 PostgreSQL 文档中的 GRANT 和 REVOKE 命令。
Azure Database for PostgreSQL 中的公共架构所有权更改
在 PostgreSQL 15 及更高版本中,公共架构的所有权更改为新的 pg_database_owner 角色,该角色允许数据库所有者对其进行控制。 有关详细信息,请参阅 PostgreSQL 发行说明。
但是,在 Azure Database for PostgreSQL 中,此更改不适用。 在所有受支持的 PostgreSQL 版本中,公共架构由 azure_pg_admin 角色拥有。 此托管服务行为提供安全性和一致性。
PostgreSQL 16 关于基于角色的安全性变更
在 PostgreSQL 中,数据库角色可以具有许多属性来定义其权限。 其中一个是 CREATEROLE 属性,此属性对 PostgreSQL 数据库管理用户和角色非常重要。 在 PostgreSQL 16 中,对此属性进行了重大更改。
在 PostgreSQL 16 中,具有 CREATEROLE 属性的用户再也无法向任何人分发任何角色的成员身份。 相反,与其他不具有此属性的用户一样,他们只能分发其拥有 ADMIN OPTION 的角色的成员身份。 此外,在 PostgreSQL 16 中,CREATEROLE 属性仍允许非超级用户预配新用户。 但是,他们只能删除自己创建的用户。 如果用户不是由具有 CREATEROLE 属性的用户创建,则尝试删除该用户会导致错误。
PostgreSQL 16 还引入了新的和改进的内置角色。 pg_create_subscription 角色允许超级用户创建订阅。
在 Azure Database for PostgreSQL 灵活服务器中,azure_pg_admin角色是系统托管的受限角色,不能由用户修改。 尝试更改它(例如向其授予另一个角色)将导致如下错误:
GRANT <db_user> TO azure_pg_admin;
ERROR: permission denied to alter restricted role "azure_pg_admin"
这是一种内置保护措施,可防止更改关键管理角色。 如果需要分配特权或角色,请考虑改为创建自定义角色,并向该角色授予必要的权限。
改进了对 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 属性,该属性允许用户写入所有数据(表、视图、序列),就好像对这些对象拥有 INSERT、UPDATE 和 DELETE 权限,以及对所有架构拥有 USAGE 权限,即使并未显式向其授权。 作为一种解决方法,建议对每个数据库和对象授予更有限的级别的类似权限。
行级安全性
行级别安全性 (RLS) 是 Azure Database for PostgreSQL 安全功能,它使数据库管理员能够定义策略来控制控制特定数据行如何针对一个或多个角色显示和操作。 行级别安全性向 Azure Database for PostgreSQL 数据库表中添加额外的筛选器。 当用户尝试对表执行操作时,此筛选器会在查询条件或其他筛选之前应用,并且根据安全策略缩小数据范围或拒绝数据。 可以为特定命令(例如 SELECT、INSERT、UPDATE 和 DELETE)创建行级别安全性策略,或为所有命令指定该策略。 行级别安全性的用例包括符合 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 子句,确保管理员角色的成员不能对属于其他管理员的行执行 SELECT、DELETE 或 UPDATE 操作,并且不能对属于另一个管理员的新行执行 INSERT 操作。
可以使用 DROP POLICY 命令删除行安全性策略,如以下示例所示:
DROP POLICY account_managers ON accounts;
尽管可能会删除该策略,但角色管理器仍无法查看属于任何其他管理器的任何数据。 存在此限制是因为在帐户表上仍然启用了行级别安全性策略。 如果默认启用了行级别安全性,PostgreSQL 将使用默认拒绝策略。
可以禁用行级别安全性,如以下示例所示:
ALTER TABLE accounts DISABLE ROW LEVEL SECURITY;
绕过行级别安全性
PostgreSQL 具有 BYPASSRLS 和 NOBYPASSRLS 权限,你可以将其分配给角色。 默认情况下分配 NOBYPASSRLS。 使用 Azure Database for PostgreSQL 中新预配的服务器,实现绕过行级别安全权限 (BYPASSRLS) 的方式如下所示:
对于 Postgres 16 及更高版本的服务器,我们遵循标准 PostgreSQL 16 行为。 通过由 azure_pg_admin 管理员角色创建的非管理用户,可根据需要创建具有 BYPASSRLS 属性或特权的角色。
对于 Postgres 15 及更低版本的服务器,可以使用 azure_pg_admin 用户执行需要 BYPASSRLS 权限的管理任务。 但是,无法使用 BypassRLS 特权创建非管理员用户,因为管理员角色没有超级用户特权,这在基于云的 PaaS PostgreSQL 服务中很常见。