访问策略和 DML 操作

默认情况下,Vertica 遵守以下规则:用户只能编辑他们可以看到的内容。也就是说,您必须能够看到表中所有行和列的原始值(存储在表中)以及最初为它们定义的数据类型,才能执行对表数据进行修改的操作。例如,如果某一列被定义为 VARCHAR(9),并且该列的访问策略指定同一列为 VARCHAR(10),则使用该访问策略的用户将无法执行以下操作:

  • INSERT

  • UPDATE

  • DELETE

  • MERGE

  • COPY

您可以通过在现有访问策略中指定 GRANT TRUSTED 来覆盖此行为。在评估用户能否执行上述操作时,此选项强制访问策略完全遵循显式 GRANT 语句。

您可以使用 ACCESS_POLICY 系统表查看现有访问策略。

行访问权限

在启用行访问策略的表上,只有当行访问策略中的条件求值为 TRUE 时,才能执行 DML 操作。例如:

t1 如下所示:

 A | B
---+---
 1 | 1
 2 | 2
 3 | 3

在 t1 上创建以下行访问策略:

=> CREATE ACCESS POLICY ON t1 for ROWS
WHERE enabled_role('manager')
OR
A<2
ENABLE;

启用此策略后,对于要执行 DML 操作的用户,存在以下行为:

  • 具有管理员角色的用户可以在表中的所有行上执行 DML,因为策略中的 WHERE 子句评估为 TRUE。

  • 具有非管理员角色的用户只能执行 SELECT 以返回列 A 中值小于 2 的数据。如果访问策略必须读取表中的数据以符合某个条件,则不允许执行 DML 操作。

列访问权限

在启用列访问策略的表上,如果可以查看最初为整个列定义的类型,则可以执行 DML 操作。

假设使用以下数据类型和值创建表 t1:

=> CREATE TABLE t1 (A int, B int);
=> INSERT INTO t1 VALUES (1,2);
=> SELECT * FROM t1;
 A | B
---+---
 1 | 2
(1 row)

假设创建了以下访问策略,该策略在执行时将列 A 的数据类型从 INT 强制为 VARCHAR(20)。

=> CREATE ACCESS POLICY on t1 FOR column A A::VARCHAR(20) ENABLE;
Column "A" is of type int but expression in Access Policy is of type varchar(20). It will be coerced at execution time

在这种情况下,u1 可以查看 A 列的全部内容,但由于活动访问策略未指定 A 列的原始数据类型,因此 u1 无法对 A 列执行 DML 操作。

=> \c - u1
You are now connected as user "u1".
=> SELECT A FROM t1;
 A
---
 1
(1 row)

=> INSERT INTO t1 VALUES (3);
ERROR 6538:  Unable to INSERT: "Access denied due to active access policy on table "t1" for column "A""

使用 GRANT TRUSTED 覆盖默认行为

在访问策略中指定 GRANT TRUSTED 会覆盖默认行为(“用户只能编辑他们可以看到的内容”),并指示访问策略在评估用户能否执行 DML 操作时完全遵循显式 GRANT 语句。

如果数据存储形式与语义上的“真”形式不匹配,GRANT TRUSTED 很有用。

例如,当与 Voltage SecureData 集成时,一个常见的用例是使用 VoltageSecureProtect 存储加密数据,其中解密留给访问策略中用来调用 VoltageSecureAccess 的 case 表达式。在这种情况下,虽然解密形式被直观地理解为数据的“真”形式,但它仍然以其加密形式存储在表中;可以查看解密数据的用户将看不到存储的数据,因此无法执行 DML 操作。您可以使用 GRANT TRUSTED 来覆盖此行为,并允许用户在拥有授权的情况下执行这些操作。

在以下示例中,customer_info 表包含客户名字和姓氏以及 SSN 的列。SSN 很敏感,应该控制对它的访问,因此在插入表时使用 VoltageSecureProtect 对其进行加密:


=> CREATE TABLE customer_info(first_name VARCHAR, last_name VARCHAR, ssn VARCHAR);
=> INSERT INTO customer_info SELECT 'Alice', 'Smith', VoltageSecureProtect('998-42-4910' USING PARAMETERS format='ssn');
=> INSERT INTO customer_info SELECT 'Robert', 'Eve', VoltageSecureProtect('899-28-1303' USING PARAMETERS format='ssn');
=> SELECT * FROM customer_info;
 first_name | last_name |     ssn
------------+-----------+-------------
 Alice      | Smith     | 967-63-8030
 Robert     | Eve       | 486-41-3371
(2 rows)

在此系统中,角色“trusted_ssn”标识特权用户,Vertica 将为这些特权用户使用 VoltageSecureAccess 对“ssn”列的值进行解密。为了允许这些特权用户执行他们有权执行的 DML 操作,您可以使用以下访问策略:

=> CREATE ACCESS POLICY ON customer_info FOR COLUMN ssn
  CASE WHEN enabled_role('trusted_ssn') THEN VoltageSecureAccess(ssn USING PARAMETERS format='ssn')
  ELSE ssn END
  GRANT TRUSTED
  ENABLE;

同样请注意,GRANT TRUSTED 允许表上所有具有 GRANT 的用户执行指定的操作,包括没有“trusted_ssn”角色的用户。