clickhouse通过修改配置文件管理用户权限

  ClickHouse作为一个分析类型(OLAP)的数据库系统,相对于MySQL数据库在用户管理方面有很大不同,它是可以通过修改配置文件来实现用户权限管理的。在安装好ClickHouse之后,其默认的配置文件在/etc/clickhouse-server目录下,对应的配置文件为users.xml,ClickHouse使用它来定义用户相关的配置项。现在开始对其进行说明,对应手册里的说明包含以下几个方面:

  • Settings profiles 
  • User settings
  • Constraints on Settings
  • Quotas
  • Permissions for queries
  • Access Rights

注意一点,修改了user.xml的参数之后是即时生效的,如有问题可以查看其错误日志。好了,现在开始对这些进行说明,先熟悉用户权限管理这一方面的相关操作。

※ Settings profiles :设置用户配置文件

profile的作用类似于用户角色,可以在user.xml中定义多组profile,并可以为每组profile定义不同的配置项,类限制资源的使用。多个profile的配置可以复用。咋眼一看有点和MySQL的Proxy权限类似。

模板:

复制代码
  <profiles> --配置profile
        <default>  -- 自定义profile
            <max_memory_usage>10000000000</max_memory_usage>
            <use_uncompressed_cache>0</use_uncompressed_cache>
            <load_balancing>random</load_balancing>
        </default>
        <readonly>  -- 自定义profile
            <readonly>1</readonly>
       <max_memory_usage>100000000</max_memory_usage>
        </readonly>
    </profiles>
复制代码

说明:

  • <default>:自定义profile,可以在它下面设置相关参数,如:最大内存使用、只读等等。更多的配置参数后续会介绍,也而已看官网文档,可以设置多个profile。

该示例指定了两个profile:default和readonly。 默认<default>有一个特殊用途:必须始终存在并且在启动服务器时应用。profile文件可以相互继承,只需要在配置文件中列出即可,如定义一个test的profile:

        <test>
            <profile>readonly</profile>
            <max_memory_usage>10000</max_memory_usage>
        </test> 

test的profile继承了readonly的profile,包含了其所有的配置,并且使用新参数来覆盖其原有的配置。设置了之后如何使用呢?有二种方法,第1是直接在终端命令行里进行设置,第2个是在users.xml中的users选项组里进行指定(后面会说明)。

[root@dba clickhouse-server]# clickhouse-client
ClickHouse client version 20.3.5.21 (official build).
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 20.3.5 revision 54433.

dba :) set profile = 'test'

SET profile = 'test'

Ok.
rows in set. Elapsed: 0.002 sec.

dba :) set max_memory_usage = 123123

SET max_memory_usage = 123123

Received exception from server (version 20.3.5):
Code: 164. DB::Exception: Received from localhost:9000. DB::Exception: Cannot modify 'max_memory_usage' setting in readonly mode.
rows in set. Elapsed: 0.005 sec.

dba :) Bye.
复制代码
[root@dba clickhouse-server]# clickhouse-client
ClickHouse client version 20.3.5.21 (official build).
Connecting to localhost:9000 as user default.
Connected to ClickHouse server version 20.3.5 revision 54433.

dba :) set profile = 'test'

SET profile = 'test'

Ok.
rows in set. Elapsed: 0.002 sec. 

dba :) set max_memory_usage = 123123

SET max_memory_usage = 123123

Received exception from server (version 20.3.5):
Code: 164. DB::Exception: Received from localhost:9000. DB::Exception: Cannot modify 'max_memory_usage' setting in readonly mode. 
rows in set. Elapsed: 0.005 sec. 

dba :) Bye.
复制代码

测试说明已经把readonly的profile的参数(readonly)继承过来了。 

※ Constraints on Settings:约束

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

  • min:最小值约束,在设置相应参数的时候,取值不能小于该阈值;

  • max:最大值约束,在设置相应参数的时候,取值不能大于该阈值;

  • readonly:只读约束,该参数值不允许被修改。

需要在profile选项组里设置constraints,模板:

复制代码
<profiles>
  <user_name>
    <constraints>
      <setting_name_1>
        <min>lower_boundary</min>
      </setting_name_1>
      <setting_name_2>
        <max>upper_boundary</max>
      </setting_name_2>
      <setting_name_3>
        <min>lower_boundary</min>
        <max>upper_boundary</max>
      </setting_name_3>
      <setting_name_4>
        <readonly/>
      </setting_name_4>
    </constraints>
  </user_name>
