Clickhouse 准入控制与用户权限管理
Written By: Xinyao Tian (作者: 田昕峣)
摘要
本文档描述了 Clickhouse 集群准入控制与用户权限管理的建设及管理的基本方法。
主要建设步骤
根据 Clickhouse 官方文档中 Managing Users and Roles 的描述,建设 Clickhouse 权限机制总共可以分为如下三个步骤:
-
在 Clickhouse 集群安装完成后编辑
/etc/clickhouse-server/users.xml
创建一个account_admin
的用户,并开启该用户的SQL-driven access control
和account management
权限; -
【该步骤可省略】登录
account_admin
用户账户并创建所需要的其他用户,并额外创建一个管理员账户admin_user_account
用于后续添加和赋权其他 Clickhouse 的新建用户 (GRANT ALL ON *.* TO admin_user_account WITH GRANT OPTION
); -
关闭 Clickhouse 的默认用户
default
的SQL-driven access control
和account management
权限,并对其进行各种权限的限制; -
利用该账户对 Clickhouse 的用户及权限进行管理,可以参考 该文档
机制特点
- 管理员可以设置任何数据库和表的权限,即使这些库和表并不存在;
- 权限与数据库内的表被分开管理。也就是说,当一张表被删除时,其相应的权限并不会被自动废除;反之,如果创建一张与之前配置权限同表名的新表,
则之前表配置的全部权限仍会生效。废除权限需要通过关键字REVOKE
来显式地进行; - 目前权限没有时间限制或过期功能。
权限配置方法
Enabling SQL-driven Access Control and Account Management
配置并创建 access_control_path
Clickhouse 使用该路径内的文件进行权限的管理。该路径的默认值为 /var/lib/clickhouse/access/
,其文件为 Clickhouse 自动生成并管理。
<!-- access path default value -->
<access_control_path>/var/lib/clickhouse/access/</access_control_path>
<!--
<access_control_path>/data/clickhouse/access</access_control_path>
-->
检视该目录可以看到已经存在如下文件:
[root@p0-lpsm-rf1 access]# ls -l /var/lib/clickhouse/access/
total 20
-rw-r----- 1 clickhouse clickhouse 1 Jun 19 15:05 quotas.list
-rw-r----- 1 clickhouse clickhouse 1 Jun 19 15:05 roles.list
-rw-r----- 1 clickhouse clickhouse 1 Jun 19 15:05 row_policies.list
-rw-r----- 1 clickhouse clickhouse 1 Jun 19 15:05 settings_profiles.list
-rw-r----- 1 clickhouse clickhouse 1 Jun 19 15:05 users.list
创建 account_admin
用户开启 SQL-driven access control 和 account management 权限
默认情况下,SQL-driven access control
和 account management
对所有用户都是关闭状态。
我们需要在 /etc/clickhouse-server/users.xml
中配置 account_admin
用户并配置 access_management
, named_collection_control
,
show_named_collections
, show_named_collections_secrets
的值为 1
,配置方法如下所示:
<users>
<!-- Previous settings -->
<!-- If user name was not specified, 'default' user is used. -->
<account_admin> <!-- user_name -->
<password>gRLTzih8mUqVpa88</password>
<access_management>1</access_management>
<named_collection_control>1</named_collection_control>
<show_named_collections>1</show_named_collections>
<show_named_collections_secrets>1</show_named_collections_secrets>
<networks>
<!-- <ip>::/0</ip> -->
<ip>127.0.0.1</ip>
<ip>10.132.60.101/10.132.60.104</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
</account_admin>
<!-- Other users settings -->
</users>
注意在生产环境中,登录 ip 最好仅限定部分主机 (如同本例给出的配置方法),否则容易引起安全事故。
通过 CLI 登录 account_admin 用户
待配置完毕上述账户后,使用 CLickhouse-Client 登录 account_admin
用户:
[root@p0-lpsm-rf1 clickhouse-server]# clickhouse-client --user=account_admin --password --host=10.132.60.101
ClickHouse client version 22.3.2.1.
Password for user (account_admin):
Connecting to localhost:9000 as user account_admin.
Connected to ClickHouse server version 22.3.2 revision 54455.
p0-lpsm-rf1 :) SHOW ACCESS
SHOW ACCESS
Query id: ff4fef47-7378-46f3-b0b5-f352d7e9258d
┌─ACCESS────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ CREATE USER account_admin IDENTIFIED WITH plaintext_password SETTINGS PROFILE default │
│ CREATE USER default IDENTIFIED WITH plaintext_password SETTINGS PROFILE default │
│ CREATE SETTINGS PROFILE default SETTINGS max_memory_usage = 10000000000, load_balancing = 'random' │
│ CREATE SETTINGS PROFILE readonly SETTINGS readonly = 1 │
│ CREATE QUOTA default KEYED BY user_name FOR INTERVAL 1 hour TRACKING ONLY TO account_admin, default │
│ GRANT ALL ON *.* TO account_admin WITH GRANT OPTION │
│ GRANT SHOW, SELECT, INSERT, ALTER, CREATE, DROP, TRUNCATE, OPTIMIZE, KILL QUERY, MOVE PARTITION BETWEEN SHARDS, SYSTEM, dictGet, INTROSPECTION, SOURCES ON *.* TO default │
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
7 rows in set. Elapsed: 0.001 sec.
限制 default 账户的权限
Clickhouse 集群安装时自动创建的 default 用户拥有很大的权限,因此需要对其进行限制以免其他用户登入。
此处,我们使用 IP 的方式限制其登录,使用本机 IP 限制其只能通过本机进行登录访问。
<users>
<!-- Previous settings -->
<default> <!-- user_name -->
<password></password>
<!-- many other configurations -->
<networks>
<ip>127.0.0.1</ip>
<ip>10.132.60.101/10.132.60.104</ip>
</networks>
<!-- many other configurations -->
</default>
<account_admin> <!-- user_name -->
<password>gRLTzih8mUqVpa88</password>
<!-- ... -->
<networks>
<ip>127.0.0.1</ip>
<ip>10.132.60.101/10.132.60.104</ip>
</networks>
<!-- ... -->
</account_admin>
</users>
利用 account_admin 账户管理用户和权限
授权操作语法:
GRANT [ON CLUSTER cluster_name] privilege[(column_name [,...])] [,...] ON {db.table|db.*|*.*|table|*} TO {user | role | CURRENT_USER} [,...] [WITH GRANT OPTION] [WITH REPLACE OPTION]
Clickhouse 单节点权限管理
创建管理员用户
【由于上述步骤已经在 config.xml 中创建了相应账户,故本创建管理员用户步骤省略】
创建 SQL 管理员账户:
CREATE USER clickhouse_admin IDENTIFIED BY 'password';
给予该用户全部管理员权限:
GRANT ALL ON *.* TO clickhouse_admin WITH GRANT OPTION;
创建新用户及测试用库和表
使用具有管理权限的用户 account_admin
创建一个测试用户 test_user
:
CREATE USER test_user IDENTIFIED BY 'password';
更改用户的密码:
ALTER USER test_user IDENTIFIED BY '123456';
创建测试数据库 test_auth_db
:
CREATE DATABASE test_auth_db;
创建一张测试表 test_auth_db.test_table_01
:
CREATE TABLE test_auth_db.test_table_01 (id UInt64, column1 String) ENGINE = MergeTree() ORDER BY id;
赋予用户权限
使用管理员账户赋予 test_user
用户 test_auth_db
数据库下所有表的增删改查权限:
GRANT CREATE TABLE ON test_auth_db.* TO test_user;
GRANT DROP TABLE ON test_auth_db.* TO test_user;
GRANT ALTER ON test_auth_db.* TO test_user;
GRANT SELECT ON test_auth_db.* TO test_user;
检视某用户的权限赋予情况:
SHOW GRANTS FOR test_user;
检视结果如下所示:
p0-lpsm-rf1 :) SHOW GRANTS FOR test_user;
SHOW GRANTS FOR test_user
Query id: d83069d4-7d12-48a9-a39f-b547e4bb6e45
┌─GRANTS FOR test_user─────────────────────────────────────────────────────────┐
│ GRANT SELECT, ALTER, CREATE TABLE, DROP TABLE ON test_auth_db.* TO test_user │
└──────────────────────────────────────────────────────────────────────────────┘
1 rows in set. Elapsed: 0.001 sec.
收回用户权限
使用管理员账户运行如下语句即可收回赋予 test_user
的各种权限:
REVOKE CREATE TABLE ON test_auth_db.* FROM test_user;
REVOKE DROP TABLE ON test_auth_db.* FROM test_user;
REVOKE ALTER ON test_auth_db.* FROM test_user;
REVOKE SELECT ON test_auth_db.* FROM test_user;
检视 test_user
的各项权限:
p0-lpsm-rf1 :) SHOW GRANTS FOR test_user;
SHOW GRANTS FOR test_user
Query id: 0ffa2a80-d80d-4be7-be4a-53469c2144a5
Ok.
0 rows in set. Elapsed: 0.001 sec.
Clickhouse 集群权限管理
Clickhouse 集群的用户权限管理与单节点大同小异,但是具体的语句上存在细微的差别。
此处,我们以一个名为 production_cluster_3s2r
的 Clickhouse Cluster 为例进行讲解。
登录 Clickhouse 集群管理员账户
使用如下命令登录 Clickhouse 的管理员权限:
[useradmin@p0-lpsm-rf1 ~]$ clickhouse-client --user=account_admin --password --host=10.132.60.101
ClickHouse client version 22.3.2.1.
Connecting to 10.132.60.101:9000 as user account_admin.
Connected to ClickHouse server version 22.3.2 revision 54455.
在集群上创建用户
集群级别用户创建:
CREATE USER psmuseretl IDENTIFIED BY '123456' ON CLUSTER production_cluster_3s2r;
集群级别修改用户密码:
ALTER USER psmuseretl IDENTIFIED BY '123123' ON CLUSTER production_cluster_3s2r;
在集群上赋予用户权限
在集群级别创建 Clickhouse 用户:
p0-lpsm-rf1 :) CREATE USER psmuserdev IDENTIFIED BY '123456' ON CLUSTER production_cluster_3s2r;
CREATE USER psmuserdev ON CLUSTER production_cluster_3s2r IDENTIFIED WITH sha256_hash BY 'B648CDD0C5F4C9B41F8E7E660B1389CB8DEA33E32E12E4D7096205ED77337C7F'
Query id: acd3d2ab-fc62-47fe-be52-7a58300b3c0e
┌─host────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ p0-lpsm-rf2 │ 9000 │ 0 │ │ 5 │ 0 │
│ p0-lpsm-rf2 │ 9100 │ 0 │ │ 4 │ 0 │
│ p0-lpsm-rf1 │ 9000 │ 0 │ │ 3 │ 0 │
│ p0-lpsm-rf3 │ 9000 │ 0 │ │ 2 │ 0 │
│ p0-lpsm-rf1 │ 9100 │ 0 │ │ 1 │ 0 │
│ p0-lpsm-rf3 │ 9100 │ 0 │ │ 0 │ 0 │
└─────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
6 rows in set. Elapsed: 0.191 sec.
给予用户集群内部节点互通权限:
p0-lpsm-rf1 :) GRANT REMOTE ON *.* TO psmuserdev ON CLUSTER production_cluster_3s2r;
GRANT ON CLUSTER production_cluster_3s2r REMOTE ON *.* TO psmuserdev
Query id: d49a490a-3d49-404a-bd28-a05037b64a3a
┌─host────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ p0-lpsm-rf2 │ 9000 │ 0 │ │ 5 │ 0 │
│ p0-lpsm-rf2 │ 9100 │ 0 │ │ 4 │ 0 │
│ p0-lpsm-rf1 │ 9000 │ 0 │ │ 3 │ 0 │
│ p0-lpsm-rf3 │ 9000 │ 0 │ │ 2 │ 0 │
│ p0-lpsm-rf1 │ 9100 │ 0 │ │ 1 │ 0 │
│ p0-lpsm-rf3 │ 9100 │ 0 │ │ 0 │ 0 │
└─────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
6 rows in set. Elapsed: 0.140 sec.
给予用户某数据库的建表和删表权限:
p0-lpsm-rf1 :) GRANT CREATE TABLE, DROP TABLE ON tklpsm.* TO psmuserdev ON CLUSTER production_cluster_3s2r;
GRANT ON CLUSTER production_cluster_3s2r CREATE TABLE, DROP TABLE ON tklpsm.* TO psmuserdev
Query id: 7fd496dd-173d-4d8e-a83f-d7d2d568ae25
┌─host────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ p0-lpsm-rf2 │ 9000 │ 0 │ │ 5 │ 0 │
│ p0-lpsm-rf2 │ 9100 │ 0 │ │ 4 │ 0 │
│ p0-lpsm-rf1 │ 9000 │ 0 │ │ 3 │ 0 │
│ p0-lpsm-rf3 │ 9000 │ 0 │ │ 2 │ 0 │
│ p0-lpsm-rf3 │ 9100 │ 0 │ │ 1 │ 0 │
│ p0-lpsm-rf1 │ 9100 │ 0 │ │ 0 │ 0 │
└─────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
6 rows in set. Elapsed: 0.114 sec.
给予用户某数据库的增删改查和权限:
p0-lpsm-rf1 :) GRANT INSERT, DELETE, ALTER, SELECT ON tklpsm.* TO psmuserdev ON CLUSTER production_cluster_3s2r;
GRANT ON CLUSTER production_cluster_3s2r INSERT, ALTER DELETE, ALTER, SELECT ON tklpsm.* TO psmuserdev
Query id: 7005edd6-17aa-461b-bfd0-65c29f73337b
┌─host────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ p0-lpsm-rf2 │ 9000 │ 0 │ │ 5 │ 0 │
│ p0-lpsm-rf2 │ 9100 │ 0 │ │ 4 │ 0 │
│ p0-lpsm-rf1 │ 9000 │ 0 │ │ 3 │ 0 │
│ p0-lpsm-rf3 │ 9000 │ 0 │ │ 2 │ 0 │
│ p0-lpsm-rf1 │ 9100 │ 0 │ │ 1 │ 0 │
│ p0-lpsm-rf3 │ 9100 │ 0 │ │ 0 │ 0 │
└─────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
6 rows in set. Elapsed: 0.119 sec.
利用管理员账户检视某用户的权限:
p0-lpsm-rf1 :) SHOW GRANTS FOR psmuserdev
SHOW GRANTS FOR psmuserdev
Query id: 15cbb7cb-44cf-40aa-ac5e-b41a9d196401
┌─GRANTS FOR psmuserdev───────────────────────────────────────────────────────────┐
│ GRANT REMOTE ON *.* TO psmuserdev │
│ GRANT CREATE TABLE, CREATE VIEW, CREATE DICTIONARY ON CHAOTI.* TO psmuserdev │
│ GRANT SELECT, INSERT, ALTER, CREATE TABLE, DROP TABLE ON tklpsm.* TO psmuserdev │
└─────────────────────────────────────────────────────────────────────────────────┘
收回某用户的相应权限:
p0-lpsm-rf1 :) REVOKE CREATE DATABASE, DROP TABLE ON CHAOTI.* FROM psmuserdev ON CLUSTER production_cluster_3s2r;
REVOKE ON CLUSTER production_cluster_3s2r CREATE DATABASE, DROP TABLE ON CHAOTI.* FROM psmuserdev
Query id: 310505f1-c2a6-4125-b4ca-e373492e715a
┌─host────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ p0-lpsm-rf2 │ 9000 │ 0 │ │ 5 │ 0 │
│ p0-lpsm-rf2 │ 9100 │ 0 │ │ 4 │ 0 │
│ p0-lpsm-rf1 │ 9000 │ 0 │ │ 3 │ 0 │
│ p0-lpsm-rf3 │ 9000 │ 0 │ │ 2 │ 0 │
│ p0-lpsm-rf1 │ 9100 │ 0 │ │ 1 │ 0 │
│ p0-lpsm-rf3 │ 9100 │ 0 │ │ 0 │ 0 │
└─────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
6 rows in set. Elapsed: 0.117 sec.
小结
本文档详细描述了 Clickhouse 权限机制的建设方法并给出了详细的操作步骤。
References
Appendix i 常用权限赋予语句示例
如下为常用的集群级别权限赋予语句的示例:
-- CREATE USER tklbidev
CREATE USER tklbidev IDENTIFIED BY 'old_password' ON CLUSTER production_cluster_3s2r;
-- ALTER USER tklbidev
ALTER USER tklbidev IDENTIFIED BY 'new_password' ON CLUSTER production_cluster_3s2r;
-- Create Database
CREATE DATABASE bigscreen ON CLUSTER production_cluster_3s2r;
-- Grant Cluster Usage Permission
GRANT REMOTE ON *.* TO tklbidev ON CLUSTER production_cluster_3s2r;
-- Grant Permissions
GRANT CREATE TABLE, DROP TABLE, TRUNCATE ON bigscreen.* TO tklbidev ON CLUSTER production_cluster_3s2r;
GRANT INSERT, DELETE, ALTER, SELECT ON bigscreen.* TO tklbidev ON CLUSTER production_cluster_3s2r;
-- REVOKE Permissions
REVOKE CREATE DATABASE, DROP TABLE ON CHAOTI.* FROM psmuserdev ON CLUSTER production_cluster_3s2r;
-- Check Perssions
SHOW GRANTS FOR tklbidev