更多精彩內容,請關注微信公眾號:后端技術小屋
原文:https://altinity.com/blog/integrating-clickhouse-with-ldap-part-one
作者:Vitaliy Zakaznikov
ClickHouse上一般使用XML文件來定義配置,其中包括用戶配置。users.xml
文件或在/etc/clickhouse-server/users.d
目錄中的配置文件都可用於定義用戶及其相關屬性,例如profile
、network restriction
、quota
和password
。這種方案在集群規模較小時比較有效,但是用來管理大規模集群卻很費勁。主要存在三個主要問題:首先每次必須添加、修改或刪除用戶時,管理員必須手動編輯這些配置文件;其次,將密碼和哈希值直接存儲在用戶配置文件中存在安全隱患;第三,為用戶分配和管理角色是非常繁瑣的。
ClickHouse現在已經解決了以上三個問題。通過引入對RBAC的支持,ClickHouse允許使用SQL語句管理用戶和角色,而無需修改配置文件。但是即使使用RBAC
,您仍然需要與組織內的其他服務分別管理用戶和角色,相互之間無法打通,且密碼仍然存儲在文件系統中。
自2020年中以來,Altinity一直在努力添加ClickHouse對輕型目錄訪問協議(也稱為LDAP)的支持。LDAP集中存儲用戶、密碼及其在組織中角色,從而使得管理用戶和權限的功能集中到一個地方。我們很高興地宣布,ClickHouse支持LDAP身份驗證和用戶目錄的特性已被合入社區,目前運行穩定且通用。我們已使用大多數Linux發行版中提供的常用OpenLDAP軟件包對其進行了仔細的測試。
在這一系列博客文章中,我們將描述對LDAP集成的新支持如何幫助中大型組織將ClickHouse用戶角色管理與其現有服務集成在一起。我們將介紹LDAP與Clickhouse的幾種不同程度的集成,從使用LDAP驗證ClickHouse用戶,到通過外部用戶目錄完全集成LDAP並將選定的LDAP組映射到RBAC中的角色。
測試環境
我們使用docker-compose集群來展示LDAP如何與ClickHouse集成。您可以在https://gitlab.com/altinity-public/blogs/ldap-integration-with-clickhouse上找到docker-compose環境,該環境中使用了yandex/clickhouse-server:21.1.2.15鏡像
要使用該環境,需要在系統上安裝git
,docker
和docker-compose
。然后將包含測試環境的代碼庫克隆到本地。
git clone https://gitlab.com/altinity-public/blogs/ldap-integration-with-clickhouse.git
檢查是否可以啟動docker-compose集群。
cd ldap-integration-with-clickhouse
cd docker-compose/
docker-compose up -d
Creating network "docker-compose_default" with the default driver
Creating docker-compose_openldap1_1 ... done
Creating docker-compose_zookeeper_1 ... done
Creating docker-compose_clickhouse1_1 ... done
Creating docker-compose_clickhouse3_1 ... done
Creating docker-compose_clickhouse2_1 ... done
Creating phpldapadmin ... done
Creating docker-compose_all_services_ready_1 ... done
如果啟動成功會看到上面的日志,表明openldap1
,zookeeper
,clickhouse1
,clickhouse2
,clickhouse3
和phpldapadmin
這些服務已經正常運行。我們還可檢查所有服務是否健康。
請注意,您必須執行
docker-compose
目錄下的所有docker-compose命令
docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------------------------------------
docker-compose_all_services_ready_1 /hello Exit 0
docker-compose_clickhouse1_1 bash -c clickhouse server ... Up (healthy) 8123/tcp, 9000/tcp, 9009/tcp
docker-compose_clickhouse2_1 bash -c clickhouse server ... Up (healthy) 8123/tcp, 9000/tcp, 9009/tcp
docker-compose_clickhouse3_1 bash -c clickhouse server ... Up (healthy) 8123/tcp, 9000/tcp, 9009/tcp
docker-compose_openldap1_1 /container/tool/run --copy ... Up (healthy) 389/tcp, 636/tcp
docker-compose_zookeeper_1 /docker-entrypoint.sh zkSe ... Up (healthy) 2181/tcp, 2888/tcp, 3888/tcp
phpldapadmin /container/tool/run Up (healthy) 443/tcp, 0.0.0.0:8080->80/tcp
健全性檢查
在繼續之前我們做一些必要的健全性檢查。首先,確保我們的OpenLDAP Server已啟動並正在運行。我們可以執行搜索操作以查看在LDAP Server上定義好的用戶
再次注意,您必須執行
docker-compose
目錄下的所有docker-compose命令。
docker-compose exec openldap1 bash -c 'ldapsearch -x -H ldap://localhost -b "ou=users,dc=company,dc=com" -D "cn=admin,dc=company,dc=com" -w admin'
# extended LDIF
#
# LDAPv3
# base <ou=users,dc=company,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# users, company.com
dn: ou=users,dc=company,dc=com
objectClass: organizationalUnit
objectClass: top
ou: users
# ldapuser, users, company.com
dn: cn=ldapuser,ou=users,dc=company,dc=com
cn: ldapuser
gidNumber: 501
givenName: John
homeDirectory: /home/users/ldapuser
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
sn: User
uid: ldapuser
uidNumber: 1002
userPassword:: bGRhcHVzZXI=
# search result
search: 2
result: 0 Success
# numResponses: 3
# numEntries: 2
可以看到,我們已經定義了一個用戶:cn=ldapuser,ou=users,dc=company,dc=com
。ldapsearch
返回的數據中,ldapuser
為用戶名,密碼設置為與用戶名相同(僅用於測試)。
其次,確保ClickHouse服務能夠正常執行查詢。
docker-compose exec clickhouse1 bash -c 'clickhouse-client -q "SELECT version()"'
docker-compose exec clickhouse2 bash -c 'clickhouse-client -q "SELECT version()"'
docker-compose exec clickhouse3 bash -c 'clickhouse-client -q "SELECT version()"'
在ClickHouse中配置LDAP服務器
在將LDAP與ClickHouse進行集成之前,需要讓ClickHouse知道哪里有可用的LDAP服務器以及如何連接它,Clickhouse甚至還可以添加多個LDAP Server的配置。為簡單起見,我們將僅使用在docker-compose集群中的openldap1
環境。接下來將配置文件添加到/etc/clickhouse-server/config.d
目錄中,以配置LDAP Server。
docker-compose exec clickhouse1 bash -c 'cat <<HEREDOC > /etc/clickhouse-server/config.d/ldap_servers.xml
<?xml version="1.0" encoding="utf-8"?>
<yandex>
<ldap_servers>
<!--LDAP servers b9f1f80c_6598_11eb_80c1_39d7fbdc1e26-->
<openldap1>
<host>openldap1</host>
<port>636</port>
<enable_tls>yes</enable_tls>
<auth_dn_prefix>cn=</auth_dn_prefix>
<auth_dn_suffix>,ou=users,dc=company,dc=com</auth_dn_suffix>
<tls_require_cert>never</tls_require_cert>
</openldap1>
</ldap_servers>
</yandex>
HEREDOC'
接着檢查ldap_servers.xml
中的配置是否已合並到預處理的config.xml
文件中。
docker-compose exec clickhouse1 bash -c 'cat /var/lib/clickhouse/preprocessed_configs/config.xml | grep LDAP'
<!--LDAP servers b9f1f80c_6598_11eb_80c1_39d7fbdc1e26-->
可以看到唯一標識字符串已經在預處理的config.xml
文件中,說明LDAP Server配置已被Clickhouse成功加載。
使用LDAP驗證ClickHouse用戶
ClickHouse與LDAP的第一級集成是允許使用LDAP Server對ClickHouse用戶進行身份驗證。這樣我們就不必在Clickhouse中為用戶明確指定密碼,而是讓ClickHouse請求LDAP Server進行用戶身份驗證。
在users.xml中定義經過LDAP Server驗證的用戶
我們可將對應的配置文件添加到/etc/clickhouse-server/users.d
目錄中以新建Clickhouse用戶,而不需要在配置中為其指定密碼,轉而用LDAP Server配置代替之。
docker-compose exec clickhouse1 bash -c 'cat <<HEREDOC > /etc/clickhouse-server/users.d/ldapuser.xml
<?xml version="1.0" encoding="utf-8"?>
<yandex>
<users>
<!--LDAP users bb6f3d71_6598_11eb_80c1_39d7fbdc1e26-->
<ldapuser>
<ldap>
<server>openldap1</server>
</ldap>
</ldapuser>
</users>
</yandex>
HEREDOC'
確認新增用戶配置已合並到預處理的users.xml
中。
$ docker-compose exec clickhouse1 bash -c 'cat /var/lib/clickhouse/preprocessed_configs/users.xml | grep bb6f3d71_6598_11eb_80c1_39d7fbdc1e26'
<!--LDAP users bb6f3d71_6598_11eb_80c1_39d7fbdc1e26-->
現在我們使用ldapuser
用戶執行查詢。
docker-compose exec clickhouse1 bash -c 'clickhouse-client -n --user "ldapuser" --password "ldapuser" -q "SELECT user()"'
ldapuser
有效了!現在我們試試用錯誤密碼登錄會不會驗證失敗?
docker-compose exec clickhouse1 bash -c 'clickhouse-client -n --user "ldapuser" --password "ldapuser2" -q "SELECT user()"'
Code: 516. DB::Exception: Received from localhost:9000. DB::Exception: ldapuser: Authentication failed: password is incorrect or there is no user with such name.
刪除用戶的配置文件,接下來我們改用RBAC定義Clickhouse用戶
docker-compose exec clickhouse1 bash -c 'rm -rf /etc/clickhouse-server/users.d/ldapuser.xml'
使用RBAC定義經過LDAP Server驗證的用戶
在Clickhouse中,除XML配置文件之外,我們還可使用RBAC命令以更簡單的方式定義用戶。我們建議使用RBAC命令,因為您可使用ON CLUSTER
語句在整個Clickhouse集群上創建或刪除用戶。
CREATE USER命令的語法定義如下。
CREATE USER [IF NOT EXISTS | OR REPLACE] name1 [ON CLUSTER cluster_name1]
[, name2 [ON CLUSTER cluster_name2] ...]
[IDENTIFIED [WITH {NO_PASSWORD|PLAINTEXT_PASSWORD|SHA256_PASSWORD|SHA256_HASH|DOUBLE_SHA1_PASSWORD|DOUBLE_SHA1_HASH}] BY {'password'|'hash'}]
[HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
[DEFAULT ROLE role [,...]]
[SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
現在您還可以使用IDENTIFIED WITH LDAP_SERVER
語句,綁定LDAP Server對該用戶進行身份驗證。
docker-compose exec clickhouse1 bash -c 'clickhouse-client -q "CREATE USER ldapuser IDENTIFIED WITH LDAP_SERVER BY '\''openldap1'\''"'
檢查用戶是否創建成功
docker-compose exec clickhouse1 bash -c 'clickhouse-client -q "SHOW USERS"'
default
ldapuser
使用ldapuser
用戶執行查詢。
docker-compose exec clickhouse1 bash -c 'clickhouse-client -n --user "ldapuser" --password "ldapuser" -q "SELECT user()"'
ldapuser
使用錯誤密碼登錄看看會不會報錯
docker-compose exec clickhouse1 bash -c 'clickhouse-client -n --user "ldapuser" --password "ldapuser2" -q "SELECT user()"'
Code: 516. DB::Exception: Received from localhost:9000. DB::Exception: ldapuser: Authentication failed: password is incorrect or there is no user with such name.
在集群中使用RBAC定義經過LDAP Server驗證的用戶
RBAC命令允許在群集上創建或刪除用戶。現在我們將LDAP Server配置添加到其他兩個ClickHouse節點:clickhouse2
和clickhouse3
中
首先,將LDAP Server配置添加到clickhouse2
中
docker-compose exec clickhouse2 bash -c 'cat <<HEREDOC > /etc/clickhouse-server/config.d/ldap_servers.xml
<?xml version="1.0" encoding="utf-8"?>
<yandex>
<ldap_servers>
<!--LDAP servers b9f1f80c_6598_11eb_80c1_39d7fbdc1e26-->
<openldap1>
<host>openldap1</host>
<port>636</port>
<enable_tls>yes</enable_tls>
<auth_dn_prefix>cn=</auth_dn_prefix>
<auth_dn_suffix>,ou=users,dc=company,dc=com</auth_dn_suffix>
<tls_require_cert>never</tls_require_cert>
</openldap1>
</ldap_servers>
</yandex>
HEREDOC'
對clickhouse3
也進行同樣的操作
docker-compose exec clickhouse3 bash -c 'cat <<HEREDOC > /etc/clickhouse-server/config.d/ldap_servers.xml
<?xml version="1.0" encoding="utf-8"?>
<yandex>
<ldap_servers>
<!--LDAP servers b9f1f80c_6598_11eb_80c1_39d7fbdc1e26-->
<openldap1>
<host>openldap1</host>
<port>636</port>
<enable_tls>yes</enable_tls>
<auth_dn_prefix>cn=</auth_dn_prefix>
<auth_dn_suffix>,ou=users,dc=company,dc=com</auth_dn_suffix>
<tls_require_cert>never</tls_require_cert>
</openldap1>
</ldap_servers>
</yandex>
HEREDOC'
現在,我們將ON CLUSTER
子句添加到CREATE USER
命令中,在集群上創建ldapuser
用戶
docker-compose exec clickhouse1 bash -c 'clickhouse-client -q "CREATE USER IF NOT EXISTS ldapuser IDENTIFIED WITH LDAP_SERVER BY '\''openldap1'\'' ON CLUSTER '\''replicated_cluster'\''"'
clickhouse2 9000 0 2 0
clickhouse1 9000 0 1 0
clickhouse3 9000 0 0 0
現在,我們以ldapuser
用戶登錄到集群的每個節點上執行命令。
docker-compose exec clickhouse1 bash -c 'clickhouse-client -n --user "ldapuser" --password "ldapuser" -q "SELECT user()"'
docker-compose exec clickhouse2 bash -c 'clickhouse-client -n --user "ldapuser" --password "ldapuser" -q "SELECT user()"'
docker-compose exec clickhouse3 bash -c 'clickhouse-client -n --user "ldapuser" --password "ldapuser" -q "SELECT user()"'
優化LDAP身份驗證用戶的登錄
在使用LDAP Server對用戶進行身份驗證后,每次用戶登錄Clickhouse時,ClickHouse都必須請求LDAP Server來對該用戶進行驗證。當許多用戶都需要身份驗證時,這可能不是最佳選擇。為了解決此問題,我們可在Clickhouse的LDAP Server配置中使用<verification_cooldown>
參數,該參數指定一次成功登錄之后的時間(單位:秒):在此期間,對於連續請求中的用戶,我們將假定其已被成功驗證, 這樣就無需每次都請求LDAP Server。默認情況下,此參數為0,表示禁用緩存,即每次用戶登錄時Clickhouse都會請求LDAP Server進行身份驗證。
當前緩存已被禁用。我們在clickhouse1
上進行基准測試:
docker-compose exec clickhouse1 bash -c 'time for n in {1..1000}; do clickhouse-client -n --user "ldapuser" --password "ldapuser" -q "SELECT 1" > /dev/null; done'
real 0m30.189s
user 0m14.492s
sys 0m9.847s
接着我們在clickhouse1
上更改<verification_cooldown>
參數,改成5分鍾
docker-compose exec clickhouse1 bash -c 'cat <<HEREDOC > /etc/clickhouse-server/config.d/ldap_servers.xml
<?xml version="1.0" encoding="utf-8"?>
<yandex>
<ldap_servers>
<!--LDAP servers b9f1f80c_6598_11eb_80c1_39d7fbdc1e26-->
<openldap1>
<host>openldap1</host>
<port>636</port>
<enable_tls>yes</enable_tls>
<verification_cooldown>300</verification_cooldown>
<auth_dn_prefix>cn=</auth_dn_prefix>
<auth_dn_suffix>,ou=users,dc=company,dc=com</auth_dn_suffix>
<tls_require_cert>never</tls_require_cert>
</openldap1>
</ldap_servers>
</yandex>
HEREDOC'
啟用緩存之后,基准測試結果如下:
docker-compose exec clickhouse1 bash -c 'time for n in {1..1000}; do clickhouse-client -n --user "ldapuser" --password "ldapuser" -q "SELECT 1" > /dev/null; done'
real 0m22.472s
user 0m12.000s
sys 0m8.894s
如上所示,通過降低Clickhouse重復請求LDAP Server進行身份驗證的開銷,我們使用戶登錄性能提高了約26%。
結論
在本文中,我們介紹了對LDAP與ClickHouse集成的支持。我們研究了如何將LDAP Server配置添加到ClickHouse中。我們還研究了最簡單的情況,即使用LDAP Sever對Clickhouse中定義的用戶進行身份驗證,無論用戶是管理員通過XML文件或RBAC命令配置的。RBAC命令提供對ON CLUSTER
語句的支持,有了ON CLUSTER
可在整個集群上創建或刪除用戶,而無需修改集群中每個節點的配置文件。最后,我們研究了如何啟用LDAP用戶身份驗證的緩存以優化用戶重復登錄Clickhouse的性能。
請繼續關注下一部分,我們將討論如何將LDAP Server用作外部用戶目錄,從而無需在ClickHouse中定義用戶。如果您還有其他疑問或想討論您的安全需求,請隨時通過info@altinity.com與我們聯系。我們很樂意為您提供幫助!
推薦閱讀
- 一文讀懂clickhouse集群監控
- 30分鍾入門Vim
- 30分鍾入門GDB
- STL源碼分析--vector
- zookeeper client原理總結
- redis實現分布式鎖
- 推薦幾個好用的效率神器
- C/C++關鍵字之restrict
- 現代C++之右值語義
- Python亂碼九問
- Linux Shell腳本攻略讀書筆記
更多精彩內容,請掃碼關注微信公眾號:后端技術小屋。如果覺得文章對你有幫助的話,請多多分享、轉發、在看。