</profiles>

 

复制代码

说明:如果违反约束,则会引发异常,并且设置实际上不会更改。支持三种约束类型:最小,最大,只读。 最小和最大约束为数字设置指定上限和下限,并且可以组合使用。 只读约束指定用户完全不能更改相应的设置。如: 

复制代码
 <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>
            <constraints>
                <max_memory_usage>
                    <min>100000</min>
                    <max>20000</max>
                </max_memory_usage>
                <force_index_by_date>
                    <readonly/>
                </force_index_by_date>
            </constraints>
        </default>
    </profiles>
复制代码

说明:在default默认profile中定义的constraints约束,将作为默认的全局约束,自动被其他profile继承。例子中约束了参数max_memory_usage的最大最小值和参数force_index_by_date的只读属性,不能修改。关于更多的参数后续会再进行说明,也可以看官方文档。如果违反约束则会报错:

Code: 452. DB::Exception: Received from localhost:9000. DB::Exception: Setting max_memory_usage shouldn't be less than 100000.

Code: 452. DB::Exception: Received from localhost:9000. DB::Exception: Setting force_index_by_date should not be changed. 
Code: 452. DB::Exception: Received from localhost:9000. DB::Exception: Setting max_memory_usage shouldn't be less than 100000.

Code: 452. DB::Exception: Received from localhost:9000. DB::Exception: Setting force_index_by_date should not be changed. 

※ Quotas:配额,限制使用资源,限制有二种类型:一是在固定周期里的执行次数(quotas),二是限制用户或则查询的使用资源(profiles)

user.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>
复制代码

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

说明:

  • <default>:配额规则名。
  • <interval>:配置时间间隔,每个时间内的资源消耗限制。
  • <duration>:时间周期,单位秒。
  • <queries>:时间周期内允许的请求总数,0表示不限制。
  • <errors>:时间周期内允许的异常总数,0表示不限制。
  • <result_rows>:时间周期内允许返回的行数,0表示不限制。
  • <read_rows>:时间周期内允许在分布式查询中,远端节点读取的数据行数,0表示不限制。
  • <execution_time>:时间周期内允许执行的查询时间,单位是秒,0表示不限制。

上面示例中的配置,属性值均为0,所以资源配额不做任何限制。现在继续声明另外一组配额:

复制代码
<statbox>
    <interval>
        <duration>3600</duration>
        <queries>1000</queries>
        <errors>100</errors>
        <result_rows>1000000000</result_rows>
        <read_rows>100000000000</read_rows>
        <execution_time>900</execution_time>
    </interval>

    <interval>
        <duration>86400</duration>
        <queries>10000</queries>
        <errors>1000</errors>
        <result_rows>5000000000</result_rows>
        <read_rows>500000000000</read_rows>
        <execution_time>7200</execution_time>
    </interval>
</statbox>
复制代码

说明:对于“ statbox”配额,每小时和每24小时(86,400秒)设置限制, 如果超过限制则会执行失败,并给出何时才能执行的错误:

 

Code: 201. DB::Exception: Received from localhost:9000. DB::Exception: Quota for user `default` for 10s has been exceeded: queries = 4/3. Interval will end at 2020-04-02 11:29:40. Name of quota template: `default`.

Code: 201. DB::Exception: Received from localhost:9000. DB::Exception: Quota for user `default` for 10s has been exceeded: queries = 4/3. Interval will end at 2020-04-02 11:29:40. Name of quota template: `default`. 

从实施定义的固定时刻开始计算时间间隔。间隔结束时,将清除所有收集的值。 接下来的一个小时,配额计算将重新开始。对于分布式查询处理,累积量存储在请求者服务器上。 因此,如果用户转到另一台服务器,则那里的配额将重新开始。重新启动服务器后,配额将重置。

quotas 在配置的“用户”部分分配给用户,如果不是根据时间周期而是根据查询的资源消耗来进行限制,则在user.xml里的profile里进行设置,如参数:

