数据库用户应仅对执行其任务所需要的数据库资源具有访问权限。例如,大多数用户应该能够读取数据,但无法修改或插入新数据。少数用户通常需要用来执行更广泛数据库任务(例如,创建和修改架构、表和视图)的权限。极少数用户可以执行管理任务,例如重新平衡群集上的节点,或者启动或停止数据库。您还可以让某些用户将自己的权限扩展到其他用户。
客户端身份验证控制着数据库对象用户在数据库中可以访问和更改的内容。您可以使用 GRANT 语句为特定用户或角色指定访问权限。
数据库用户应仅对执行其任务所需要的数据库资源具有访问权限。例如,大多数用户应该能够读取数据,但无法修改或插入新数据。少数用户通常需要用来执行更广泛数据库任务(例如,创建和修改架构、表和视图)的权限。极少数用户可以执行管理任务,例如重新平衡群集上的节点,或者启动或停止数据库。您还可以让某些用户将自己的权限扩展到其他用户。
客户端身份验证控制着数据库对象用户在数据库中可以访问和更改的内容。您可以使用 GRANT 语句为特定用户或角色指定访问权限。
每个 Vertica 数据库都有一个或多个用户。当用户连接至数据库时,他们必须使用超级用户在数据库中定义的有效凭证(用户名和密码)登录。
数据库用户拥有其在数据库中创建的表、过程和存储位置等对象。
在 Vertica 数据库中,共有三种类型的用户:
数据库管理员 (DBADMIN)
对象所有者
其他所有人 (PUBLIC)
安装时,新的 Vertica 数据库会自动包含具有 超级用户权限的用户。除非在安装期间显式命名,否则此用户被标识为 dbadmin
。此用户不能被删除,并且具有以下不可撤销的角色:
使用这些角色,dbadmin
用户可以执行所有数据库操作。此用户还可以创建其他具有管理权限的用户。
不要将 dbadmin
用户与 DBADMIN 角色的用户混淆。DBADMIN 角色是一组可以分配给一个或多个用户的权限。
Vertica 文档经常将 dbadmin
用户称为超级用户。此参考文档与 Linux 超级用户无关。
dbadmin
用户可以创建具有相同权限的其他用户:
创建用户:
=> CREATE USER DataBaseAdmin2; CREATE USER
向新用户 DataBaseAdmin2
授予相应角色:
=> GRANT dbduser, dbadmin, pseudosuperuser to DataBaseAdmin2;
GRANT ROLE
用户 DataBaseAdmin2
现在具有与授予给最初 dbadmin 用户相同的权限。
DataBaseAdmin2
使用 SET ROLE 启用已分配给您的角色:
=> \c - DataBaseAdmin2;
You are now connected to database "VMart" as user "DataBaseAdmin2". => SET ROLE dbadmin, dbduser, pseudosuperuser; SET ROLE
确认角色已启用:
=> SHOW ENABLED ROLES;
name | setting ------------------------------------------------- enabled roles | dbduser, dbadmin, pseudosuperuser
对象所有者是创建特定数据库对象并可以对该对象执行任何操作的用户。默认情况下,仅所有者(或 超级用户)可以对数据库对象执行操作。为了允许其他用户使用对象,所有者或超级用户必须使用其中一个 GRANT 语句向这些用户授予权限。
有关详细信息,请参阅数据库权限。
所有非 DBA(超级用户)或对象所有者都是 PUBLIC 用户。
新创建的用户默认没有 PUBLIC 架构的访问权。请确保对创建的所有用户运行 GRANT USAGE ON SCHEMA PUBLIC。
要创建数据库用户:
以超级用户身份从 vsql 连接至数据库。
发出
CREATE USER
语句及可选参数。
运行一系列 GRANT 语句,授予新用户权限。
要在 MC 上创建用户,请参阅在管理控制台中创建 MC 用户
默认情况下,新数据库用户有权在数据库中创建临时表。
新创建的用户默认没有 PUBLIC
架构的访问权。请确保对创建的所有用户运行 GRANT USAGE ON SCHEMA PUBLIC
可以使用
ALTER USER
语句更改用户相关信息,例如用户的密码。如果要将用户配置为不使用任何密码身份验证,可以在 CREATE USER
或 ALTER USER
语句中设置空密码 '',或在 CREATE USER
中忽略 IDENTIFIED BY
参数。
以下一系列命令将密码为“password”的用户 Fred 添加到数据库。第二个命令向 Fred 授予公共架构的 USAGE 权限:
=> CREATE USER Fred IDENTIFIED BY 'password';
=> GRANT USAGE ON SCHEMA PUBLIC to Fred;
使用双引号创建的用户名区分大小写。例如:
=> CREATE USER "FrEd1";
在上述示例中,登录名必须完全匹配。如果创建用户名时没有使用双引号(例如,FRED1
),则用户可以使用 FRED1
、FrEd1
、fred1
等登录。
ALTER USER 允许您为单个用户设置用户级别配置参数。这些设置会覆盖相同参数的数据库或会话级别设置。例如,以下 ALTER USER 语句将用户 Yvonne 和 Ahmed 的 DepotOperationsForQuery 设置为 FETCHES,从而覆盖默认设置 ALL:
=> SELECT user_name, parameter_name, current_value, default_value FROM user_configuration_parameters
WHERE user_name IN('Ahmed', 'Yvonne') AND parameter_name = 'DepotOperationsForQuery';
user_name | parameter_name | current_value | default_value
-----------+-------------------------+---------------+---------------
Ahmed | DepotOperationsForQuery | ALL | ALL
Yvonne | DepotOperationsForQuery | ALL | ALL
(2 rows)
=> ALTER USER Ahmed SET DepotOperationsForQuery='FETCHES';
ALTER USER
=> ALTER USER Yvonne SET DepotOperationsForQuery='FETCHES';
ALTER USER
若要标识用户级别配置参数,请查询系统表 CONFIGURATION_PARAMETERS 的 allowed_levels
列。例如,以下查询标识会影响存储库使用的用户级别参数:
n=> SELECT parameter_name, allowed_levels, default_value, current_level, current_value
FROM configuration_parameters WHERE allowed_levels ilike '%USER%' AND parameter_name ilike '%depot%';
parameter_name | allowed_levels | default_value | current_level | current_value
-------------------------+-------------------------+---------------+---------------+---------------
UseDepotForReads | SESSION, USER, DATABASE | 1 | DEFAULT | 1
DepotOperationsForQuery | SESSION, USER, DATABASE | ALL | DEFAULT | ALL
UseDepotForWrites | SESSION, USER, DATABASE | 1 | DEFAULT | 1
(3 rows)
可以用以下两种方式获取用户设置:
查询系统表 USER_CONFIGURATION_PARAMETERS:
=> SELECT * FROM user_configuration_parameters;
user_name | parameter_name | current_value | default_value
-----------+---------------------------+---------------+---------------
Ahmed | DepotOperationsForQuery | FETCHES | ALL
Yvonne | DepotOperationsForQuery | FETCHES | ALL
Yvonne | LoadSourceStatisticsLimit | 512 | 256
(3 rows)
使用 SHOW USER:
=> SHOW USER Yvonne PARAMETER ALL;
user | parameter | setting
--------+---------------------------+---------
Yvonne | DepotOperationsForQuery | FETCHES
Yvonne | LoadSourceStatisticsLimit | 512
(2 rows)
=> SHOW USER ALL PARAMETER ALL;
user | parameter | setting
--------+---------------------------+---------
Yvonne | DepotOperationsForQuery | FETCHES
Yvonne | LoadSourceStatisticsLimit | 512
Ahmed | DepotOperationsForQuery | FETCHES
(3 rows)
作为超级用户,您可以使用 ALTER USER...ACCOUNT LOCK 手动锁定数据库用户帐户,使用 ALTER USER...ACCOUNT UNLOCK 解锁数据库用户帐户。例如,下列命令将阻止用户 Fred 登录到数据库:
=> ALTER USER Fred ACCOUNT LOCK;
=> \c - Fred
FATAL 4974: The user account "Fred" is locked
HINT: Please contact the database administrator
以下示例解锁对 Fred 的用户帐户的访问权限:
=> ALTER USER Fred ACCOUNT UNLOCK;|
=> \c - Fred
You are now connected as user "Fred".
CREATE USER 可以指定锁定新帐户。与任何锁定的帐户一样,可以使用 ALTER USER...ACCOUNT UNLOCK 解锁它。
=> CREATE USER Bob ACCOUNT LOCK;
CREATE USER
用户的配置文件可以指定在登录尝试失败一定次数后锁定帐户。
作为超级用户,您可以在使用 CREATE USER 创建用户时或稍后使用 ALTER USER 设置任何用户的密码。非超级用户还可以使用 ALTER USER 更改自己的密码。有一个例外情况:使用 LDAPLink 服务添加到 Vertica 数据库的用户无法使用 ALTER USER 更改其密码。
如果您提供相关的 salt,您还可以为用户提供预先经过哈希处理的密码。salt 必须是十六进制字符串。此方法绕过密码复杂性要求。
要查看现有用户的密码哈希和 salt,请参阅 PASSWORDS 系统表。
更改用户的密码对其当前会话没有影响。
在以下示例中,使用密码“mypassword”创建用户“Bob”。
=> CREATE USER Bob IDENTIFIED BY 'mypassword';
CREATE USER
随后将密码更改为“Orca”。
=> ALTER USER Bob IDENTIFIED BY 'Orca' REPLACE 'mypassword';
ALTER USER
在以下示例中,使用预先经过哈希处理的密码和 salt 创建用户“Alice”。
=> CREATE USER Alice IDENTIFIED BY
'sha512e0299de83ecfaa0b6c9cbb1feabfbe0b3c82a1495875cd9ec1c4b09016f09b42c1'
SALT '465a4aec38a85d6ecea5a0ac8f2d36d8';
在管理控制台上,具有 ADMIN 或 IT 权限的用户可以重置用户的非 LDAP 密码:
登录管理控制台并导航至 MC 设置 (MC Settings) > 用户管理 (User management)。
单击选择要修改的用户,再单击编辑 (Edit)。
单击编辑密码 (Edit password),然后输入两次新密码。
单击确定 (OK),然后单击保存 (Save)。
角色是可以向一个或多个用户或其他角色授予的权限集。角色可帮助您授予和管理不同类别用户的权限集,而不是将这些权限单独授予每个用户。
例如,多个用户可能需要管理权限。您可以按如下方式向他们授予这些权限:
使用 CREATE ROLE创建管理员角色:
CREATE ROLE administrator;
使用一个或多个 GRANT 语句向此角色授予适当的权限。您可以在以后根据需要添加和移除权限。角色权限的更改会自动传播给拥有该角色的用户。
Vertica 具有以下预定义角色:
安装时,Vertica 会自动按如下方式授予和启用预定义角色:
将 DBADMIN、PSEUDOSUPERUSER 和 DBDUSER 角色不可撤销地授予 dbadmin 用户。这些角色始终会针对 dbadmin
启用,并且永远无法删除。
在创建时将 PUBLIC 授予 dbadmin
以及所有其他用户。此角色始终处于启用状态,并且无法删除或撤销。
安装后,dbadmin
用户和具有 PSEUDOSUPERUSER 角色的用户可以将一个或多个预定义角色授予任何用户或非预定义角色。例如,以下一组语句创建 userdba
角色并向它授予预定义角色 DBADMIN:
=> CREATE ROLE userdba;
CREATE ROLE
=> GRANT DBADMIN TO userdba WITH ADMIN OPTION;
GRANT ROLE
如果原始 授权(角色) 语句包含 WITH ADMIN OPTION,则被授予预定义角色的用户和角色可以将该角色授予其他用户。有一个例外:如果您向某个用户授予 PSEUDOSUPERUSER 角色并省略 WITH ADMIN OPTION,则被授予者可以将任何角色(包括所有预定义角色)授予其他用户。
例如,userdba
角色以前被授予 DBADMIN 角色。因为 GRANT 语句包含 WITH ADMIN OPTION,所以被分配 userdba
角色的用户可以将 DBADMIN 角色授予其他用户:
=> GRANT userdba TO fred;
GRANT ROLE
=> \c - fred
You are now connected as user "fred".
=> SET ROLE userdba;
SET
=> GRANT dbadmin TO alice;
GRANT ROLE
您可以向除 SYSMONITOR 以外的预定义角色授予对单个数据库对象(例如表或架构)的权限。例如:
=> CREATE SCHEMA s1;
CREATE SCHEMA
=> GRANT ALL ON SCHEMA s1 to PUBLIC;
GRANT PRIVILEGE
您可以向 PUBLIC 授予任何角色,包括预定义角色。例如:
=> CREATE ROLE r1;
CREATE ROLE
=> GRANT r1 TO PUBLIC;
GRANT ROLE
对于任何其他预定义角色,不能通过向其授予其他角色来修改它。尝试这样做会导致回退错误:
=> CREATE ROLE r2;
CREATE ROLE
=> GRANT r2 TO PSEUDOSUPERUSER;
ROLLBACK 2347: Cannot alter predefined role "pseudosuperuser"
DBADMIN
角色是在安装数据库时分配给 dbadmin
用户的预定义角色。安装后,dbadmin
用户和具有
PSEUDOSUPERUSER
角色的用户可以将任何角色授予任何用户或非预定义角色。
例如,超级用户 dbadmin
创建角色 fred
并向 fred
授予 DBADMIN
角色:
=> CREATE USER fred;
CREATE USER
=> GRANT DBADMIN TO fred WITH ADMIN OPTION;
GRANT ROLE
在用户 fred
启用其 DBADMIN role
后,他可以通过创建用户 alice
来行使他的 DBADMIN
权限。因为 GRANT
语句包含 WITH ADMIN OPTION
,所以 fred 也可以将 DBADMIN
角色授予用户 alice
:
=> \c - fred
You are now connected as user "fred".
=> SET ROLE dbadmin;
SET
CREATE USER alice;
CREATE USER
=> GRANT DBADMIN TO alice;
GRANT ROLE
下表列出了 DBADMIN 角色支持的权限:
创建用户和角色,并向他们授予角色和权限
创建和删除架构
查看所有系统表
查看和终止用户会话
访问任意用户创建的所有数据
PSEUDOSUPERUSER
角色是在安装数据库时自动分配给 dbadmin
用户的预定义角色。dbadmin
可以将此角色授予任何用户角色或非预定义角色。此后,PSEUDOSUPERUSER
用户可以将任何角色(包括预定义角色)授予其他用户。
具有 PSEUDOSUPERUSER
角色的用户有权履行管理权限(无法撤销)。角色权限包括:
绕过所有 GRANT/REVOKE 身份验证
创建架构和表
创建用户和角色,并向他们授予权限
修改用户帐户,例如,设置用户帐户的密码、锁定/解锁帐户。
创建或删除 UDF 库和函数,或任何外部过程
DBDUSER
角色是在安装数据库时分配给 dbadmin
用户的预定义角色。dbadmin
和任何 PSEUDOSUPERUSER
可以将此角色授予任何用户或非预定义角色。拥有此角色并启用它的用户可以从命令行调用 Database Designer 函数。
确保将资源池与 DBDUSER
角色相关联,以方便在运行 Database Designer 时进行资源管理。多个用户可以同时运行 Database Designer,他们互相之间不会出现干扰,也不会用尽群集的所有资源。当您以编程方式或使用管理工具运行 Database Designer 时,设计执行操作通常会限制在该用户的资源池内,但不太密集的任务可能会溢出到系统资源池。
除了作为 DBADMIN 用户维护 Vertica 以外,组织的数据库管理员可能还有许多责任。在本例中,DBADMIN 可能希望将一些 Vertica 管理任务委托给其他 Vertica 用户。
DBADMIN 可以将任务委托给 SYSMONITOR 角色,为其授予对系统表的访问权限,而不必授予完整的 DBADMIN 访问权限。
SYSMONITOR 角色提供以下权限。
查看所有标记为可监控的系统表。通过发出以下语句,您可以查看所有可监控表的列表:
=> select * from system_tables where is_monitorable='t';
如果在将 SYSMONITOR 授予用户或角色时包含 WITH ADMIN OPTION
,则该用户或角色可以将 SYSMONITOR 权限授予其他用户和角色。
若要为用户或角色授予 SYSMONITOR 角色,您必须是以下身份之一:
DBADMIN 用户
已分配有 SYSMONITOR 且具有 ADMIN OPTION 的用户
使用 GRANT(角色) SQL 语句为用户分配 SYSMONITOR 角色。以下示例将展示如何为 user1 授予 SYSMONITOR 角色,并通过使用 WITH ADMIN OPTION 参数包含管理权限。ADMIN OPTION 将为 SYSMONITOR 角色授予管理权限。
=> GRANT SYSMONITOR TO user1 WITH ADMIN OPTION
;
以下示例将展示如何为 user1 撤销 SYSMONITOR 角色的 ADMIN OPTION 权限。
=> REVOKE ADMIN OPTION for SYSMONITOR FROM user1
;
使用 CASCADE 为所有分配有 SYSMONITOR 角色的用户撤销 ADMIN OPTION 权限。
=> REVOKE ADMIN OPTION for SYSMONITOR FROM PUBLIC CASCADE
;
以下示例将展示如何:
创建用户
创建角色
为新角色授予 SYSMONITOR 权限
为用户授予角色
=> CREATE USER user1; => CREATE ROLE monitor; => GRANT SYSMONITOR to monitor; => GRANT monitor to user1;
以下示例将使用“授予 SYSMONITOR 角色”示例中创建的用户和角色来说明如何:
创建名为 personal_data 的表
以 user1 身份登录
为 user1 授予 monitor 角色。(您已在“授予 SYSMONITOR 角色”示例中为 monitor 授予了 SYSMONITOR 权限。)
以 user1 身份运行 SELECT 语句
操作结果取决于已授予 user1 的权限。
=> CREATE TABLE personal_data (SSN varchar (256));=> \c -user1;user1=> SET ROLE monitor;user1=> SELECT COUNT(*) FROM TABLES;COUNT ------- 1 (1 row)
由于您已分配了 SYSMONITOR 角色,因此 user1 可以看到 Tables 系统表中行的数量。在这个简单的示例中,数据库中只有一个表 (personal_data),因此 SELECT COUNT 返回一行。在实际情况中,SYSMONITOR 角色将看到数据库中的所有表。
使用下列命令检查分配有 SYSMONITOR 角色的用户是否可以访问系统表:
=> select table_name, is_monitorable from system_tables where table_name='<table_name>';
示例
以下示例将检查 SYSMONITOR 是否可以访问 current_session 系统表:
=> select table_name,is_monitorable from system_tables where table_name='current_session';table_name | is_monitorable -------------------------------- current_session | t
Is_monitorable 列中的 t 表示 SYSMONITOR 可以访问 current_session 系统表。
UDXDEVELOPER 角色是允许用户创建和替换用户所定义库的预定义角色。dbadmin
可以将此角色授予任何用户角色或非预定义角色。
具有 UDXDEVELOPER 角色的用户可以执行以下操作:
如果为库所有者或具有 DROP 权限:
CREATE OR REPLACE LIBRARY
要使用此角色的权限,您必须使用 SET ROLE 显式启用它。
具有 UDXDEVELOPER 角色的用户可以创建库,因此可以在数据库中安装任何 UDx 函数。UDx 函数以拥有数据库的 Linux 用户身份运行,因此可以访问 Vertica 有权访问的资源。
写得不好的函数会降低数据库性能。请仅将此角色授予您相信会负责任地使用 UDx 的用户。您可以通过在隔离模式下运行 UDx 并设置 FencedUDxMemoryLimitMB 配置参数来限制 UDx 可以使用的内存。
PUBLIC
角色是自动分配给所有新用户的预定义角色。它始终处于启用状态,并且无法删除或撤销。使用此角色授予所有数据库用户相同的最低权限集。
与所有其他角色一样,可以授予 PUBLIC
角色对单个对象和其他角色的权限。以下示例授予 PUBLIC
角色对表 publicdata
的 INSERT 和 SELECT 权限。这使所有用户都可以读取该表中的数据并插入新数据:
=> CREATE TABLE publicdata (a INT, b VARCHAR);
CREATE TABLE
=> GRANT INSERT, SELECT ON publicdata TO PUBLIC;
GRANT PRIVILEGE
=> CREATE PROJECTION publicdataproj AS (SELECT * FROM publicdata);
CREATE PROJECTION
=> \c - bob
You are now connected as user "bob".
=> INSERT INTO publicdata VALUES (10, 'Hello World');
OUTPUT
--------
1
(1 row)
以下示例向 PUBLIC
授予 employee
角色,以便所有数据库用户都具有 employee
权限:
=> GRANT employee TO public;
GRANT ROLE
PUBLIC
指定为被授予者的任何 GRANT
语句,子句 WITH ADMIN OPTION
都是无效的。
通过将角色授予其他角色,您可以构建角色层次结构,层次结构中较低的角色具有较窄的权限范围,而层次结构中较高的角色被授予角色及其权限的组合。当您按分层方式组织角色时,添加到较低级别角色的任何权限都会自动传播到它们上方的角色。
以下示例将创建两个角色,为其分配权限,然后将这两个角色分配给另一个角色。
创建名为 applog
的表:
=> CREATE TABLE applog (id int, sourceID VARCHAR(32), data TIMESTAMP, event VARCHAR(256));
创建 logreader
角色并授予它对表 applog
的只读权限:
=> CREATE ROLE logreader;
CREATE ROLE
=> GRANT SELECT ON applog TO logreader;
GRANT PRIVILEGE
创建 logwriter
角色并授予它对表 applog
的写入权限:
=> CREATE ROLE logwriter;
CREATE ROLE
=> GRANT INSERT, UPDATE ON applog to logwriter;
GRANT PRIVILEGE
创建 logadmin
角色并授予它对表 applog
的删除权限:
=> CREATE ROLE logadmin;
CREATE ROLE
=> GRANT DELETE ON applog to logadmin;
GRANT PRIVILEGE
将 logreader
和 logwriter
角色授予角色 logadmin
:
=> GRANT logreader, logwriter TO logadmin;
创建用户 bob
并向他授予 logadmin
角色:
=> CREATE USER bob;
CREATE USER
=> GRANT logadmin TO bob;
GRANT PRIVILEGE
修改用户 bob
的帐户,使他的 logadmin
角色在登录时自动启用:
=> ALTER USER bob DEFAULT ROLE logadmin;
ALTER USER
=> \c - bob
You are now connected as user "bob".
=> SHOW ENABLED_ROLES;
name | setting
---------------+----------
enabled roles | logadmin
(1 row)
只能为用户启用已向其显式授予的角色。在前面的示例中,对于 bob
,无法启用 logreader
或 logwriter
角色。它们只能通过启用 logadmin
来间接启用。
如果使用 WITH ADMIN OPTION
将一个或多个角色授予另一个角色,则被授予“较高”角色的用户将继承对下级角色的管理访问权限。
例如,您可以按如下方式,将以前授予的角色 logreader
和 logwriter
修改为 logadmin
:
=> GRANT logreader, logwriter TO logadmin WITH ADMIN OPTION;
NOTICE 4617: Role "logreader" was already granted to role "logadmin"
NOTICE 4617: Role "logwriter" was already granted to role "logadmin"
GRANT ROLE
现在,用户 bob
有权通过他的 logadmin
角色将其两个下级角色授予其他用户,在本例中是将角色 logreader
授予用户 Alice
:
=> \c - bob;
You are now connected as user "bob".
=> GRANT logreader TO Alice;
GRANT ROLE
=> \c - alice;
You are now connected as user "alice".
=> show available_roles;
name | setting
-----------------+-----------
available roles | logreader
(1 row)
因为在将 logadmin
角色授予 bob
时未包括 WITH ADMIN OPTION
,所以他不能将该角色授予 alice
:
=> \c - bob;
You are now connected as user "bob".
=> GRANT logadmin TO alice;
ROLLBACK 4925: The role "logadmin" cannot be granted to "alice"
作为具有
DBADMIN
或
PSEUDOSUPERUSER
角色的超级用户,您可以使用
CREATE ROLE
创建角色,使用
DROP ROLE
删除角色。
=> CREATE ROLE administrator;
CREATE ROLE
没有为新角色授予任何权限或角色。超级用户必须向新角色授予权限和访问权限。
如果您尝试删除授予用户或其他角色的角色,Vertica 将返回一则回退消息:
=> DROP ROLE administrator;
NOTICE: User Bob depends on Role administrator
ROLLBACK: DROP ROLE failed due to dependencies
DETAIL: Cannot drop Role administrator because other objects depend on it
HINT: Use DROP ROLE ... CASCADE to remove granted roles from the dependent users/roles
若要强制执行删除操作,请使用 CASCADE
限定 DROP ROL
E 语句:
=> DROP ROLE administrator CASCADE;
DROP ROLE
您可以使用 GRANT 语句为角色分配权限,就像您为用户分配权限一样。有关可以授予哪些权限的信息,请参阅数据库权限。
为角色授予权限会立即影响到活动的用户会话。为角色授予权限时,此权限便立即可供已启用该角色的所有用户使用。
以下示例将创建两个角色,并为这两个角色分配对同一个表的不同权限。
创建名为 applog
的表:
=> CREATE TABLE applog (id int, sourceID VARCHAR(32), data TIMESTAMP, event VARCHAR(256));
创建名为 logreader
和 logwriter
的角色:
=> CREATE ROLE logreader;
CREATE ROLE
=> CREATE ROLE logwriter;
CREATE ROLE
将 applog
的只读权限授予 logreader
,并将写入权限授予 logwriter
:
=> GRANT SELECT ON applog TO logreader;
GRANT PRIVILEGE
=> GRANT INSERT ON applog TO logwriter;
GRANT PRIVILEGE
使用 REVOKE 语句撤销角色的权限。撤销角色的权限会立即影响到处于活动状态的用户会话。当您撤销某个角色的权限时,通过该角色拥有此权限的用户将无法再使用此权限。
例如:
=> REVOKE INSERT ON applog FROM logwriter;
REVOKE PRIVILEGE
您可以使用 授权(角色) 将一个或多个角色分配给用户或其他角色:
GRANT role[,...] TO grantee[,...] [ WITH ADMIN OPTION ]
例如,您可以创建三个角色(appdata
、applogs
和 appadmin
)并为用户 bob
授予 appadmin
:
=> CREATE ROLE appdata;
CREATE ROLE
=> CREATE ROLE applogs;
CREATE ROLE
=> CREATE ROLE appadmin;
CREATE ROLE
=> GRANT appadmin TO bob;
GRANT ROLE
GRANT
可以将一个或多个角色分配给另一个角色。例如,以下 GRANT
语句将角色 appdata
和 applogs
授予角色 appadmin
:
=> GRANT appdata, applogs TO appadmin;
-- grant to other roles
GRANT ROLE
因为先前为用户 bob 分配了角色 appadmin
,所以他现在拥有向角色 appdata
和 applogs
授予的所有权限。
当您将一个角色授予另一个角色时,Vertica 会检查循环引用。在上一个示例中,已将角色 appdata
分配给 appadmin
角色。因此,随后将 appadmin
分配给 appdata
的尝试将失败,并返回以下警告:
=> GRANT appadmin TO appdata;
WARNING: Circular assignation of roles is not allowed
HINT: Cannot grant appadmin to appdata
GRANT ROLE
向用户授予角色后,必须启用该角色。您可以为当前会话启用角色:
=> SET ROLE appdata;
SET ROLE
还可以通过使用
ALTER USER...DEFAULT ROLE
修改用户的配置文件,在用户登录期间启用角色:
=> ALTER USER bob DEFAULT ROLE appdata;
ALTER USER
您可以通过使用 WITH ADMIN OPTION
选项限定 授权(角色) 语句,从而将对角色的管理访问权限委托给非超级用户。具有管理访问权限的用户可以管理其他用户对该角色的访问权限,包括向他们授予管理访问权限。在以下示例中,超级用户将具有管理权限的 appadmin
角色授予用户 bob
和 alice.
=> GRANT appadmin TO bob, alice WITH ADMIN OPTION;
GRANT ROLE
现在,两个用户都可以行使他们的管理权限来将 appadmin
角色授予其他用户或撤销该角色。例如,用户 bob
现在可以撤销用户 alice
的 appadmin
角色:
=> \connect - bob
You are now connected as user "bob".
=> REVOKE appadmin FROM alice;
REVOKE ROLE
以下示例创建名为 commenter
的角色并将该角色授予用户 bob
:
创建 comments
表:
=> CREATE TABLE comments (id INT, comment VARCHAR);
创建 commenter
角色:
=> CREATE ROLE commenter;
授予 commenter
对 comments
表的 INSERT 和 SELECT 权限:
=> GRANT INSERT, SELECT ON comments TO commenter;
向用户 bob
授予 commenter
角色。
=> GRANT commenter TO bob;
为了访问该角色及其关联权限,bob
为自己启用新授予的角色。
=> \c - bob
=> SET ROLE commenter;
因为 bob
对 comments
表具有 INSERT 和 SELECT 权限,所以他可以执行以下操作:
=> INSERT INTO comments VALUES (1, 'Hello World');
OUTPUT
--------
1
(1 row)
=> SELECT * FROM comments;
id | comment
----+-------------
1 | Hello World
(1 row)
=> COMMIT;
COMMIT
因为 bob
的角色缺少 DELETE 权限,所以以下语句会返回错误:
=> DELETE FROM comments WHERE id=1;
ERROR 4367: Permission denied for relation comments
REVOKE(角色)
可以从一个或多个被授权者(即用户或角色)撤销角色:
REVOKE [ ADMIN OPTION FOR ] role[,...] FROM grantee[,...] [ CASCADE ]
例如,以下语句从用户 bob
撤销 commenter
角色:
=> \c
You are now connected as user "dbadmin".
=> REVOKE commenter FROM bob;
REVOKE ROLE
您可以使用 ADMIN OPTION FOR
子句限定
REVOKE(角色)
。该子句从被授予者撤销将指定角色授予其他用户或角色的权限(由以前的 GRANT (Role)...WITH ADMIN OPTION
语句授予)。被授予者的当前角色不受影响。
以下示例撤销用户 Alice 授予和撤销 commenter
角色的权限:
=> \c
You are now connected as user "dbadmin".
=> REVOKE ADMIN OPTION FOR commenter FROM alice;
REVOKE ROLE
当您在会话中启用角色时,将获得分配给该角色的所有权限。您可以同时启用多个角色,从而获得这些角色的所有权限,以及已经直接授予您的任何权限。
默认情况下,对于用户,仅自动启用预定义角色。否则,在启动会话时,您必须使用 Vertica 函数
SET ROLE
显式启用分配的角色。
例如,dbadmin 创建 logreader
角色并将其分配给用户 alice
:
=> \c
You are now connected as user "dbadmin".
=> CREATE ROLE logreader;
CREATE ROLE
=> GRANT SELECT ON TABLE applog to logreader;
GRANT PRIVILEGE
=> GRANT logreader TO alice;
GRANT ROLE
用户 alice
必须启用新角色才能查看 applog
表:
=> \c - alice
You are now connected as user "alice".
=> SELECT * FROM applog;
ERROR: permission denied for relation applog
=> SET ROLE logreader;
SET
=> SELECT * FROM applog;
id | sourceID | data | event
----+----------+----------------------------+----------------------------------------------
1 | Loader | 2011-03-31 11:00:38.494226 | Error: Failed to open source file
2 | Reporter | 2011-03-31 11:00:38.494226 | Warning: Low disk space on volume /scratch-a
(2 rows)
您可以使用 SET ROLE ALL
启用对您的用户帐户可用的所有角色:
=> SET ROLE ALL;
SET
=> SHOW ENABLED_ROLES;
name | setting
---------------+------------------------------
enabled roles | logreader, logwriter
(1 row)
用户可以使用
SET ROLE NONE
禁用所有角色。此语句禁用当前会话的除预定义角色以外的所有其他角色:
=> SET ROLE NONE;
=> SHOW ENABLED_ROLES;
name | setting
---------------+---------
enabled roles |
(1 row)
默认情况下,会为新用户分配 PUBLIC 角色,在新会话开始时会自动启用此角色。通常,会创建其他角色并将它们分配给用户,但不会自动启用这些角色。相反,用户必须在每个新会话中使用
SET ROLE
显式启用为他们分配的角色。
您可以通过两种方式自动为用户启用角色:
在登录时为单个用户启用角色
在登录时为所有用户启用所有角色
为用户分配角色后,您可以通过使用
ALTER USER...DEFAULT ROLE
修改每个用户的配置文件来为该用户设置一个或多个默认角色。用户默认角色在用户会话开始时自动启用。如果用户通常依赖这些角色的权限来执行日常任务,您应该考虑为用户设置默认角色。
ALTER USER...DEFAULT ROLE
覆盖以前的默认角色设置。
以下示例显示了如何将 regional_manager
设置为用户 LilyCP
的默认角色:
=> \c
You are now connected as user "dbadmin".
=> GRANT regional_manager TO LilyCP;
GRANT ROLE
=> ALTER USER LilyCP DEFAULT ROLE regional_manager;
ALTER USER
=> \c - LilyCP
You are now connected as user "LilyCP".
=> SHOW ENABLED_ROLES;
name | setting
---------------+------------------
enabled roles | regional_manager
(1 row)
配置参数 EnableAllRolesOnLogin
指定是否在登录时为所有数据库用户启用所有角色。默认情况下,此参数设置为 0。如果设置为 1,Vertica 会在所有用户登录数据库时启用他们的角色。
您可以使用
ALTER USER...DEFAULT ROLE NONE
清除为用户分配的所有默认角色。例如:
=> ALTER USER fred DEFAULT ROLE NONE;
ALTER USER
=> SELECT user_name, default_roles, all_roles FROM users WHERE user_name = 'fred';
user_name | default_roles | all_roles
-----------+---------------+-----------
fred | | logreader
(1 row)
您可以通过三种方式获取有关角色的信息:
通过查询系统表 ROLES、USERS 和 GRANTS,分别获取有关角色、分配给角色的用户以及授予这些用户和角色的权限的全面信息。
HAS_ROLE
可获取该信息。
函数
HAS_ROLE
检查是否已将 Vertica 角色授予指定的用户或角色。非超级用户可以使用此函数检查自己的角色成员资格。超级用户可以使用它来确定其他用户和角色的角色分配。您还可以使用管理控制台检查角色分配。
在以下示例中,dbadmin
用户检查是否为用户 MikeL
分配了 admnistrator
角色:
=> \c
You are now connected as user "dbadmin".
=> SELECT HAS_ROLE('MikeL', 'administrator');
HAS_ROLE
----------
t
(1 row)
用户 MikeL
检查其是否具有 regional_manager
角色:
=> \c - MikeL
You are now connected as user "MikeL".
=> SELECT HAS_ROLE('regional_manager');
HAS_ROLE
----------
f
(1 row)
dbadmin 将 regional_manager
角色授予 administrator
角色。再次检查时,MikeL
会验证他现在具有 regional_manager
角色:
dbadmin=> \c
You are now connected as user "dbadmin".
dbadmin=> GRANT regional_manager to administrator;
GRANT ROLE
dbadmin=> \c - MikeL
You are now connected as user "MikeL".
dbadmin=> SELECT HAS_ROLE('regional_manager');
HAS_ROLE
----------
t
(1 row)
SHOW AVAILABLE ROLES
列出向您授予的所有角色:
=> SHOW AVAILABLE ROLES;
name | setting
-----------------+-----------------------------
available roles | logreader, logwriter
(1 row)
SHOW ENABLED ROLES
列出在会话中启用的角色:
=> SHOW ENABLED ROLES;
name | setting
---------------+----------
enabled roles | logreader
(1 row)
您可以单独或以联接方式查询表 ROLES、USERS 和 GRANTS,以获取有关用户角色、分配给这些角色的用户以及显式授予用户和通过角色隐式授予的权限的详细信息。
针对 ROLES 执行以下查询将返回用户可以访问的所有角色的名称,以及授予(分配)这些角色的角色。附加到角色的星号 (*) 表示用户可以将该角色授予其他用户:
=> SELECT * FROM roles;
name | assigned_roles
-----------------+----------------
public |
dbduser |
dbadmin | dbduser*
pseudosuperuser | dbadmin*
logreader |
logwriter |
logadmin | logreader, logwriter
(7 rows)
针对系统表 USERS 执行以下查询将返回所有具备 DBADMIN 角色的用户。附加到角色的星号 (*) 表示用户可以将该角色授予其他用户:
=> SELECT user_name, is_super_user, default_roles, all_roles FROM v_catalog.users WHERE all_roles ILIKE '%dbadmin%';
user_name | is_super_user | default_roles | all_roles
-----------+---------------+--------------------------------------+--------------------------------------
dbadmin | t | dbduser*, dbadmin*, pseudosuperuser* | dbduser*, dbadmin*, pseudosuperuser*
u1 | f | | dbadmin*
u2 | f | | dbadmin
(3 rows)
针对系统表 GRANTS 执行以下查询将返回向用户 Jane 或角色 R1 授予的权限。附加到权限的星号 (*) 表示用户可以将该权限授予其他用户:
=> SELECT grantor,privileges_description,object_name,object_type,grantee FROM grants WHERE grantee='Jane' OR grantee='R1';
grantor | privileges_description | object_name | object_type | grantee
--------+------------------------+-------------+--------------+-----------
dbadmin | USAGE | general | RESOURCEPOOL | Jane
dbadmin | | R1 | ROLE | Jane
dbadmin | USAGE* | s1 | SCHEMA | Jane
dbadmin | USAGE, CREATE* | s1 | SCHEMA | R1
(4 rows)
创建数据库对象(例如架构、表或视图)时,该对象的所有权将分配给创建它的用户。默认情况下,只有对象的所有者和具有超级用户权限的用户(如数据库管理员)才对新对象具有权限。只有这些用户(以及他们为其显式授权的其他用户)才能将对象权限授予其他用户
权限分别由 GRANT 和 REVOKE 语句授予和撤销。可以为给定对象授予的权限与对象类型相关。例如,表权限包括 SELECT、INSERT 和 UPDATE,而库和资源池权限仅包括 USAGE 权限。有关对象权限的汇总,请参阅数据库对象权限。
由于数据库对象的权限可能来自多个不同的来源(如显式授权、角色和继承),因此权限可能难以监控。使用 GET_PRIVILEGES_DESCRIPTION 元函数检查当前用户从指定数据库对象的所有源获得的有效权限。
所有用户都对他们拥有的对象拥有隐式权限。在创建对象时,它的所有者会自动被授予与对象类型相关的所有权限(请参阅数据库对象权限)。无论对象类型如何,以下权限都与所有权密不可分并且不能被撤销,即使是所有者也不能撤销:
将所有对象权限授予其他用户并撤销它们
ALTER(如适用)和 DROP
扩展以下权限:将对象权限授予其他用户和撤销该权限
对象所有者可以撤销他们自己的所有非隐式或普通权限。例如,在创建表时,它的所有者会自动被授予所有隐式和普通权限:
如果用户 Joan
创建表 t1
,她可以撤销自己的普通权限 UPDATE 和 INSERT,这实际上会将该表设为只读:
=> \c - Joan
You are now connected as user "Joan".
=> CREATE TABLE t1 (a int);
CREATE TABLE
=> INSERT INTO t1 VALUES (1);
OUTPUT
--------
1
(1 row)
=> COMMIT;
COMMIT
=> REVOKE UPDATE, INSERT ON TABLE t1 FROM Joan;
REVOKE PRIVILEGE
=> INSERT INTO t1 VALUES (3);
ERROR 4367: Permission denied for relation t1
=> SELECT * FROM t1;
a
---
1
(1 row)
Joan 随后可以还原自己的 UPDATE 和 INSERT 权限:
=> GRANT UPDATE, INSERT on TABLE t1 TO Joan;
GRANT PRIVILEGE
dbadmin=> INSERT INTO t1 VALUES (3);
OUTPUT
--------
1
(1 row)
=> COMMIT;
COMMIT
dbadmin=> SELECT * FROM t1;
a
---
1
3
(2 rows)
您可以在三个级别管理权限继承:
数据库
架构
表和视图
默认情况下,继承权限在数据库级别启用,在架构级别禁用。如果在两个级别都启用了权限继承,新表和视图在创建时会自动继承这些权限。您还可以排除特定表和视图的继承。
默认情况下,通过配置参数 disableinheritedprivileges
在数据库级别启用继承权限。要启用继承的权限:
=> ALTER DATABASE [database name] SET disableinheritedprivileges = 0;
要禁用继承的权限:
=> ALTER DATABASE [database name] SET disableinheritedprivileges = 1;
使用 ALTER SCHEMA 启用继承权限DEFAULT INCLUDE PRIVILEGES 仅影响新创建的表和视图。
此设置不会影响已存在的表和视图。
默认情况下,在架构级别禁用继承的权限。如果为数据库启用了继承的权限,您可以使用 CREATE SCHEMA 和 ALTER SCHEMA 允许数据库的表和视图继承架构权限。除非显式排除,否则在架构上授予的权限将自动由其中的所有新表和视图继承。
有关哪些表和视图从哪些架构继承权限的信息,请参阅 INHERITING_OBJECTS。
有关每个表或视图继承哪些权限的信息,请参阅 INHERITED_PRIVILEGES。
如果针对数据库禁用继承的权限,则对其架构启用继承不起作用。尝试启用可能会返回以下消息:
Inherited privileges are globally disabled; schema parameter is set but has no effect.
启用架构权限继承对现有的表和视图不起作用。您必须使用 ALTER TABLE 和 ALTER VIEW 针对现有的表和视图显式设置架构继承。您还可以分别使用 CREATE TABLE/ALTER TABLE 和 CREATE VIEW/ALTER VIEW 显式排除表和视图继承架构权限。
您可以在架构创建期间使用以下语句启用架构权限继承:
=> CREATE SCHEMA s1 DEFAULT INCLUDE PRIVILEGES;
如果架构已经存在,您可以使用 ALTER SCHEMA 让所有新创建的表和视图继承架构的权限。在此语句之前在架构上创建的表和视图不受影响:
=> ALTER SCHEMA s1 DEFAULT INCLUDE PRIVILEGES;
在架构上启用继承的权限后,可以使用 GRANT(架构) 将架构权限授予用户和角色:
=> GRANT USAGE, CREATE, SELECT, INSERT ON SCHEMA S1 TO PUBLIC;
GRANT PRIVILEGE
使用 ALTER SCHEMA 启用继承权限DEFAULT INCLUDE PRIVILEGES 仅影响新创建的表和视图。
此设置不会影响已存在的表和视图。
如果为数据库和架构启用了继承的权限,则授予架构的权限将自动授予其中的所有新表和视图。您还可以显式排除表和视图继承架构权限。
有关哪些表和视图从哪些架构继承权限的信息,请参阅 INHERITING_OBJECTS。
有关每个表或视图继承哪些权限的信息,请参阅 INHERITED_PRIVILEGES。
CREATE TABLE/ALTER TABLE 和 CREATE VIEW/ALTER VIEW 可以允许表和视图从其父架构继承权限。例如,以下语句在架构 s1 上启用继承,因此新表 s1.t1 和视图 s1.myview 会自动继承在该架构上设置的权限(如果适用):
=> CREATE SCHEMA s1 DEFAULT INCLUDE PRIVILEGES;
CREATE SCHEMA
=> GRANT USAGE, CREATE, SELECT, INSERT ON SCHEMA S1 TO PUBLIC;
GRANT PRIVILEGE
=> CREATE TABLE s1.t1 ( ID int, f_name varchar(16), l_name(24));
WARNING 6978: Table "t1" will include privileges from schema "s1"
CREATE TABLE
=> CREATE VIEW s1.myview AS SELECT ID, l_name FROM s1.t1
WARNING 6978: View "myview" will include privileges from schema "s1"
CREATE VIEW
如果架构已经存在,您可以使用 ALTER SCHEMA 让所有新创建的表和视图继承架构的权限。但是,在此语句之前在架构上创建的表和视图不受影响:
=> CREATE SCHEMA s2;
CREATE SCHEMA
=> CREATE TABLE s2.t22 ( a int );
CREATE TABLE
...
=> ALTER SCHEMA S2 DEFAULT INCLUDE PRIVILEGES;
ALTER SCHEMA
在此例中,在架构 s2 已经包含表 s2.t22 之后,在该架构上启用继承的权限。要在此表和其他现有表和视图上设置继承,必须使用 ALTER TABLE 和 ALTER VIEW 对它们显式设置架构继承:
=> ALTER TABLE s2.t22 INCLUDE SCHEMA PRIVILEGES;
您可以使用 CREATE TABLE/ALTER TABLE 和 CREATE VIEW/ALTER VIEW 禁止表和视图继承架构权限。
以下示例显示了如何创建不继承架构权限的表:
=> CREATE TABLE s1.t1 ( x int) EXCLUDE SCHEMA PRIVILEGES;
您可以修改现有表,使其不继承架构权限:
=> ALTER TABLE s1.t1 EXCLUDE SCHEMA PRIVILEGES;
以下步骤显示了用户 Joe
如何针对给定架构启用权限继承,以便其他用户可以访问该架构中的表。
Joe
创建架构 schema1
,并在其中创建表 table1
:
=>\c - Joe
You are now connected as user Joe
=> CREATE SCHEMA schema1;
CRDEATE SCHEMA
=> CREATE TABLE schema1.table1 (id int);
CREATE TABLE
Joe
将对 schema1
的 USAGE 和 CREATE 权限授予 Myra
:
=> GRANT USAGE, CREATE ON SCHEMA schema1 to Myra;
GRANT PRIVILEGE
Myra
查询 schema1.table1
,但查询失败:
=>\c - Myra
You are now connected as user Myra
=> SELECT * FROM schema1.table1;
ERROR 4367: Permission denied for relation table1
Joe
授予 Myra
对 schema1
的 SELECT ON SCHEMA
权限:
=>\c - Joe
You are now connected as user Joe
=> GRANT SELECT ON SCHEMA schema1 to Myra;
GRANT PRIVILEGE
Joe
使用 ALTER TABLE
包含 table1
的 SCHEMA 权限:
=> ALTER TABLE schema1.table1 INCLUDE SCHEMA PRIVILEGES;
ALTER TABLE
Myra
的查询现在成功:
=>\c - Myra
You are now connected as user Myra
=> SELECT * FROM schema1.table1;
id
---
(0 rows)
Joe
修改 schema1
以包含权限,以便在 schema1
中创建的所有表都继承架构权限:
=>\c - Joe
You are now connected as user Joe
=> ALTER SCHEMA schema1 DEFAULT INCLUDE PRIVILEGES;
ALTER SCHEMA
=> CREATE TABLE schema1.table2 (id int);
CREATE TABLE
启用继承的权限后,Myra
可以查询 table2
,而 Joe
不必显式授予对表的权限:
=>\c - Myra
You are now connected as user Myra
=> SELECT * FROM schema1.table2;
id
---
(0 rows)
为了向所有用户设置最低级别的权限,Vertica 具有特殊的 PUBLIC 角色,会向每个用户自动授予此角色。此角色会自动启用,但数据库管理员或 超级用户也可以使用 GRANT 语句单独向用户授予更高的权限。
管理控制台 (MC) 的权限通过角色进行管理,这些角色确定了用户对 MC 和 MC 管理的 Vertica 数据库(通过 MC 界面)的访问权限。MC 权限不会更改或覆盖 Vertica 权限或角色。有关详细信息,请参阅用户、角色和权限。
本主题列出了 Vertica 中的数据库对象所需的权限。
除非另有说明,否则 超级用户可以执行下表中显示的所有操作。对象所有者始终可以对自己的对象执行操作。
某些操作(如设置其他用户的默认资源池或选择视图)取决于其他用户的有效权限。如果其他用户通过角色获得这些先决权限,则他必须具有默认角色,操作才能成功。
有关更改用户默认角色的详细信息,请参阅自动启用角色。
PUBLIC 架构存在于任何新创建的 Vertica 数据库中。必须授予新创建的用户对此架构的访问权限:
=> GRANT USAGE ON SCHEMA public TO user;
数据库超级用户还必须为新用户显式授予 CREATE 权限,并为他们授予各个对象权限,以便新用户可以在 PUBLIC 架构中创建或查找对象。
下表使用以下缩写:
UDF = 分级
UDT = 转换
UDAnF= 分析
UDAF = 聚合
您可以使用一个或一组 vsql \d 元命令和SQL 系统表来查看您有权查看的对象。
使用 \dn 查看架构名称和所有者。
使用 \dn 查看数据库中的所有表,以及系统表 V_CATALOG.TABLES
使用 \dn 查看显示架构、投影名称、所有者和节点的投影,以及系统表 V_CATALOG.PROJECTIONS
对于 Vertica 数据库中大多数的用户可见对象(如表和模型),可以显式授予权限。对于某些对象(如投影),权限是从其他对象隐式派生的。
下表概述了可为 Vertica 数据库对象显式授予的权限:
超级用户可以无限制地访问所有非加密数据库元数据。对于非超级用户,对特定对象的元数据的访问权限取决于他们对这些对象的权限:
用来存储表数据的投影没有与其直接关联的所有者或权限。相反,创建、访问或更改投影的权限派生自针对该投影的锚表和相应架构设置的权限。
除非拥有所有权,否则超级用户仅对密钥、证书和 TLS 配置具有隐式 DROP 权限。这让超级用户能够在他们各自的系统表(CRYPTOGRAPHIC_KEYS、CERTIFICATES 和 TLS_CONFIGURATIONS)中查看这些对象是否存在并删除它们,但不允许他们查看密钥或证书文本。
有关授予额外权限的详细信息,请参阅 GRANT(密钥)和 GRANT(TLS 配置)。
Vertica 支持通过 GRANT 和 REVOKE 语句(例如,GRANT(架构)和 REVOKE(架构)、GRANT(表)和 REVOKE(表) 等等)来控制用户对数据库对象的访问。通常,超级用户会在创建数据库后不久创建用户和角色,然后使用 GRANT 语句为所创建的用户和角色分配权限。
在适用的情况下,GRANT 语句需要对象架构的 USAGE 权限。以下用户可以授予和撤销权限:
超级用户:所有数据库对象(包括数据库本身)的所有权限
非超级用户:他们拥有的对象的所有权限
包括 WITH GRANT OPTION 的权限的被授予者:对该对象的相同权限
在以下示例中,dbadmin(具有超级用户权限)创建用户 Carol
。随后的 GRANT 语句授予 Carol
架构和表权限:
对架构的 CREATE 和 USAGE 权限 PUBLIC
对表 public.applog
的 SELECT、INSERT 和 UPDATE 权限。此 GRANT 语句还包括 WITH GRANT OPTION
。这使得 Carol
可以将此表上的相同权限授予其他用户 — 在本例中,将 SELECT 权限授予用户 Tom
:
=> CREATE USER Carol;
CREATE USER
=> GRANT CREATE, USAGE ON SCHEMA PUBLIC to Carol;
GRANT PRIVILEGE
=> GRANT SELECT, INSERT, UPDATE ON TABLE public.applog TO Carol WITH GRANT OPTION;
GRANT PRIVILEGE
=> GRANT SELECT ON TABLE public.applog TO Tom;
GRANT PRIVILEGE
Vertica 超级用户是在安装时自动创建的数据库用户(默认情况下,名为 dbadmin
)。Vertica 超级用户对数据库用户、权限和角色拥有完整且不可撤销的授权。
超级用户可以更改任何用户和角色的权限,并覆盖具有 PSEUDOSUPERUSER 角色的用户所授予的任何权限。他们还可以授予和撤销用户拥有的任何对象的权限,并重新分配对象所有权。
对于大多数编录对象,超级用户拥有所有可能的权限。但是,对于密钥、证书和 TLS 配置,超级用户在默认情况下只能获得 DROP 权限,并且必须由其所有者授予其他权限。有关详细信息,请参阅 GRANT(密钥)和 GRANT(TLS 配置)。
超级用户可以看到所存在的全部密钥、证书和 TLS 配置,但是,除非向他们授予 USAGE 权限,否则他们看不到密钥或证书的文本。
通常情况下,架构所有者为创建该架构的用户。默认情况下,架构所有者有权在架构内创建对象。所有者还可以更改架构:重新分配所有权、重命名以及启用或禁用架构权限继承。
架构所有权不一定授予所有者对该架构中对象的访问权限。对象访问权限取决于向他们授予的权限。
所有其他用户和角色必须由所有者或超级用户显式授予对架构的访问权限。
数据库以及其中的每个对象都具有所有者。对象所有者通常是创建该对象的人员,但是超级用户可以更改对象(如表和序列)的所有权。
对象所有者必须具有合适的架构权限才能访问、更改、重命名、移动或删除其拥有的任何对象,而不需要任何额外的权限。
对象所有者还可以:
将自己所拥有的对象的权限授予其他用户
WITH GRANT OPTION 子句指定用户可以向其他用户授予权限。例如,如果用户 Bob 创建一个表,则 Bob 可以将该表的权限授予用户 Ted、Alice 等等。
将权限授予 **角色**
被授予角色的用户会获得权限。
如授予和撤销权限中所述,特定用户可使用带有或不带有可选 WITH GRANT OPTION 的 GRANT 语句授予权限,WITH GRANT OPTION 子句允许用户向其他用户授予相同的权限。
超级用户可向其他用户授予对所有对象类型的权限。
超级用户或对象所有者可向 角色授予权限。然后,被授予角色的用户会获得相应权限。
对象所有者可使用可选的 WITH GRANT OPTION 子句向其他用户授予对于对象的权限。
用户需要具有对架构的 USAGE 权限以及对于对象的相应权限。
当用户授予一个显式的权限列表时,例如 GRANT INSERT, DELETE, REFERENCES ON applog TO Bob
:
只有成功授予了所有角色,GRANT 语句才会成功执行。如果任一授予操作失败,则整个语句将回退。
如果用户没有所列权限的授予选项,Vertica 将返回 ERROR。
当用户授予 ALL 权限(例如 GRANT ALL ON applog TO Bob
)时,语句始终会成功执行。Vertica 会授予授予者具有 WITH GRANT OPTION 的所有权限,而略过没有可选 WITH GRANT OPTION 的权限。
例如,如果用户 Bob 删除了具有可选授予选项的对于表 applog 的权限,则仅会向 Bob 授予 DELETE 权限,语句会成功执行:
=> GRANT DELETE ON applog TO Bob WITH GRANT OPTION;GRANT PRIVILEGE
有关详细信息,请参阅 GRANT 语句。
下面的非超级用户可以撤销对象的权限:
对象所有者
对象权限的授予者
用户还必须具有对对象架构的 USAGE 权限。
例如,针对系统表 V_CATALOG.GRANTS
执行以下查询将显示用户 u1
、u2
和 u3
对架构 s1
和表 s1.t1
具有以下权限:
=> SELECT object_type, object_name, grantee, grantor, privileges_description FROM v_catalog.grants
WHERE object_name IN ('s1', 't1') AND grantee IN ('u1', 'u2', 'u3');
object_type | object_name | grantee | grantor | privileges_description
-------------+-------------+---------+---------+---------------------------
SCHEMA | s1 | u1 | dbadmin | USAGE, CREATE
SCHEMA | s1 | u2 | dbadmin | USAGE, CREATE
SCHEMA | s1 | u3 | dbadmin | USAGE
TABLE | t1 | u1 | dbadmin | INSERT*, SELECT*, UPDATE*
TABLE | t1 | u2 | u1 | INSERT*, SELECT*, UPDATE*
TABLE | t1 | u3 | u2 | SELECT*
(6 rows)
privileges_description
下权限上的星号 (*) 表示被授予者可以将这些权限授予其他用户。
在以下语句中,u2
撤销它在 s1.t1
上授予 u3
的 SELECT 权限。u3
随后尝试查询此表时返回错误:
=> \c - u2
You are now connected as user "u2".
=> REVOKE SELECT ON s1.t1 FROM u3;
REVOKE PRIVILEGE
=> \c - u3
You are now connected as user "u2".
=> SELECT * FROM s1.t1;
ERROR 4367: Permission denied for relation t1
如果您撤销用户对某个对象的权限,则该用户不能再将这些相同权限授予其他用户。如果该用户先前已将撤销的权限授予其他用户,则 REVOKE
语句还必须包含 CASCADE
选项才能撤销这些其他用户的权限;否则,它会返回错误。
例如,用户 u2
可以授予 SELECT、INSERT 和 UPDATE 权限,并将这些权限授予用户 u4
:
=> \c - u2
You are now connected as user "u2".
=> GRANT SELECT, INSERT, UPDATE on TABLE s1.t1 to u4;
GRANT PRIVILEGE
如果您通过查询 V_CATALOG.GRANTS
来查看是否拥有表 s1.t1
的权限,它会返回以下结果集:
=> \ c
You are now connected as user "dbadmin".
=> SELECT object_type, object_name, grantee, grantor, privileges_description FROM v_catalog.grants
WHERE object_name IN ('t1') ORDER BY grantee;
object_type | object_name | grantee | grantor | privileges_description
-------------+-------------+---------+---------+------------------------------------------------------------
TABLE | t1 | dbadmin | dbadmin | INSERT*, SELECT*, UPDATE*, DELETE*, REFERENCES*, TRUNCATE*
TABLE | t1 | u1 | dbadmin | INSERT*, SELECT*, UPDATE*
TABLE | t1 | u2 | u1 | INSERT*, SELECT*, UPDATE*
TABLE | t1 | u4 | u2 | INSERT, SELECT, UPDATE
(3 rows)
现在,如果用户 u1
想要撤销用户 u2
的 UPDATE 权限,则撤销操作必须级联到用户 u4
(该用户也拥有 u2
授予的 UPDATE 权限);否则,REVOKE
语句返回错误:
=> \c - u1
=> REVOKE update ON TABLE s1.t1 FROM u2;
ROLLBACK 3052: Dependent privileges exist
HINT: Use CASCADE to revoke them too
=> REVOKE update ON TABLE s1.t1 FROM u2 CASCADE;
REVOKE PRIVILEGE
=> \c
You are now connected as user "dbadmin".
=> SELECT object_type, object_name, grantee, grantor, privileges_description FROM v_catalog.grants
WHERE object_name IN ('t1') ORDER BY grantee;
object_type | object_name | grantee | grantor | privileges_description
-------------+-------------+---------+---------+------------------------------------------------------------
TABLE | t1 | dbadmin | dbadmin | INSERT*, SELECT*, UPDATE*, DELETE*, REFERENCES*, TRUNCATE*
TABLE | t1 | u1 | dbadmin | INSERT*, SELECT*, UPDATE*
TABLE | t1 | u2 | u1 | INSERT*, SELECT*
TABLE | t1 | u4 | u2 | INSERT, SELECT
(4 rows)
您还可以撤销用户的授予者权限而不撤销这些权限。例如,用户 u1
可以阻止用户 u2
将 INSERT 权限授予其他用户,但允许用户 u2
保留该权限:
=> \c - u1
You are now connected as user "u1".
=> REVOKE GRANT OPTION FOR INSERT ON TABLE s1.t1 FROM U2 CASCADE;
REVOKE PRIVILEGE
u2
先前授予用户 u4
对表 s1.t1
的 INSERT 权限。当您撤销 u2
授予此权限的能力时,必须从其任何被授予者(在本例中为用户 u4
)中移除该权限。
您可以通过查询 V_CATALOG.GRANTS
表来查看是否拥有 s1.t1
表的权限,从而确认撤销操作的结果:
=> \c
You are now connected as user "dbadmin".
=> SELECT object_type, object_name, grantee, grantor, privileges_description FROM v_catalog.grants
WHERE object_name IN ('t1') ORDER BY grantee;
object_type | object_name | grantee | grantor | privileges_description
-------------+-------------+---------+---------+------------------------------------------------------------
TABLE | t1 | dbadmin | dbadmin | INSERT*, SELECT*, UPDATE*, DELETE*, REFERENCES*, TRUNCATE*
TABLE | t1 | u1 | dbadmin | INSERT*, SELECT*, UPDATE*
TABLE | t1 | u2 | u1 | INSERT, SELECT*
TABLE | t1 | u4 | u2 | SELECT
(4 rows)
查询结果显示:
用户 u2
保留对表的 INSERT 权限,但不能再将 INSERT 权限授予其他用户(没有星号)。
撤销操作向下级联到被授予者 u4
,该用户现在失去 INSERT 权限。
撤销对于对象的权限可能会在整个组织内产生级联影响。如果为用户撤销了授予选项,则此用户授予其他用户的权限也会被撤销。
如果权限是由多个授予者授予用户或角色的,则要为被授予者完全撤销此权限,每个最初授予者都必须撤销该权限。唯一例外是超级用户可以撤销对象所有者授予的权限,反之亦然。
在以下示例中,对表 t1 的 SELECT 权限是通过一个从超级用户到 User3 的用户链授予的。
超级用户为 User1 授予对架构 s1 的 CREATE 权限:
=> \c - dbadmin
You are now connected as user "dbadmin".
=> CREATE USER User1;
CREATE USER
=> CREATE USER User2;
CREATE USER
=> CREATE USER User3;
CREATE USER
=> CREATE SCHEMA s1;
CREATE SCHEMA
=> GRANT USAGE on SCHEMA s1 TO User1, User2, User3;
GRANT PRIVILEGE
=> CREATE ROLE reviewer;
CREATE ROLE
=> GRANT CREATE ON SCHEMA s1 TO User1;
GRANT PRIVILEGE
User1 在架构 s1 中创建新表 t1,然后为 User2 授予对 s1.t1 的 SELECT WITH GRANT OPTION 权限:
=> \c - User1
You are now connected as user "User1".
=> CREATE TABLE s1.t1(id int, sourceID VARCHAR(8));
CREATE TABLE
=> GRANT SELECT on s1.t1 to User2 WITH GRANT OPTION;
GRANT PRIVILEGE
User2 为 User3 授予对 s1.t1 的 SELECT WITH GRANT OPTION 权限。
=> \c - User2
You are now connected as user "User2".
=> GRANT SELECT on s1.t1 to User3 WITH GRANT OPTION;
GRANT PRIVILEGE
User3 为查看者角色授予对 s1.t1 的 SELECT 权限:
=> \c - User3
You are now connected as user "User3".
=> GRANT SELECT on s1.t1 to reviewer;
GRANT PRIVILEGE
用户不能撤销处于链上游的权限。例如,User2 没有为 User1 授予权限,因此当 User1 运行以下 REVOKE 命令时,Vertica 会回退命令:
=> \c - User2
You are now connected as user "User2".
=> REVOKE CREATE ON SCHEMA s1 FROM User1;
ROLLBACK 0: "CREATE" privilege(s) for schema "s1" could not be revoked from "User1"
用户可以间接地为通过级联链接受权限的用户撤销权限,如上例所示。这里,用户可以使用 CASCADE 选项为链“下游”的所有用户撤销权限。超级用户或 User1 可以使用 CASCADE 选项为所有用户撤销对表 s1.t1 的 SELECT 权限。例如,超级用户或 User1 可以执行以下语句为链中的所有用户和角色撤销 SELECT 权限:
=> \c - User1
You are now connected as user "User1".
=> REVOKE SELECT ON s1.t1 FROM User2 CASCADE;
REVOKE PRIVILEGE
当超级用户或 User1 执行上述语句时,会为 User2、User3 和查看者角色撤销对表 s1.t1 的 SELECT 权限。同时也会为 User2 和 User3 撤销 GRANT 权限,超级用户可以通过查询 V_CATALOG.GRANTS 系统表进行验证。
=> SELECT * FROM grants WHERE object_name = 's1' AND grantee ILIKE 'User%';
grantor | privileges_description | object_schema | object_name | grantee
---------+------------------------+---------------+-------------+---------
dbadmin | USAGE | | s1 | User1
dbadmin | USAGE | | s1 | User2
dbadmin | USAGE | | s1 | User3
(3 rows)
超级用户或对象所有者可以使用其中一个 ALTER 语句修改权限,如更改序列所有者或表所有者。重新分配给新所有者时,不会将授权从原始所有者转移到新所有者;由原始所有者所执行的授权会被删除。
您可以通过查询以下系统表来查看有关权限、授予者、被授予者和对象的信息:
附加到权限后面的星号 (*) 表示用户可以将该权限授予其他用户。
您还可以使用 GET_PRIVILEGES_DESCRIPTION 元函数查看指定数据库对象的有效权限。
若要查看显式授予的对象权限,请查询 GRANTS 表。
以下查询返回 myschema 架构的显式权限。
=> SELECT grantee, privileges_description FROM grants WHERE object_name='myschema';
grantee | privileges_description
---------+------------------------
Bob | USAGE, CREATE
Alice | CREATE
(2 rows)
若要查看哪些表和视图从哪些架构继承权限,请查询 INHERITING_OBJECTS 表。
以下查询返回从其父架构(客户)继承权限的表和视图。
=> SELECT * FROM inheriting_objects WHERE object_schema='customers';
object_id | schema_id | object_schema | object_name | object_type
-------------------+-------------------+---------------+---------------+-------------
45035996273980908 | 45035996273980902 | customers | cust_info | table
45035996273980984 | 45035996273980902 | customers | shipping_info | table
45035996273980980 | 45035996273980902 | customers | cust_set | view
(3 rows)
若要查看表和视图继承的特定权限及其关联的授予语句的信息,请查询 INHERITED_PRIVILEGES 表。
以下查询返回表和视图从其父架构(客户)继承的权限。
=> SELECT object_schema,object_name,object_type,privileges_description,principal,grantor FROM inherited_privileges WHERE object_schema='customers';
object_schema | object_name | object_type | privileges_description | principal | grantor
---------------+---------------+-------------+---------------------------------------------------------------------------+-----------+---------
customers | cust_info | Table | INSERT*, SELECT*, UPDATE*, DELETE*, ALTER*, REFERENCES*, DROP*, TRUNCATE* | dbadmin | dbadmin
customers | shipping_info | Table | INSERT*, SELECT*, UPDATE*, DELETE*, ALTER*, REFERENCES*, DROP*, TRUNCATE* | dbadmin | dbadmin
customers | cust_set | View | SELECT*, ALTER*, DROP* | dbadmin | dbadmin
customers | cust_info | Table | SELECT | Val | dbadmin
customers | shipping_info | Table | SELECT | Val | dbadmin
customers | cust_set | View | SELECT | Val | dbadmin
customers | cust_info | Table | INSERT | Pooja | dbadmin
customers | shipping_info | Table | INSERT | Pooja | dbadmin
(8 rows)
若要查看当前用户对指定数据库对象的有效权限,请使用 GET_PRIVILEGES_DESCRIPTION 元函数。
在以下示例中,用户 Glenn 设置了 REPORTER 角色,并希望检查他对架构 s1
和表 s1.articles
的有效权限。
表 s1.articles
从其架构 (s1
) 继承权限。
REPORTER 角色具有以下权限:
对架构的 SELECT 权限 s1
对表的 INSERT WITH GRANT OPTION 权限 s1.articles
用户 Glenn 具有以下权限:
对架构 s1
的 UPDATE 和 USAGE 权限。
对表 s1.articles
的 DELETE 权限。
GET_PRIVILEGES_DESCRIPTION 返回 Glenn 对架构 s1
的以下有效权限:
=> SELECT GET_PRIVILEGES_DESCRIPTION('schema', 's1');
GET_PRIVILEGES_DESCRIPTION
--------------------------------
SELECT, UPDATE, USAGE
(1 row)
GET_PRIVILEGES_DESCRIPTION 返回 Glenn 对表 s1.articles
的以下有效权限:
=> SELECT GET_PRIVILEGES_DESCRIPTION('table', 's1.articles');
GET_PRIVILEGES_DESCRIPTION
--------------------------------
INSERT*, SELECT, UPDATE, DELETE
(1 row)
CREATE ACCESS POLICY 可用于在表上创建访问策略,以指定某些用户和角色可以从这些表中查询多少数据。访问策略通常会阻止这些用户查看表中特定列和行的数据。您可以将访问策略应用于表列和行。如果表的行和列上都有访问策略,Vertica 首先筛选行访问策略,然后筛选列访问策略。
可为任何表类型(列式、外部或 Flex 表)创建大部分访问策略。不能在 Flex 表上创建列访问策略。也可以对任何列类型(包括联接)上创建访问策略。
CREATE ACCESS POLICY 可以在各个表列上创建访问策略,每列一个策略。每个列访问策略都允许您为不同的用户和角色指定对该列数据的不同访问级别。列访问表达式还可以指定如何为用户和角色呈现列数据。
以下示例在 client_dimension
表中的 customer_address
列上创建访问策略。此访问策略为具有 administrator
角色的非超级用户提供对该列中所有数据的完全访问权限,但会屏蔽所有其他用户的客户地址数据:
=> CREATE ACCESS POLICY ON public.customer_dimension FOR COLUMN customer_address
-> CASE
-> WHEN ENABLED_ROLE('administrator') THEN customer_address
-> ELSE '**************'
-> END ENABLE;
CREATE ACCESS POLICY
Vertica 使用此策略来确定它授予用户 MaxineT 和 MikeL 的访问权限,对于这两个用户分别分配了 employee
和 administrator
角色。当这些用户查询 customer_dimension
表时,Vertica 会应用列访问策略表达式,如下所示:
=> \c - MaxineT;
You are now connected as user "MaxineT".
=> SET ROLE employee;
SET
=> SELECT customer_type, customer_name, customer_gender, customer_address, customer_city FROM customer_dimension;
customer_type | customer_name | customer_gender | customer_address | customer_city
---------------+-------------------------+-----------------+------------------+------------------
Individual | Craig S. Robinson | Male | ************** | Fayetteville
Individual | Mark M. Kramer | Male | ************** | Joliet
Individual | Barbara S. Farmer | Female | ************** | Alexandria
Individual | Julie S. McNulty | Female | ************** | Grand Prairie
...
=> \c - MikeL
You are now connected as user "MikeL".
=> SET ROLE administrator;
SET
=> SELECT customer_type, customer_name, customer_gender, customer_address, customer_city FROM customer_dimension;
customer_type | customer_name | customer_gender | customer_address | customer_city
---------------+-------------------------+-----------------+------------------+------------------
Individual | Craig S. Robinson | Male | 138 Alden Ave | Fayetteville
Individual | Mark M. Kramer | Male | 311 Green St | Joliet
Individual | Barbara S. Farmer | Female | 256 Cherry St | Alexandria
Individual | Julie S. McNulty | Female | 459 Essex St | Grand Prairie
...
访问策略具有以下限制:
一列只能有一个访问策略。
不能为除原生数组以外的复杂类型列设置列访问策略。
不能为 Flex 表中的实体化列设置列访问策略。可以为 __raw__
列设置访问策略,但此举将限制对整个表的访问。
行访问策略对临时表和具有聚合投影的表无效。
访问策略表达式不能包含:
子查询
聚合函数
分析函数
用户定义的转换函数 (UDTF)
如果查询优化器无法使用计算值替换仅涉及常量的确定性表达式,则会阻止所有 DML 操作,例如 INSERT。
CREATE ACCESS POLICY 可以为给定的表创建单行访问策略。此策略允许您为不同的用户和角色指定对表行数据的不同级别的访问权限。当用户启动查询时,Vertica 会对所有表行上访问策略的 WHERE 表达式求值。查询仅返回当前用户或角色的表达式求值结果为 true 的行。
例如,您可能希望为四个角色指定对表 store.store_store_sales
的不同访问级别:
employee
:具有此角色的用户只能访问 employee_key
列中将他们标识为员工的销售记录。以下查询显示有多少销售记录(在 store.store_sales_fact
中)与每个用户(在 public.emp_dimension
中)相关联:
=> SELECT COUNT(sf.employee_key) AS 'Total Sales', sf.employee_key, ed.user_name FROM store.store_sales_fact sf
JOIN emp_dimension ed ON sf.employee_key=ed.employee_key
WHERE ed.job_title='Sales Associate' GROUP BY sf.employee_key, ed.user_name ORDER BY sf.employee_key
Total Sales | employee_key | user_name
-------------+--------------+-------------
533 | 111 | LucasLC
442 | 124 | JohnSN
487 | 127 | SamNS
477 | 132 | MeghanMD
545 | 140 | HaroldON
...
563 | 1991 | MidoriMG
367 | 1993 | ThomZM
(318 rows)
regional_manager
:具有此角色 (public.emp_dimension
) 的用户只能访问他们管理的销售区域 (store.store_dimension
) 的销售记录:
=> SELECT distinct sd.store_region, ed.user_name, ed.employee_key, ed.job_title FROM store.store_dimension sd
JOIN emp_dimension ed ON sd.store_region=ed.employee_region WHERE ed.job_title = 'Regional Manager';
store_region | user_name | employee_key | job_title
--------------+-----------+--------------+------------------
West | JamesGD | 1070 | Regional Manager
South | SharonDM | 1710 | Regional Manager
East | BenOV | 593 | Regional Manager
MidWest | LilyCP | 611 | Regional Manager
NorthWest | CarlaTG | 1058 | Regional Manager
SouthWest | MarcusNK | 150 | Regional Manager
(6 rows)
dbadmin
和 administrator
:具有这些角色的用户可以无限制地访问所有表数据。
给定这些用户以及与他们关联的数据,您可以在 store.store_store_sales
上创建如下所示的行访问策略:
CREATE ACCESS POLICY ON store.store_sales_fact FOR ROWS WHERE
(ENABLED_ROLE('employee')) AND (store.store_sales_fact.employee_key IN
(SELECT employee_key FROM public.emp_dimension WHERE user_name=CURRENT_USER()))
OR
(ENABLED_ROLE('regional_manager')) AND (store.store_sales_fact.store_key IN
(SELECT sd.store_key FROM store.store_dimension sd
JOIN emp_dimension ed ON sd.store_region=ed.employee_region WHERE ed.user_name = CURRENT_USER()))
OR ENABLED_ROLE('dbadmin')
OR ENABLED_ROLE ('administrator')
ENABLE;
以下示例指示具有指定角色的用户可以使用的不同访问级别:
dbadmin
可以访问 store.store_sales_fact
中的所有行:
=> \c
You are now connected as user "dbadmin".
=> SELECT count(*) FROM store.store_sales_fact;
count
---------
5000000
(1 row)
用户 LilyCP
具有 regional_manager
角色,因此她可以访问她管理的中西部地区的所有销售数据:
=> \c - LilyCP;
You are now connected as user "LilyCP".
=> SET ROLE regional_manager;
SET
=> SELECT count(*) FROM store.store_sales_fact;
count
--------
782272
(1 row)
用户 SamRJ
具有 employee
角色,因此他只能访问与其关联的销售数据:
=> \c - SamRJ;
You are now connected as user "SamRJ".
=> SET ROLE employee;
SET
=> SELECT count(*) FROM store.store_sales_fact;
count
-------
417
(1 row)
以下限制适用于行访问策略:
一个表只能有一个行访问策略。
下表中的行访问策略无效:
具有聚合投影的表
临时表
系统表
视图
您不能在具有行访问策略的表上创建定向查询。
默认情况下,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 会覆盖默认行为(“用户只能编辑他们可以看到的内容”),并指示访问策略在评估用户能否执行 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”角色的用户。
访问策略会影响 Vertica Database Designer 生成的投影设计,以及优化器为查询执行创建的计划。
Database Designer 为给定表创建投影时,将考虑适用于当前用户的访问策略。Database Designer 为表生成的投影集已针对该用户的访问权限以及具有类似访问权限的其他用户进行优化。但这些投影对于具有不同访问权限的用户可能不太理想。这些差异可能会对 Vertica 如何高效处理第二组用户的查询有一些影响。当您评估表的投影设计时,请选择一种为所有授权用户优化访问的设计。
Vertica 优化器通过在其查询计划中重写用户查询来强制执行访问策略,这会影响查询性能。例如,clients 表具有行和列访问策略,均已启用。当用户查询此表时,查询优化器会生成一个用来重写查询的计划,因此它包含两个策略:
=> SELECT * FROM clients;
查询优化器生成一个查询计划,该计划按如下方式重写查询:
SELECT * FROM (
SELECT custID, password, CASE WHEN enabled_role('manager') THEN SSN ELSE substr(SSN, 8, 4) END AS SSN FROM clients
WHERE enabled_role('broker') AND
clients.clientID IN (SELECT brokers.clientID FROM brokers WHERE broker_name = CURRENT_USER())
) clients;
默认情况下,您只能管理您拥有的表的访问策略。您可以选择使用 AccessPolicyManagementSuperuserOnly 参数(默认值为 false)仅允许超级用户管理访问策略:
=> ALTER DATABASE DEFAULT SET PARAMETER AccessPolicyManagementSuperuserOnly = 1;
ALTER DATABASE
您可以通过多种方式查看和管理表的访问策略:
您可以通过两种方式查看访问策略:
查询系统表 ACCESS_POLICY。例如,以下查询返回表 public.customer_dimension
上的所有访问策略:
=> \x
=> SELECT policy_type, is_policy_enabled, table_name, column_name, expression FROM access_policy WHERE table_name = 'public.customer_dimension';
-[ RECORD 1 ]-----+----------------------------------------------------------------------------------------
policy_type | Column Policy
is_policy_enabled | Enabled
table_name | public.customer_dimension
column_name | customer_address
expression | CASE WHEN enabled_role('administrator') THEN customer_address ELSE '**************' END
使用 EXPORT_TABLES、EXPORT_OBJECTS 或 EXPORT_CATALOG 从数据库编录导出表 DDL。例如:
=> SELECT export_tables('','customer_dimension');
export_tables
-----------------------------------------------------------------------------
CREATE TABLE public.customer_dimension
(
customer_key int NOT NULL,
customer_type varchar(16),
customer_name varchar(256),
customer_gender varchar(8),
...
CONSTRAINT C_PRIMARY PRIMARY KEY (customer_key) DISABLED
);
CREATE ACCESS POLICY ON public.customer_dimension FOR COLUMN customer_address CASE WHEN enabled_role('administrator') THEN customer_address ELSE '**************' END ENABLE;
ALTER ACCESS POLICY 可以修改现有访问策略的表达式。例如,您可以通过扩展对 dbadmin 角色的访问权限来修改前面示例中的访问策略:
=> ALTER ACCESS POLICY ON public.customer_dimension FOR COLUMN customer_address
CASE WHEN enabled_role('dbadmin') THEN customer_address
WHEN enabled_role('administrator') THEN customer_address
ELSE '**************' END ENABLE;
ALTER ACCESS POLICY
查询系统表 ACCESS_POLICY 会确认此更改:
=> SELECT policy_type, is_policy_enabled, table_name, column_name, expression FROM access_policy
WHERE table_name = 'public.customer_dimension' AND column_name='customer_address';
-[ RECORD 1 ]-----+-------------------------------------------------------------------------------------------------------------------------------------------
policy_type | Column Policy
is_policy_enabled | Enabled
table_name | public.customer_dimension
column_name | customer_address
expression | CASE WHEN enabled_role('dbadmin') THEN customer_address WHEN enabled_role('administrator') THEN customer_address ELSE '**************' END
表的所有者可以启用和禁用表中的行和列访问策略。
启用和禁用表中的访问策略。
ALTER ACCESS POLICY ON [schema.]table FOR ROWS { ENABLE | DISABLE }
以下示例先禁用后重新启用表 customer_dimension
上的行访问策略:
=> ALTER ACCESS POLICY ON customer_dimension FOR ROWS DISABLE;
ALTER ACCESS POLICY
=> ALTER ACCESS POLICY ON customer_dimension FOR ROWS ENABLE;
ALTER ACCESS POLICY
按如下方式启用和禁用表列的访问策略:
ALTER ACCESS POLICY ON [schema.]table FOR COLUMN column { ENABLE | DISABLE }
以下示例先禁用后重新启用表 customer_dimension.customer_address
上的同一个列访问策略:
=> ALTER ACCESS POLICY ON public.customer_dimension FOR COLUMN customer_address DISABLE;
ALTER ACCESS POLICY
=> ALTER ACCESS POLICY ON public.customer_dimension FOR COLUMN customer_address ENABLE;
ALTER ACCESS POLICY
按如下方式将访问策略从一个表复制到另一个表。非超级用户必须同时拥有源表和目标表的所有权:
ALTER ACCESS POLICY ON [schema.]table { FOR COLUMN column | FOR ROWS } COPY TO TABLE table
当您使用以下函数(而非 CREATE TABLE AS SELECT 或 CREATE TABLE LIKE)创建表的副本或移动其内容时,会将原始表的访问策略复制到新/目标表:
若要将访问策略复制到另一个表,请使用 ALTER ACCESS POLICY。
例如,您可以按如下方式复制行访问策略:
=> ALTER ACCESS POLICY ON public.emp_dimension FOR ROWS COPY TO TABLE public.regional_managers_dimension;
以下语句将列 employee_key
上的访问策略从表 public.emp_dimension
复制到 store.store_sales_fact
:
=> ALTER ACCESS POLICY ON public.emp_dimension FOR COLUMN employee_key COPY TO TABLE store.store_sales_fact;