数据库
首页 > 数据库> > clickhouse通过RABC即SQL-driven来管理用户权限

clickhouse通过RABC即SQL-driven来管理用户权限

作者:互联网

  ClickHouse也支持基于RBAC(Role-Based Access Control)的访问控制管理,即通过SQL-driven来进行管理。在 RBAC  中,权限与角色相关联,通过成为角色的成员而得到这些角色的权限。简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,ClickHouse推荐使用该方式进行用户权限管理。

说明

ClickHouse(version 20.9.3.45)权限包括:

- 用户账户
- 角色
- 行策略
- 设置描述
- 配额

可以通过如下方式配置权限:

建议使用SQL-driven工作流的方式。当然配置的方式也可以同时起作用, 可以平滑的配置管理方式切换到SQL-driven的工作流方式。

使用

在介绍用户权限管理之前,再次了解下用户权限相关的几个方面:

一 配置文件设置

1. 权限的类型:

ClickHouse中的查询可以分为几种类型:

  1. 读: SELECTSHOWDESCRIBEEXISTS.
  2. 写: INSERTOPTIMIZE.
  3. 设置: SETUSE.
  4. DDL: CREATEALTERRENAMEATTACHDETACHDROP TRUNCATE.
  5. KILL:kill 查询

以下设置按查询类型规范用户权限:

以上的权限通过配置标签来控制(users.xml):

<profiles>   --在profiles里设置
        ...
        <normal> --只读,不能DDL
            <readonly>1</readonly>
            <allow_ddl>0</allow_ddl>
        </normal>

        <normal_1> --读且能set,不能DDL
            <readonly>2</readonly>
            <allow_ddl>0</allow_ddl>
        </normal_1>

        <normal_2> --只读,即使DDL允许
            <readonly>1</readonly>
            <allow_ddl>1</allow_ddl>
        </normal_2>

        <normal_3> --读写,能DDL
            <readonly>0</readonly>
            <allow_ddl>1</allow_ddl>
        </normal_3>

    </profiles>

...
    <users>
        ...
        <test>
            <password>123456</password>
            <networks incl="networks" replace="replace">
                <ip>::/0</ip>
            </networks>
            <profile>normal_3</profile> --用户引用相关profile
            <quota>default</quota>
        </test>
    </users>
...

2. 配置组(Profiles)的设置:users.xml

profile的作用类似于用户角色,可以在users.xml中定义多组profile,并可以为每组profile定义不同的配置项:读、写、DDL权限,以及限制的设置,各个profile可以相互继承。设置好profile之后,可以在用户中被使用。

复制代码
<?xml version="1.0"?>
<yandex>
    <profiles>
        <!--自定义profile,可以任意命名-->
        <default>
            <max_memory_usage>100000000</max_memory_usage>
            <use_uncompressed_cache>0</use_uncompressed_cache>
            <load_balancing>random</load_balancing>
        </default>

        <readonly>
            <readonly>1</readonly>
        </readonly>

        <readwrite>
            <constraints>
                <max_memory_usage>
                    <readonly/>
                </max_memory_usage>
                <force_index_by_date>
                    <readonly/>
                </force_index_by_date>
            </constraints>
        </readwrite>

    </profiles>

...
</yandex>
复制代码

上面新增profile:readonly 和 readwrite,还可以在命令行里切换profile:

:) set profile = 'readonly';

切换了profile之后,就拥有了该profile下的权限。关于配置profile的修改,可以之前的文章【用户权限管理】。

3. 限制(constraints): 

users.xml配置文件的profile选项组下constraints选项组里定义设置的约束,并禁止用户使用SET查询更改某些设置。constraints标签可以设置一组约束条件,以限制profile内的参数值被随意修改,约束条件有如下三种规则:

复制代码
...
    <profiles>
        <default>
            <max_memory_usage>10000000000</max_memory_usage>
            <use_uncompressed_cache>0</use_uncompressed_cache>
            <force_index_by_date>0</force_index_by_date>
            <load_balancing>random</load_balancing>
        </default>
        <test>
            <constraints>
                <max_memory_usage>
                    <min>100000</min>
                    <max>200000</max>
                </max_memory_usage>
                <force_index_by_date>
                    <readonly/>
                </force_index_by_date>
            </constraints>
        </test>
    </profiles>