复制代码
1:max_memory_usage:在单个ClickHouse服务进程中,运行一次查询限制使用的最大内存用量,默认值为10G;
2:max_memory_usage_for_user:在单个ClickHouse服务进程中,以用户为单位进行统计,单个用户在运行查询时,限制使用的最大内存用量,默认值为0,即不做限制;
3:max_memory_usage_for_all_queries:在单个ClickHouse服务进程中,所有运行的查询累加在一起,限制使用的最大内存用量,默认为0不做限制;
4:max_partitions_per_insert_block:在单次INSERT写入的时候,限制创建的最大分区个数,默认值为100个。如果超出这个阈值数目,将会得到异常;
5:max_rows_to_group_by:在执行GROUP BY聚合查询的时候,限制去重后的聚合KEY的最大个数,默认值为0,即不做限制。当超过阈值数量的时候,其处理方式由group_by_overflow_mode参数决定;
6:group_by_overflow_mode:当max_rows_to_group_by熔断规则触发的时候,有三种处理形式: 
throw抛出异常,此乃默认值;
break立即停止查询,并返回当前部分的数据;
any仅以当前已存在的聚合KEY,继续完成聚合查询;
7:max_bytes_before_external_group_by:在执行GROUP BY聚合查询的时候,限制使用的最大内存用量,默认值为0,即不做限制。当超过阈值数量的时候,聚合查询将会进一步借用本地磁盘。
复制代码

如果超过了限制则报错:

Code: 241. DB::Exception: Received from localhost:9000. DB::Exception: Memory limit (for user) exceeded: would use 4.81 MiB (attempt to allocate chunk of 5045339 bytes), maximum: 1.00 B: While executing MergeTree

Code: 241. DB::Exception: Received from localhost:9000. DB::Exception: Memory limit (for user) exceeded: would use 4.81 MiB (attempt to allocate chunk of 5045339 bytes), maximum: 1.00 B: While executing MergeTree

※ User settings:用户配置

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

模板:

复制代码
<users>
    <!-- If user name was not specified, 'default' user is used. -->
    <user_name> --配置的用户
        <password></password> --明文密码
        <!-- Or -->
        <password_sha256_hex></password_sha256_hex> --加密密码,二选一

        <networks incl="networks" replace="replace"> --允许登录的地址,用于限制用户登录的客户端地址
        </networks>

        <profile>profile_name</profile>   --指定用户的profile

        <quota>default</quota>    -- 指定用户的quota,限制用户使用资源

        <databases>               --指定数据库
            <database_name>
                <table_name>      --指定数据表
                    <filter>expression</filter>
                </table_name>
            </database_name>
        </databases>
    </user_name>
    <!-- Other users settings -->
</users>
复制代码

说明:默认配置了default用户,在此之前的所有示例中,一直使用的是这个用户。

  • <user_name>:自定义用户
  • <password>:用户密码
    密码可以以纯文本、SHA256(十六进制格式)、password_double_sha1_hex(和MySQL兼容)指定,设置方法如下:
    复制代码
    1.纯文本:
    <password>password</password>
    2.sha256:
    <password_sha256_hex>password</password_sha256_hex>
    从shell生成密码的示例:
    PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha256sum | tr -d '-'
    第一行明文,第二行sha256
    3.sha1:
    <password_double_sha1_hex>password</password_double_sha1_hex> 从shell生成密码的示例: PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha1sum | tr -d '-' | xxd -r -p | sha1sum | tr -d '-' 第一行明文,第二行sha1
    复制代码
  • <networks>:限制用户登录的客户端地址
    可以通过IP,主机等进行限制
    复制代码
    <ip>:IP地址,如10.0.0.1
    <host>:主机名,如example01.host.ru
    <host_regexp>:^example\d\d-\d\d-\d\.host\.ru$
    
    来自任何IP:
    <ip> :: / 0 </ ip>
    来自本机:
    <ip>::1</ip>
    <ip>127.0.0.1</ip>
    复制代码
  • <profile>:指定用户的profile
  • <quota>:指定用户的quota,限制用户使用资源
  • <database_name>:指定用户访问的数据库
  • <table_name>:指定用户访问的表
  • <filter>:指定用户访问的过滤器,限制返回符合条件的行。如:id = 1 ,即查询表只返回id=1的行

例子:

复制代码
  <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的数据。

