访问策略和 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 让用户可以对表进行更改,即使数据被访问策略所覆盖也是如此。在这些情况下,某些受访问策略约束但在表上也有 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”角色的用户。