...
复制代码

上面对profile为test进行了限制,如果在该profile下试图违反约束,则会引发异常并且不会更改设置:

复制代码
:) SET max_memory_usage=2000000;
-- Code: 452. DB::Exception: Received from localhost:9010. DB::Exception: Setting max_memory_usage shouldn't be greater than 200000.

:) SET max_memory_usage=10000;
-- Code: 452. DB::Exception: Received from localhost:9010. DB::Exception: Setting max_memory_usage shouldn't be less than 100000. 

:) SET force_index_by_date=1;
-- Code: 452. DB::Exception: Received from localhost:9010. DB::Exception: Setting force_index_by_date should not be changed. 

 

复制代码

关于限制配置的修改,可以看之前的文章【用户权限管理】。

4. 配额(quotas)

配合,限制使用资源,类似于熔断。限制有二种类型:一是在固定周期里的执行次数(quotas),二是限制用户或则查询的使用资源(profiles)。在users.xml配置文件的选项组quotas里设置,限制该用户一段时间内的资源使用,即对一段时间内运行的一组查询施加限制,而不是限制单个查询。模板:

复制代码
<!-- Quotas. -->
    <quotas>
        <!-- Name of quota. -->
        <default> --指定quotas名
            <!-- Limits for time interval. You could specify many intervals with different limits. -->
            <interval> --时间间隔
                <!-- Length of interval. -->
                <duration>3600</duration> --周期
                <!-- No limits. Just calculate resource usage for time interval. -->
                <queries>0</queries>
                <errors>0</errors>
                <result_rows>0</result_rows>
                <read_rows>0</read_rows>
                <execution_time>0</execution_time>
            </interval>
        </default>
    </quotas>
复制代码

默认情况下,配额仅跟踪每小时的资源消耗,而没有限制使用情况。在每个请求之后,将为每个时间间隔计算的资源消耗输出到服务器日志。

说明:

关于配额熔断的配置,可以看之前的文章【用户权限管理】。

5. 用户设置

users.xml配置文件中的users选项组是配置自定义的用户,定义一个新用户,必须包含以下几项属性:用户名、密码、访问ip、数据库、表等等。它还可以应用上面的profile、constraints、quota。如:

复制代码
<users>
        <default>
            <password>123456</password>
            <networks incl="networks" replace="replace">
                <ip>::/0</ip>
            </networks>
            <profile>default</profile>
            <quota>default</quota>
        </default>

        <zhoujy>
            <password_double_sha1_hex>6bb4837eb74329105ee4568dda7dc67ed2ca2ad9</password_double_sha1_hex>
            <networks incl="networks" replace="replace">
                <ip>::/0</ip>
            </networks>
            <profile>default</profile>
            <quota>default</quota>
            <allow_databases>
                <database>test</database>
            </allow_databases>
            <databases>
                <test>  
                    <xx>
                        <filter>id >= 500 </filter>  --行级限制
                    </xx>
                </test>
            </databases>
        </zhoujy>

    </users>
复制代码

该示例指定了两个用户:

default:指定了密码、访问IP、profile、quota。
zhoujy :指定了密码、访问IP、profile、quota,以及它只能使用test库,并且只能返回test库xx表id大于等于500的数据。

通过以上的设置,已经把用户权限的知识点大部分都已经介绍完了,包括了读写权限、权限的限制和要把这些“规则”应用到用户上,这样就完成了用户权限的定制了。

以上所有介绍的知识点都可以看之前的文章【用户权限管理】,该文章中都做了详细的说明。通过修改配置文件虽然能实现ACL,但是比较麻烦,不便于维护管理。所以推荐使用SQL方式进行配置。本文的重点是介绍通过SQL-driven来进行管理用户权限。

二 SQL设置

启用SQL-driven管理需要开启users.xml文件中users的参数:

<access_management>1</access_management>

通过SQL-driven设置创建的用户,都存储在access目录中,该目录的位置是由参数 local_directory 控制:

 <local_directory>
            <!-- Path to folder where users created by SQL commands are stored. -->
            <!-- <path>/var/lib/clickhouse/access/</path> -->
            <path>/ccdata/clickhouse/access/</path>
        </local_directory>

1. 创建用户(Create User) 

复制代码
CREATE USER 
   [IF NOT EXISTS | OR REPLACE] name1 [ON CLUSTER cluster_name1] [, name2 [ON CLUSTER cluster_name2] ...]
    [NOT IDENTIFIED | IDENTIFIED {[WITH {no_password | plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']}]
    [HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
    [DEFAULT ROLE role [,...]]
    [GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
    [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY | WRITABLE] | PROFILE 'profile_name'] [,...]
复制代码

ON CLUSTER 子句允许在集群上创建用户。

① 用户认证:密码,用户连接密码。

IDENTIFIED WITH no_password   -- 没有密码
IDENTIFIED WITH plaintext_password BY 'qwerty'   -- 明文密码
IDENTIFIED WITH sha256_password BY 'qwerty' or IDENTIFIED BY 'password'  -- sha256_password 加密密码
IDENTIFIED WITH sha256_hash BY 'hash'  -- sha256_hash 加密密码
IDENTIFIED WITH double_sha1_password BY 'qwerty'  -- double_sha1_password 加密密码
IDENTIFIED WITH double_sha1_hash BY 'hash'  -- double_sha1_hash 加密密码
IDENTIFIED WITH ldap SERVER 'server_name'
IDENTIFIED WITH kerberos or IDENTIFIED WITH kerberos REALM 'realm'

 

② 用户主机:主机,用户连接地址。

HOST IP 'ip_address_or_subnetwork' —  用户通过指定IP连接。
HOST ANY — 可以从任何位置连接,默认。
HOST LOCAL — 只能在本地连接。
HOST NAME 'fqdn' — 用户主机可以指定为域名。
HOST NAME REGEXP 'regexp' — 主机使用正则表达式。
HOST LIKE 'template' — 使用 LIKE 运算符来过滤用户主机。 如HOST LIKE '%' 等价于 HOST ANY,HOST LIKE '%.mysite.com' 过滤 mysite.com 域中的所有主机。

指定主机的另一种方法是在用户名后使用@:

CREATE USER mira@'127.0.0.1' — 等效于 HOST IP 语法
CREATE USER mira@'localhost' — 等效于 HOST LOCAL 语法
CREATE USER mira@'192.168.%.%' — 等效于 HOST LIKE 语法

③  授权权限

通过GRANTEES来授权用户或则角色,可以获得创建该用户的权限。

④:例子

--创建密码为123456的用户cc,只能本机登录:
:) create user cc host ip '127.0.0.1' identified with sha256_password by '123456';
--创建用户帐户cao,为其分配角色并将此角色设为默认:
:) CREATE USER cao DEFAULT ROLE role1, role2;
--创建用户帐户 john 并将他未来的所有角色设为默认:
:) CREATE USER john DEFAULT ROLE ALL;
--当将来某个角色分配给 john 时,它将自动变为默认值。

--创建用户帐户 john 并将他未来的所有角色设为默认,除了 role1 和 role2:
:) CREATE USER john DEFAULT ROLE ALL EXCEPT role1, role2;
--创建用户帐户 john 并允许将权限授给具有 jack 帐户的用户:
:) CREATE USER john GRANTEES jack;
----  DB::Exception: user `john`: cannot insert because user `john` already exists in local directory: Couldn't insert user `john`. Successfully inserted: none. 

2. 创建角色(Create Role) 

创建角色,角色是一组权限。分配了角色的用户获得该角色的所有权限。

CREATE ROLE [IF NOT EXISTS | OR REPLACE] name1 [, name2 ...]
    [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]