※ Permissions for queries:查询权限管理

查询可以分为以下几种类型:

  • 读:SELECT,SHOW,DESCRIBE,EXISTS
  • 写:INSERT,OPTIMIZE。
  • DDL:CREATE,ALTER,RENAME,ATTACH,DETACH,DROP TRUNCATE。
  • 设置:SET,USE。
  • KILL

以上的权限通过配置标签来控制:

readonly :读权限、写权限和设置权限,由此标签控制,它有三种取值:

  • 0,不进行任何限制(默认值);

  • 1,只拥有读权限(只能执行SELECT、EXISTS、SHOW和DESCRIBE);

  • 2,拥有读权限和设置权限(在读权限基础上,增加了SET查询)。

当设置readonly=1后,用户将无法在当前会话中更改readonly和allow_ddl设置;也可以通过约束来限制更改权限。

allow_ddl:DDL权限由此标签控制,它有两种取值:

  • 当取值为0时,不允许DDL查询;

  • 当取值为1时,允许DDL查询(默认值)

如果当前会话的allow_ddl = 0,则无法执行SET allow_ddl = 1

注意:KILL QUERY可以在任何设置上执行,readonlyallow_ddl需要定义在用户profiles中。

复制代码
 <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>
...
复制代码

说明:在profiles里设置相应的权限角色,再在users里引用,继承这些参数的限制。

※ Access Rights:访问权限控制

访问权限在users.xml中的users选项组里设置,用于在群集中组合的服务器之间交换信息的用户不得有任何限制或配额-否则,分布式查询将失败。不能授予对一个数据库有完全访问权限,而对另一数据库具有只读访问权限。权限控制包含如下:

  • 网络访问控制:通过IP地址或则host主机名
  • 数据库访问控制:通过read_only、allow_ddl来控制读、写、设置、DDL、KILL等
  • 指定数据库访问:通过<allow_databases>指定访问数据库
  • 指定表的访问:通过filter指定表达式来访问表中的数据行

使用

在说明部分已经对ClickHouse的用户权限管理做了大致介绍,如果需要后续会继续更新相关知识点。好了,现在开始对各种场景进行生成相应的用户配置文件。

1)管理账号:因为profiles里默认的profile是没有限制的,所以默认就是管理账号。因为ClickHouse的没有类似MySQL这样的管理权限,所以默认情况下管理账号也是读写账号。唯一的区别就是限制各个账号可以设置不同的使用资源。 

<?xml version="1.0"?>
<yandex>
<profiles>
<default>
<max_memory_usage>10000000000</max_memory_usage>
<use_uncompressed_cache>0</use_uncompressed_cache>
<load_balancing>random</load_balancing>
</default>
<readonly>
<readonly>1</readonly>
</readonly>
</profiles>

<users>
<default>
<password></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>
<ip>127.0.0.1</ip>
<ip>192.168.163.132</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
</zhoujy>

</users>

<quotas>
<default>
<interval>
<duration>3600</duration>
<queries>0</queries>
<errors>0</errors>
<result_rows>0</result_rows>
<read_rows>0</read_rows>
<execution_time>0</execution_time>
</interval>
</default>
</quotas>

</yandex>

 

复制代码
<?xml version="1.0"?>
<yandex>
    <profiles>
        <default>
            <max_memory_usage>10000000000</max_memory_usage>
            <use_uncompressed_cache>0</use_uncompressed_cache>
            <load_balancing>random</load_balancing>
        </default>
        <readonly>
            <readonly>1</readonly>
        </readonly>
    </profiles>

    <users>
        <default>
            <password></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>
                <ip>127.0.0.1</ip>
                <ip>192.168.163.132</ip>
            </networks>
            <profile>default</profile>
            <quota>default</quota>
        </zhoujy>

    </users>

    <quotas>
        <default>
            <interval>
                <duration>3600</duration>
                <queries>0</queries>
                <errors>0</errors>
                <result_rows>0</result_rows>
                <read_rows>0</read_rows>
                <execution_time>0</execution_time>
            </interval>
        </default>
    </quotas>

</yandex>
复制代码

2)只读账号:在profiles里设置readonly,在users里给指定用户进行引用。

