例子:
<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的数据。
查询可以分为以下几种类型:
- 读:SELECT,SHOW,DESCRIBE,EXISTS
- 写:INSERT,OPTIMIZE。
- DDL:CREATE,ALTER,RENAME,ATTACH,DETACH,DROP TRUNCATE。
- 设置:SET,USE。
- KILL
以上的权限通过配置标签来控制:
readonly :读权限、写权限和设置权限,由此标签控制,它有三种取值:
当设置readonly=1后,用户将无法在当前会话中更改readonly和allow_ddl设置;也可以通过约束来限制更改权限。
allow_ddl:DDL权限由此标签控制,它有两种取值:
-
当取值为0时,不允许DDL查询;
-
当取值为1时,允许DDL查询(默认值)
如果当前会话的allow_ddl = 0,则无法执行SET allow_ddl = 1
注意:KILL QUERY可以在任何设置上执行,readonly和allow_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里引用,继承这些参数的限制。
访问权限在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>
View Code
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>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>
View Code
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>
View Code
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下的每隔用户选项组里引用,如:
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>
<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>
<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>
<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>
<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>
<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>
…
关于用户相关配置大致先说明到这里,后续会持续更新。
总结
ClickHouse用户权限管理配置完全不同于MySQL数据库,其是通过修改文件来管理用权限的,本文只对一些常用的场景进行说明,后续遇到复杂情况,也会定期更新。特别需要注意的是,在修改完权限文件之后ClickHouse不需要重启,直接会生效,所以不影响其在线服务。如果出现问题,可以直接查看其错误日志,定位问题解决即可。