一个用户可以分配多个角色。通过 SET ROLE 分配的角色。权限的范围是所有应用角色权限的组合集合。用户可以拥有适用于用户登录的默认角色,要设置默认角色,使用 SET DEFAULT ROLE 或 ALTER USER 语句。使用 REVOKE 来撤销角色,使用 DROP ROLE 来删除角色。

--创建角色

:) CREATE ROLE zjy;
--给角色授权

:) GRANT SELECT ON dbtest.* TO zjy;
--将角色分配给用户

 :) GRANT zjy TO cc;
--执行角色拥有的权限

:) SET ROLE zjy;

:) SELECT * FROM testdb.*;

3. 创建行策略(Create ROW POLICY) 

创建行策略,即用于确定用户可以从表中读取哪些行的过滤器。注意:行策略仅对具有只读访问权限的用户有意义。

CREATE [ROW] POLICY [IF NOT EXISTS | OR REPLACE] policy_name1 [ON CLUSTER cluster_name1] ON [db1.]table1 
        [, policy_name2 [ON CLUSTER cluster_name2] ON [db2.]table2 ...] 
    [FOR SELECT] USING condition
    [AS {PERMISSIVE | RESTRICTIVE}]
    [TO {role1 [, role2 ...] | ALL | ALL EXCEPT role1 [, role2 ...]}]

4. 创建熔断配额策略(CREATE QUOTA) 

创建可以分配给用户或角色的配额熔断策略。

CREATE QUOTA [IF NOT EXISTS | OR REPLACE] name [ON CLUSTER cluster_name]
    [KEYED BY {user_name | ip_address | client_key | client_key,user_name | client_key,ip_address} | NOT KEYED]
    [FOR [RANDOMIZED] INTERVAL number {second | minute | hour | day | week | month | quarter | year}
        {MAX { {queries | query_selects | query_inserts | errors | result_rows | result_bytes | read_rows | read_bytes | execution_time} = number } [,...] |
         NO LIMITS | TRACKING ONLY} [,...]]
    [TO {role [,...] | ALL | ALL EXCEPT role [,...]}]

关键字:user_name、ip_address、client_key、client_key、user_name和client_key、ip_address对应system.quotas表中的字段。

关键字:querys、query_selects、query_inserts、errors、result_rows、result_bytes、read_rows、read_bytes、execution_time对应system.quotas_usage表中的字段。

--将当前用户的最大查询数限制为 15 个月内123 次:

CREATE QUOTA qA FOR INTERVAL 15 month MAX queries = 123 TO CURRENT_USER;
--对于默认用户,在30分钟之内限制最大执行时间为半秒,将最大查询数限制为 321,将最大错误数限制为 10 :

CREATE QUOTA qB FOR INTERVAL 30 minute MAX execution_time = 0.5, FOR INTERVAL 5 quarter MAX queries = 321, errors = 10 TO default;
--在用户、角色和访问策略建立好之后,后面就需要授权了。

 