<?xml version="1.0"?>
<yandex>
<profiles>
<default>
<max_memory_usage>10000000000</max_memory_usage>
<use_uncompressed_cache>0</use_uncompressed_cache>
<load_balancing>random</load_balancing>
</default>
<readonly>
<readonly>1</readonly>
</readonly>
</profiles>

<users>
<default>
<password></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>
<ip>127.0.0.1</ip>
<ip>192.168.163.132</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
</zhoujy>

</users>

<quotas>
<default>
<interval>
<duration>3600</duration>
<queries>0</queries>
<errors>0</errors>
<result_rows>0</result_rows>
<read_rows>0</read_rows>
<execution_time>0</execution_time>
</interval>
</default>
</quotas>

</yandex>
复制代码
<?xml version="1.0"?>
<yandex>
    <profiles>
        <default>
            <max_memory_usage>10000000000</max_memory_usage>
            <use_uncompressed_cache>0</use_uncompressed_cache>
            <load_balancing>random</load_balancing>
        </default>
        <readonly>
            <readonly>1</readonly>
        </readonly>
    </profiles>

    <users>
        <default>
            <password></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>
                <ip>127.0.0.1</ip>
                <ip>192.168.163.132</ip>
            </networks>
            <profile>readonly</profile>
            <quota>default</quota>
        </zhoujy>

    </users>

    <quotas>
        <default>
            <interval>
                <duration>3600</duration>
                <queries>0</queries>
                <errors>0</errors>
                <result_rows>0</result_rows>
                <read_rows>0</read_rows>
                <execution_time>0</execution_time>
            </interval>
        </default>
    </quotas>

</yandex>
复制代码

3)读写账号:如果非要和管理账号区分的话,就限制该账号不能使用set相关的操作,使用constraints进行设置: 

<?xml version="1.0"?>
<yandex>
<profiles>
<default>
<max_memory_usage>10000000000</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>

<users>
<default>
<password></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>
<ip>127.0.0.1</ip>
<ip>192.168.163.132</ip>
</networks>
<profile>readwrite</profile>
<quota>default</quota>
</zhoujy>

</users>

<quotas>
<default>
<interval>
<duration>3600</duration>
<queries>0</queries>
<errors>0</errors>
<result_rows>0</result_rows>
<read_rows>0</read_rows>
<execution_time>0</execution_time>
</interval>
</default>
</quotas>

</yandex>
复制代码
<?xml version="1.0"?>
<yandex>
    <profiles>
        <default>
            <max_memory_usage>10000000000</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>

    <users>
        <default>
            <password></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>
                <ip>127.0.0.1</ip>
                <ip>192.168.163.132</ip>
            </networks>
            <profile>readwrite</profile>
            <quota>default</quota>
        </zhoujy>

    </users>

    <quotas>
        <default>
            <interval>
                <duration>3600</duration>
                <queries>0</queries>
                <errors>0</errors>
                <result_rows>0</result_rows>
                <read_rows>0</read_rows>
                <execution_time>0</execution_time>
            </interval>
        </default>
    </quotas>

</yandex>
复制代码

4)限制账号:限制方面有很多情况,这里逐步进行说明

4.1:限制IP访问,在users选项组里进行设置ip:

复制代码
...
            <networks incl="networks" replace="replace">
                <ip>::/0</ip>   --允许任何地址访问
                <ip>127.0.0.1</ip>  --允许本地访问
                <ip>192.168.163.132</ip> --允许该IP访问
            </networks>
...
复制代码

设置多个IP访问,还支持host、host_regexp等选项组。

4.2:限制数据库访问,在users选项组里进行设置allow_database:

...
            <allow_databases>
                <database>test</database>
            </allow_databases>
...

只允许访问test库,其他库不能使用。

4.3:限制表行访问,在users选项组里进行设置database: 

复制代码
...
            <databases>
                <test>
                    <xx>
                        <filter>id >= 500 </filter>
                    </xx>
                </test>
            </databases>
...
复制代码

只能访问test库中表xx的id大于等于500的数据。

4.4:限制一定周期内的资源使用,在quotas选项组里设置:

复制代码
...
    <quotas>
        <default>   --quotas名称
            <interval> --周期
                <duration>3600</duration>  --周期时间,单位秒
                <queries>0</queries>   --查询限制,0不限制
                <errors>0</errors>       --错误限制,0不限制
                <result_rows>0</result_rows> --返回行限制,0不限制
                <read_rows>0</read_rows>  --读取行限制,0不限制
                <execution_time>0</execution_time> --执行时间限制,0不限制
            </interval>
        </default>
    </quotas>
...
复制代码

设置好quotas之后,需要在users下的每隔用户选项组里引用,如: 

<quota>default</quota>

4.5:限制整体资源使用,需要在profiles选项组里设置:

复制代码
...
    <profiles>
        <default>
            <max_memory_usage>10000000000</max_memory_usage>  --限制查询最大使用内存
            <use_uncompressed_cache>0</use_uncompressed_cache>
            <load_balancing>random</load_balancing>
        </default>
    </profiles>
...
复制代码

查询只能使用最大10000000000 bytes的内存,还可以设置其他的参数。

5:常用模板设置

最后来配置一个日常经常使用的一个users.xml模板,大致的要求如下:

①:只读账号:能从任何IP访问的账号 zhoujy_ro

②:读写账号,不能set:只能从192.168.163.132连接的账号 zhoujy_rw

③:管理账号,能读写能set:只能从192.168.163.132、192.168.163.133连接的账号 zhoujy_admin

④:限制账号:

只能读写指定库:只能从192.168.163.132连接的账号 zhoujy_db

只能读指定库表中的行:只能从192.168.163.132连接的账号 zhoujy_tb

模板示例:

复制代码
<?xml version="1.0"?>
<yandex>
    <profiles>

        <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>

    <users>
        <default>
            <password></password>
            <networks incl="networks" replace="replace">
                <ip>::/0</ip>
            </networks>
            <profile>default</profile>
            <quota>default</quota>
        </default>

        <!--从任何IP访问的只读账号zhoujy_ro -->
        <zhoujy_ro>
            <password_double_sha1_hex>6bb4837eb74329105ee4568dda7dc67ed2ca2ad9</password_double_sha1_hex>
            <networks incl="networks" replace="replace">
                <ip>::/0</ip>
            </networks>
            <profile>readonly</profile>
            <quota>default</quota>
        </zhoujy_ro>

        <!--从指定IP访问的读写账号zhoujy_rw,指定不能set的参数 -->
        <zhoujy_rw>
            <password_double_sha1_hex>6bb4837eb74329105ee4568dda7dc67ed2ca2ad9</password_double_sha1_hex>
            <networks incl="networks" replace="replace">
                <ip>192.168.163.132</ip>
            </networks>
            <profile>readwrite</profile>
            <quota>default</quota>
        </zhoujy_rw>

        <!--从指定IP访问的管理账号 -->
        <zhoujy_admin>
            <password_double_sha1_hex>6bb4837eb74329105ee4568dda7dc67ed2ca2ad9</password_double_sha1_hex>
            <networks incl="networks" replace="replace">
                <ip>192.168.163.132</ip>
                <ip>192.168.163.133</ip>
            </networks>
            <profile>default</profile>
            <quota>default</quota>
        </zhoujy_admin>

        <!--从指定IP访问指定数据库 -->
        <zhoujy_db>
            <password_double_sha1_hex>6bb4837eb74329105ee4568dda7dc67ed2ca2ad9</password_double_sha1_hex>
            <networks incl="networks" replace="replace">
                <ip>::/0</ip>
                <ip>127.0.0.1</ip>
                <ip>192.168.163.132</ip>
            </networks>
            <profile>readwrite</profile>
            <quota>default</quota>
            <allow_databases>
                <database>test</database>
            </allow_databases>
        </zhoujy_db>

        <!--从指定IP访问指定数据库表的记录 -->
        <zhoujy_tb>
            <password_double_sha1_hex>6bb4837eb74329105ee4568dda7dc67ed2ca2ad9</password_double_sha1_hex>
            <networks incl="networks" replace="replace">
                <ip>::/0</ip>
                <ip>127.0.0.1</ip>
                <ip>192.168.163.132</ip>
            </networks>
            <profile>readonly</profile>
            <quota>default</quota>
            <allow_databases>
                <database>test</database>
            </allow_databases>
            <databases>
                <test>
                    <xx>
                        <filter>id >= 500 </filter>
                    </xx>
                </test>
            </databases>
        </zhoujy_tb>

    </users>

    <quotas>
        <default>
            <interval>
                <duration>3600</duration>
                <queries>0</queries>
                <errors>0</errors>
                <result_rows>0</result_rows>
                <read_rows>0</read_rows>
                <execution_time>0</execution_time>
            </interval>
        </default>
    </quotas>

