GRANT PERMISSION ON TABLE <table_name> FOR ROWS <where_clause>;
复制
针对数据敏感的场景,例如希望各银行的用户只能查询到各自分行的数据,不希望展示某些列(如电话号)的数据,此时可为指定的表授予行/列级权限,最大限度满足企业多样的数据管控需求,保护数据访问安全性。
本文介绍如何通过 SQL 命令的方式管理行/列级权限,此外,您还可以通过页面直观地配置库、表、列级权限。
行/列级与表级权限说明
类别 | 说明 |
---|---|
表权限(PRIVILEGE) |
限制执行 SELECT、INSERT、UPDATE、DELETE 操作。 |
行权限(PERMISSION) |
限制表级的 SELECT、UPDATE、DELETE 操作对指定行生效。 |
列权限(PERMISSION) |
限制表级的 SELECT 操作对指定列生效。 |
您需要为用户授予表级权限,行/列级权限设置才有意义,例如某用户没有表 A 的 SELECT 权限,那么为其授予行级 SELECT 权限也依旧无法读取表 A 的数据。
INSERT 操作不受行/列级权限限制,此外,由于行级权限没有“行 Owner” 的概念,不会自动继承行级权限,例如用户插入了一条数据,在对其执行 SELECT、UPDATE、DELETE 操作时依然受控于行权限约束。 |
SQL 语法及使用示例
执行本文介绍的 SQL 命令前,您需要以 ADMIN 角色或表 Owner 的身份连接数据库。 |
设置行级权限
语法
说明:<where_clause> 为一个where字句。
示例一:授予行权限给用户
在本示例中,我们在表中新建一个用户列(username),将每行记录的 username 值设为对该行记录有权限的用户,然后结合 context 函数,即可实现只有当前用户(current_user)和 username 的值相匹配时才能对记录进行操作。
本示例中,我们使用的表为 finances_holo,其完整数据如下:
+------+---------+-----------+ | eid | funds | username | +------+---------+-----------+ | 001 | 500.0 | alice | | 002 | 500.0 | bob | | 003 | 1000.0 | alice | | 004 | 2000.0 | carol | +------+---------+-----------+
复制
-
以 ADMIN 角色或表 Owner 的身份连接数据库,执行下述操作即可在实现上述需求,同时我们授予 ADMIN 角色对所有记录拥有操作权限。
GRANT PERMISSION ON TABLE finances_holo FOR ROWS WHERE username = CURRENT_USER() OR HAS_ROLE('admin');
复制 -
查看行级权限已开启,如下所示。
> SHOW PERMISSION ON TABLE finances_holo; +-------------+-------------------------------------------------------+ | row/column | definition | +-------------+-------------------------------------------------------+ | ROWS | WHERE username = CURRENT_USER() OR HAS_ROLE('admin') | +-------------+-------------------------------------------------------+
复制 -
(可选)验证用户权限。
上述授权操作并不会为用户赋予表级权限,例如某用户本身不具备对 finances_holo 表的 SELECT 权限,那么他也无法读取到数据。接下来,我们以 alice 用户为例,演示其在不同表权限下的数据读写情况。
-
场景一:alice 拥有表的 SELECT/INSERT/UPDATE/DELETE 权限时。
执行 SELECT 操作查看所有记录时,只会展示 username 值为 alice 的记录。
> SELECT * FROM finances_holo; +------+---------+-----------+ | eid | funds | username | +------+---------+-----------+ | 003 | 1000.0 | alice | | 001 | 500.0 | alice | +------+---------+-----------+
复制执行 UPDATE/DELETE 操作,只会对上述两条记录生效,以 UPDATE 操作为例,如下所示。
INSERT 权限不受行级权限影响。
> UPDATE finances_holo SET funds = 800 WHERE eid = "001"; 1 row affected (0.711 seconds) > SELECT * FROM finances_holo; +------+---------+-----------+ | eid | funds | username | +------+---------+-----------+ | 003 | 1000.0 | alice | | 001 | 800.0 | alice | +------+---------+-----------+ 2 rows selected (1.68 seconds)
复制 -
场景二:alice 不具备 finances_holo 表的任何权限。
以执行 SELECT 操作查看数据为例,ArgoDB 将返回无权限提示信息。
> SELECT * FROM finances_holo; Error: COMPILE FAILED: Internal error HiveAccessControlException: [Error 20388] Permission denied: Principal [name=alice, type=USER] does not have following privileges for operation QUERY [[SELECT] on Object [type=TABLE_OR_VIEW, name=demodata.finances_holo]] (state=42000,code=20388)
复制
-
示例二:使用辅助表设置行级权限
本示例中,我们希望安装用户所在的分支银行对 finances_new 表授予行级权限,即用户只能看到其所属支行的数据。
首先,我们为表新增一个支行列(branch),将每行记录的 username 值设置为对该行记录有权限的 支行名称,然后通过一个辅助表来记录用户与支行的对应关系,在行级权限设置时,通过该表过滤出有权限的用户。
本示例中,我们使用了两个表,分别是:
-
finances_new:完整数据如下。
+------+---------+---------+ | eid | funds | branch | +------+---------+---------+ | 001 | 500.0 | A | | 002 | 500.0 | A | | 003 | 1000.0 | A | | 004 | 2000.0 | B | +------+---------+---------+
复制 -
branch_assignment(辅助表),记录了用户与支行的关系,完整数据如下。
> SELECT * FROM branch_assignment; +-----------+---------+ | username | branch | +-----------+---------+ | bob | A | | alice | A | | carol | B | +-----------+---------+
复制-
以 ADMIN 角色或表 Owner 的身份连接数据库,执行下述操作即可在实现上述需求,同时我们授予 ADMIN 角色对所有记录拥有操作权限。
GRANT PERMISSION ON TABLE finances_new FOR ROWS WHERE branch = (SELECT branch FROM branch_assignment WHERE username = CURRENT_USER()) OR HAS_ROLE('ADMIN');
复制为保障权限判断运行正常,我们为用户授予了 branch_assignment 表的 SELECT 权限。
-
执行
SHOW PERMISSION ON finances_new;
命令可查看行级权限已开启。 -
(可选)验证用户权限。
假设我们已经为不同支行的用户授予了 finances_new 表的 SELECT 权限,接下来,我们以 alice 和 carol 用户为例,演示其数据读取情况。
-
以 alice 身份连接 ArgoDB 数据库,只能看到 A 支行的数据。
> SELECT * FROM finances_new; +------+---------+---------+ | eid | funds | branch | +------+---------+---------+ | 001 | 500.0 | A | | 002 | 500.0 | A | | 003 | 1000.0 | A | +------+---------+---------+
复制 -
以 carol 身份连接 ArgoDB 数据库,只能看到 B 支行的数据。
> SELECT * FROM finances_new; +------+---------+---------+ | eid | funds | branch | +------+---------+---------+ | 004 | 2000.0 | B | +------+---------+---------+
复制
-
-
撤销行级权限设置
语法
REVOKE PERMISSION ON TABLE <table_name> FOR ROWS;
复制
<table_name>更换为目标表名,执行该语句将撤销对指定表的行级权限设置。
示例
-
以 ADMIN 角色或表 Owner 的身份连接数据库,查看 finances_holo 表的行级权限设置。
SHOW PERMISSION ON TABLE finances_holo; +-------------+-------------------------------------------------------+ | row/column | definition | +-------------+-------------------------------------------------------+ | ROWS | WHERE username = CURRENT_USER() OR HAS_ROLE('admin') | +-------------+-------------------------------------------------------+
复制 -
撤销行级权限设置,随后查看权限设置已清空。
> REVOKE PERMISSION ON TABLE finances_holo FOR ROWS; No rows affected (0.115 seconds) > SHOW PERMISSION ON TABLE finances_holo; +-------------+-------------+ | row/column | definition | +-------------+-------------+ +-------------+-------------+
复制
设置列级权限
语法
GRANT PERMISSION ON [TABLE] <table_name> FOR COLUMN <case_when>;
复制
这里的 <case_when_clause> 为一个 CASE WHEN 条件函数。
使用示例
假设我们有一个银行用户信息表(bank_account),其完整数据如下。
+--------+---------------------+------------------+ | name | id | email | +--------+---------------------+------------------+ | jack | 511702198907108849 | jack@126.com | | alice | 530724198511061294 | alice@gmail.com | | tom | 320702199203128764 | tom@outlook.com | | amy | 440183198811183889 | amy@qq.com | +--------+---------------------+------------------+
复制
为保障信息安全,我们希望只有 ADMIN 用和表 Owner 可查看完整数据,对普通的业务用户只展示脱敏后的数据,具体如下:
-
name 列:只显示第一个字符,其他隐藏为星号。
-
id 列:只显示前三位,后四位,其他隐藏。
-
email 列:邮箱的用户仅显示第一个字母,其余隐藏为星号,同时可正常展示邮箱域名。
-
以 ADMIN 角色或表 Owner 的身份连接数据库,执行下述命令为 normal_user 和 hive 用户授予 bank_account 表的 SELECT 权限。
GRANT SELECT ON bank_account TO USER hive, USER normal_user;
复制 -
依次执行下述命令,完成列级权限设置。
-- 当用户角色不为 ADMIN 时,只显示 name 列的第一个字符,其他隐藏为星号; GRANT PERMISSION ON bank_account FOR COLUMN name CASE WHEN HAS_ROLE('ADMIN') THEN name ELSE MASK(name, 1) END;
复制-- 当用户角色不为 ADMIN 时,只显示 id 列的前三位,后四位,其他隐藏为星号; GRANT PERMISSION ON bank_account FOR COLUMN id CASE WHEN HAS_ROLE('ADMIN') THEN id ELSE MASK(id, 3, 4) END;
复制-- 当用户角色不为 ADMIN 时,只显示 email 列邮箱前缀的第一个字母,前缀的其他字母隐藏为星号,邮箱域名显示。 GRANT PERMISSION ON bank_account FOR COLUMN email CASE WHEN HAS_ROLE('ADMIN') THEN email ELSE MASK_EMAIL(email) END;
复制关于脱敏用法的详细介绍,见脱敏函数。
-
查看授权设置,示例如下。
> SHOW PERMISSION ON bank_account; +---------------+--------------------------------------------------------------------+ | row/column | definition | +---------------+--------------------------------------------------------------------+ | COLUMN name | CASE WHEN HAS_ROLE('ADMIN') THEN name ELSE MASK(name, 1) END | | COLUMN id | CASE WHEN HAS_ROLE('ADMIN') THEN id ELSE MASK(id, 3, 4) END | | COLUMN email | CASE WHEN HAS_ROLE('ADMIN') THEN email ELSE MASK_EMAIL(email) END | +---------------+--------------------------------------------------------------------+
复制 -
(可选)验证用户权限。
-
-
以管理员 hive 身份连接数据库,可查看到完整的数据。
> SET ROLE ADMIN; No rows affected (0.031 seconds) > SELECT * FROM bank_account; +--------+---------------------+------------------+ | name | id | email | +--------+---------------------+------------------+ | jack | 511702198907108849 | jack@126.com | | alice | 530724198511061294 | alice@gmail.com | | tom | 320702199203128764 | tom@outlook.com | | amy | 440183198811183889 | amy@qq.com | +--------+---------------------+------------------+
复制 -
以普通用户 normal_user 身份连接数据库,只能查看到脱敏后的数据。
> SELECT * FROM bank_account; +--------+---------------------+------------------+ | name | id | email | +--------+---------------------+------------------+ | j*** | 511***********8849 | j***@126.com | | a**** | 530***********1294 | a****@gmail.com | | t** | 320***********8764 | t**@outlook.com | | a** | 440***********3889 | a**@qq.com | +--------+---------------------+------------------+
复制
撤销列级权限设置
撤销指定列的权限设置
语法
REVOKE PERMISSION ON [TABLE] <table_name> FOR COLUMN <column_name>;
复制
示例
撤销 bank_account 表中,对 email 列的权限设置。
REVOKE PERMISSION ON bank_account FOR COLUMN email;
复制
撤销表中所有列的权限设置
语法
REVOKE PERMISSION ON [TABLE] <table_name> FOR COLUMNS;
复制
示例
撤销 bank_account 表中,对所有列的权限设置。
REVOKE PERMISSION ON bank_account FOR COLUMNS;
复制
查看行/列级权限
语法
SHOW PERMISSION ON TABLE <table_name>;
复制
如需查看表权限,可通过 SHOW GRANT 命令。 |
示例
> SHOW PERMISSION ON TABLE bank_account; +---------------+--------------------------------------------------------------------+ | row/column | definition | +---------------+--------------------------------------------------------------------+ | COLUMN name | CASE WHEN HAS_ROLE('ADMIN') THEN name ELSE MASK(name, 1) END | | COLUMN id | CASE WHEN HAS_ROLE('ADMIN') THEN id ELSE MASK(id, 3, 4) END | | COLUMN email | CASE WHEN HAS_ROLE('ADMIN') THEN email ELSE MASK_EMAIL(email) END | +---------------+--------------------------------------------------------------------+
复制