5. 创建配置组策略(CREATE SETTINGS PROFILE

创建可分配给用户或角色的设置配置文件

CREATE SETTINGS PROFILE [IF NOT EXISTS | OR REPLACE] TO name1 [ON CLUSTER cluster_name1] 
        [, name2 [ON CLUSTER cluster_name2] ...]
    [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | INHERIT 'profile_name'] [,...]
--例如:

CREATE SETTINGS PROFILE max_memory_usage_profile SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000 TO robin

 

使用 max_memory_usage 设置的值和约束创建 max_memory_usage_profile 设置配置文件,并将其分配给用户 robin:

6. 权限:权限是指执行特定操作的许可

权限有层级结构,一组允许的操作依赖相应的权限范围。 

级别(由低到高):

权限的层级:

7. 授权(Grants privileges)

取消权限,使用 REVOKE 语句,查看已授的权限使用 SHOW GRANTS 。

GRANT [ON CLUSTER cluster_name] privilege[(column_name [,...])] [,...] ON {db.table|db.*|*.*|table|*} TO {user | role | CURRENT_USER} [,...] [WITH GRANT OPTION]

WITH GRANT OPTION 授予 user 或 role执行 GRANT 操作的权限,之后该用户可将自身的权限对其他对象进行授权。

GRANT [ON CLUSTER cluster_name] role [,...] TO {user | another_role | CURRENT_USER} [,...] [WITH ADMIN OPTION]

WITH ADMIN OPTION 子句向用户或角色授予 ADMIN OPTION 特权。

使用 GRANT 账号必须有 GRANT OPTION的权限。用户只能将在自身权限范围内的权限进行授权。如:管理员有权通过下面的语句给 john账号添加授权

GRANT SELECT(x,y) ON db.table TO john WITH GRANT OPTION

john 有权执行 GRANT OPTION,他能给其它账号进行和自己账号权限范围相同的授权。可以使用* 号代替表或库名进行授权操作。同样,可以忽略库名,权限将指向当前的数据库。

可以一次给多个账号进行多种授权操作:

 GRANT SELECT,INSERT ON *.* TO john,robin;

允许 johnrobin 账号对任意数据库的任意表执行 INSERT和 SELECT操作。访问 systen数据库总是被允许的。

8. 撤权(revoke privileges)

9. 修改权限(ALTER)

10. 删除(drop)

DROP USER:删除用户
:) DROP USER [IF EXISTS] name [,...] [ON CLUSTER cluster_name];
--DROP ROLE:删除角色,删除的角色将从分配给它的所有实体中撤销。

:) DROP ROLE [IF EXISTS] name [,...] [ON CLUSTER cluster_name];
--DROP ROW POLICY:删除行策略,删除的行策略从分配给它的所有实体中撤销。

:) DROP [ROW] POLICY [IF EXISTS] name [,...] ON [database.]table [,...] [ON CLUSTER cluster_name];
--DROP QUOTA:删除配额熔断。 删除的配额熔断将从分配到它的所有实体中撤销。

:) DROP QUOTA [IF EXISTS] name [,...] [ON CLUSTER cluster_name];
--DROP SETTINGS PROFILE:删除profile文件。 已删除的文件将从分配给它的所有实体中撤销。

:) DROP [SETTINGS] PROFILE [IF EXISTS] name [,...] [ON CLUSTER cluster_name];

11. 查看权限(show)

--SHOW GRANTS:显示用户的权限
:) SHOW GRANTS [FOR user]
--SHOW CREATE USER:显示创建用户时用到的参数
:) SHOW CREATE USER [name | CURRENT_USER]
--SHOW CREATE ROLE:显示创建角色时用到的参数
:) SHOW CREATE ROLE name;
--SHOW CREATE ROW POLICY:显示创建行策略时用到的参数
:) SHOW CREATE [ROW] POLICY name ON [database.]table;
--SHOW CREATE QUOTA:显示创建时配额熔断时用到的参数

:) SHOW CREATE QUOTA [name | CURRENT];
--SHOW CREATE SETTINGS PROFILE:显示创建settings时用到的参数

:) SHOW CREATE [SETTINGS] PROFILE name;
--SHOW USERS:返回用户列表。查看用户参数,请参阅系统表system.users。
:) SHOW USERS;
--SHOW ROLES:返回角色列表。查看角色参数,请参阅系统表system.roles 和 system.role-grants。

:) SHOW [CURRENT|ENABLED] ROLES;
--SHOW PROFILES:返回配置文件列表。要查看配置参数,请参阅系统表settings_profiles。

:) SHOW [SETTINGS] PROFILES;
--SHOW POLICIES:返回指定表的行策略列表。 要查看用户帐户参数,请参阅系统表system.row_policies。

:) SHOW [ROW] POLICIES [ON [db.]table];
--SHOW QUOTAS:返回配额列表。 要查看配额参数,请参阅系统表system.quotas。

:) SHOW QUOTAS;
--SHOW QUOTA:返回所有用户或当前用户的配额。 要查看其他参数,请参阅系统表system.quotas_usage 和 system.quota_usage。

:) SHOW [CURRENT] QUOTA;
--SHOW ACCESS:显示目前所有的users、roles、profiles、grants信息。