</yandex>
复制代码

这里有个问题:如果有很多用户需要设置,该文件会很冗长,并且也不容易管理。这时可以为每个用户单独配置一个xml文件的方式,存放在/etc/clickhouse-server/users.d目录下即可:

复制代码
# cat /etc/clickhouse-server/users.d/zhoujy_rw.xml 
<yandex>
    <users>
        <zhoujy_rw>
            <password_double_sha1_hex>6bb4837eb74329105ee4568dda7dc67ed2ca2ad9</password_double_sha1_hex>
            <networks incl="networks" replace="replace">
                <ip>192.168.163.132</ip>
            </networks>
            <profile>readwrite</profile>
            <quota>default</quota>
        </zhoujy_rw>
    </users>
</yandex>
复制代码

ClickHouse对于每个配置文件,服务器在启动时会生成file-preprocessed.xml文件。这些文件包含所有已完成的替换和替代,比如上面的用户虽然用单独文件存放,但会在生成file-preprocessed.xml里会整合在一起,默认路径在:/var/lib/clickhouse/preprocessed_configs/,即实时重新加载用户和集群的设置。 这意味着可以修改群集,用户及其设置,而无需重新启动服务器,当然也可以验证配置参数是否生效。

针对配置还可以定义“替代”,如果元素具有incl属性,则文件中的相应的值将被替换、删除、追加。默认情况下,带替换文件的路径为/etc/metrika.xml。可以在配置文件(users.xml)里添加include_from元素来进行进行更改:

<include_from>/etc/clickhouse-server/metrika.xml</include_from>

如上面的配置文件,包含了【incl="networks"】,使用incl表示该参数可以通过metrika.xml文件进行替换(replace="replace")、追加(默认)、删除(remove,经过测试发现remove配置不了,后期继续关注):

复制代码
# cat /etc/clickhouse-server/metrika.xml 
<yandex>
            <networks>
                <ip>192.168.163.133</ip>
            </networks>
            <networks_admin>
                <ip>192.168.163.132</ip>
            </networks_admin>
</yandex>


# cat /etc/clickhouse-server/users.xml
...
    <users>
        <default>
            <password></password>
            <networks incl="networks_admin" repace="replace" />
            <profile>default</profile>
            <quota>default</quota>
        </default>

        <web>
            <password></password>
            <networks incl="networks">
                <ip>192.168.163.131</ip>
            </networks>
            <profile>default</profile>
            <quota>default</quota>
        </web>
    </users>
...

最终运行起来的时候生效的结果如下:
# cat /var/lib/clickhouse/preprocessed_configs/users.xml 
...
    <users>
        <default>
            <password/>
            <networks repace="replace"> 
                <ip>192.168.163.132</ip>   ---已经replace继承过来了
            </networks>
            <profile>default</profile>
            <quota>default</quota>
        </default>

        <web>
            <password/>
            <networks>
                <ip>192.168.163.131</ip>

                <ip>192.168.163.133</ip>  ---已经默认追加过来了
            </networks>
            <profile>default</profile>
            <quota>default</quota>
        </web>
    </users>
...
复制代码

关于用户相关配置大致先说明到这里,后续会持续更新。

  <password/>
            <networks>
                <ip>192.168.163.131</ip>

                <ip>192.168.163.133</ip>  ---已经默认追加过来了
            </networks>
            <profile>default</profile>
            <quota>default</quota>
        </web>
    </users>
...
复制代码

总结

      ClickHouse用户权限管理配置可以通过修改文件来管理用权限的,也可以通过RBAC(Role-Based Access Control)的访问控制管理,即通过SQL-driven,后续有文档说明。需要注意的是,在修改完权限文件之后ClickHouse不需要重启,直接会生效,所以不影响其在线服务。如果出现问题,可以直接查看其错误日志,定位问题解决即可。

posted @ 2022-02-15 11:30  渐逝的星光  阅读(1346)  评论(0编辑  收藏  举报