:) SHOW ACCESS;
--SHOW SETTINGS:显示系统设置的列表。 从 system.settings 表中选择数据。

:) SHOW [CHANGED] SETTINGS LIKE|ILIKE <name>;

到此,访问权限和账户管理的介绍已经结束,包括了配置文件和SQL方式的设置,从用户创建/修改/删除、角色创建/修改/删除、权限创建/撤等等,更多的信息信息可以见官网说明。

实战

前提条件:因为是通过SQL-driven来进行账号操作的,在ClickHouse安装好之后,会有个默认账户default,在该用户下面开 access_management 参数即可。开启参数:

复制代码
  <users>

        <default>
            <password>123456</password>
            <networks>
                <ip>::/0</ip>
            </networks>
            <profile>default</profile>
            <quota>default</quota>
            <access_management>1</access_management>
        </default>

    </users>
复制代码

之后通过default用户进行SQL-driven的账号管理操作。

1. 创建账号

--管理账号
-- 创建账号
:) create user dba host ip '127.0.0.1' identified with sha256_password by '123456';

-- 授权,all
:) grant all on *.* to dba with grant option;
--普通业务读写账号
-- 创建账号
:) create user app host ip '127.0.0.1' identified with sha256_password by '123456';

-- 授权,增删改查权限
:) grant select,insert,alter delete,alter update on testdb.* to app; 
--只读账号
-- 创建账号
:) create user ro host ip '127.0.0.1' identified with sha256_password by '123456';

-- 授权,增删改查权限
:) grant select on testdb.* to ro;

更多的语法见上面的CREATE USER。

2. 创建Role

更多的语法见上面的CREATE ROLE。

3. 创建行策略

用于确定用户可以从表中读取哪些行的过滤器,对应配置问了里的filter参数。注意:行策略仅对具有只读访问权限的用户有意义。

复制代码
-- 创建行策略
:) CREATE ROW POLICY pol1 ON testdb.ttt USING b=1 TO app1;

-- 创建用户,该用户需要有select权限,才能应用
:) create user app1 host ip '127.0.0.1' identified with sha256_password by '123456'; 

-- 行策略应用,该策略只能访问x2表id大于5的数据
:) CREATE ROW POLICY pol1 ON testdb.x2 USING id>5 TO app1;
复制代码

更多的语法见上面的 CREATE ROW POLICY。

4. 创建QUOTA
分配给用户或角色的配额熔断策略,限制用户的使用资源。 

-- 创建quota
:) CREATE QUOTA qA FOR INTERVAL 5 minute MAX queries = 10 TO app1;

限制用户app1,5分钟之内最多执行次数,超过则报错:

Code: 201. DB::Exception: Received from localhost:9010. DB::Exception: Quota for user `app1` for 300s has been exceeded: queries = 11/10. Interval will end at 2021-07-01 00:20:00. Name of quota template: `qA`.

更多的语法见上面的 CREATE QUOTA。

5. 创建Profile

创建可分配给用户或角色的的配置文件。

-- 限制用户app的最大使用内存。
:) CREATE SETTINGS PROFILE max_memory_usage_profile SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000 TO app;

更多的语法见上面的 CREATE SETTINGS PROFILE。到此,正常的用户权限设置已经完成。

 

总结

从上面看到,通过SQL-driven来设置用户权限和管理比修改配置文件要方便很多,官方也推荐使用该方式进行用户权限管理。通过该方式配置的用户都是以文件形式存储在access目录中,该目录的位置是由参数 local_directory 控制:

      <local_directory>
            <!-- Path to folder where users created by SQL commands are stored. -->
            <!-- <path>/var/lib/clickhouse/access/</path> -->
            <path>/ccdata/clickhouse/access/</path>
        </local_directory>

注意,如果把该目录的文件删除,则会让这些用户角色全部失效。

标签:SHOW,--,CREATE,用户,driven,RABC,SQL,权限,级别
来源: https://www.cnblogs.com/MrYang-11-GetKnow/p/15896355.html