zookeeper權限控制 ACL
zookeeper類似於文件系統,client可以創建、更新、刪除節點。但是如何做到節點的權限控制呢,zookeeper提供了access control list訪問控制列表。ACL 權限可以針對節點設置相關讀寫等權限,保障數據安全性。permissions 可以指定不同的權限范圍及角色。
ACL權限控制,通過 [scheme:id:permissions] 來構成權限列表。
- 權限模式(schema):授權的策略,采用的某種權限機制,包括 world、auth、digest、ip、super 幾種。
- 授權對象(id):授權的對象,代表允許訪問的用戶
- 權限(permission):授予的權限,由 cdrwa 組成,其中每個字母代表支持不同權限, 創建權限 create(c)、刪除權限 delete(d)、讀權限 read(r)、寫權限 write(w)、管理權限admin(a)。
ACL特性
- zookeeper的權限控制是基於每個znode節點的,需要對每個節點設置權限
- 每個znode支持多種權限控制方案和多個權限
- 子節點不會繼承父節點的權限,客戶端無權訪問某節點,但可能可以訪問它的子節點
權限模式
方案 | 描述 |
world | 只有一個用戶:anyone,代表登錄zookeeper的所有人(默認) |
ip | 對客戶端使用ip地址認證 |
auth | 使用已添加的用戶認證 |
digest | 使用"用戶名:密碼"方式認證 |
授權對象
給誰授予權限,授權對象ID是指權限賦予的實體,例如:IP地址或用戶
授予的權限
create、delete、read、writer、admin也就是增、刪、改、查、管理權限,這5種權限簡寫為cdrwa。這5種權限中,delete是指對子節點的刪除權限,其他4種權限是指對自身節點的操作權限。
權限 | ACL簡寫 | 描述 |
create | c | 可以創建子節點 |
delete | d | 可以刪除子節點(僅下一級節點) |
read | r | 可以讀取節點數據及顯示子節點列表 |
write | w | 可以設置節點數據 |
admin | a | 可以設置節點訪問控制列表權限 |
授權的相關命令
命令 | 使用方式 | 描述 |
getAcl | getAcl [-s] path | 讀取ACL權限 |
setAcl | setAcl [-s] [-v version] [-R] path acl | 設置ACL權限 |
addauth | addauth schema auth | 添加認證用戶 |
案例演示
world授權模式
world代表開放式權限,即創建節點的默認權限。
[zk: localhost:2181(CONNECTED) 10] getAcl /node1 'world,'anyone : cdrwa # 刪除c權限,創建子節點失敗 [zk: localhost:2181(CONNECTED) 12] setAcl /node1 world:anyone:drwa [zk: localhost:2181(CONNECTED) 14] create /node1/node13 "node13" Insufficient permission : /node1/node13 # 刪除d權限,刪除子節點失敗 [zk: localhost:2181(CONNECTED) 15] setAcl /node1 world:anyone:rwa [zk: localhost:2181(CONNECTED) 16] delete /node1/node12 Insufficient permission : /node1/node12 # 刪除r權限,獲取節點數據失敗,且讀取子節點列表失敗 [zk: localhost:2181(CONNECTED) 17] setAcl /node1 world:anyone:wa [zk: localhost:2181(CONNECTED) 18] get /node1 org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /node1 [zk: localhost:2181(CONNECTED) 40] ls /node1 Insufficient permission : /node1 # 刪除w權限,修改節點數據失敗 [zk: localhost:2181(CONNECTED) 20] setAcl /node1 world:anyone:a [zk: localhost:2181(CONNECTED) 21] set /node1 "node1234" Insufficient permission : /node1 # 刪除a權限,查看設置權限管理失敗 [zk: localhost:2181(CONNECTED) 22] setAcl /node1 world:anyone: [zk: localhost:2181(CONNECTED) 23] getAcl /node1 Insufficient permission : /node1
ip授權模式
限制 IP 地址的訪問權限
[zk: localhost:2181(CONNECTED) 2] create /node2 "node2" Created /node2 [zk: localhost:2181(CONNECTED) 3] setAcl /node2 ip:127.0.0.1:crdwa [zk: localhost:2181(CONNECTED) 4] getAcl /node2 'ip,'127.0.0.1 : cdrwa [zk: localhost:2181(CONNECTED) 5] get /node2 node2 [zk: localhost:2181(CONNECTED) 6] setAcl /node2 ip:192.168.126.3:crdwa [zk: localhost:2181(CONNECTED) 7] getAcl /node2 Insufficient permission : /node2 # 同時給多個ip地址賦權 [zk: localhost:2181(CONNECTED) 10] setAcl /node3 ip:192.168.126.3:crdwa,ip:127.0.0.1:crdwa [zk: localhost:2181(CONNECTED) 11] getAcl /node3 'ip,'192.168.126.3 : cdrwa 'ip,'127.0.0.1 : cdrwa
auth授權模式
auth 用於授予權限,注意需要先創建用戶。
[zk: localhost:2181(CONNECTED) 16] create /node3 Created /node3 [zk: localhost:2181(CONNECTED) 17] addauth digest user:123456 [zk: localhost:2181(CONNECTED) 18] setAcl /node3 auth:user:123456:cdrwa [zk: localhost:2181(CONNECTED) 20] getAcl /node3 'digest,'user:6DY5WhzOfGsWQ1XFuIyzxkpwdPo= : cdrwa [zk: localhost:2181(CONNECTED) 21] get /node3 null # 退出客戶端重新登錄 [zk: localhost:2181(CONNECTED) 0] whoami Auth scheme: User ip: 127.0.0.1 [zk: localhost:2181(CONNECTED) 1] get /node3 org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /node3 [zk: localhost:2181(CONNECTED) 2] addauth digest user:123456 [zk: localhost:2181(CONNECTED) 3] get /node3 null [zk: localhost:2181(CONNECTED) 4] whoami Auth scheme: User digest: user ip: 127.0.0.1
digest授權模式
digest 可用於賬號密碼登錄和驗證,digest和auth有兩點區別。一是digest不用進行授權用戶的添加,二是digest在授權過程中需要提供加密之后的密碼。這里的密碼是經過SHA1及BASE64處理的密文,在shell中用以下命令計算:
echo -n wfj:123456 | openssl dgst -binary -sha1 | openssl base64
案例:
# 在shell計算密文 [root@d477dbe7959e ~]# echo -n wfj:123456 | openssl dgst -binary -sha1 | openssl base64 rljj942QO396u5a6EO/22EozxsI= # 創建節點並賦予digest權限 [zk: localhost:2181(CONNECTED) 1] create /node4 "node4" Created /node4 [zk: localhost:2181(CONNECTED) 2] setAcl /node4 digest:wfj:rljj942QO396u5a6EO/22EozxsI=:cdrwa [zk: localhost:2181(CONNECTED) 3] get /node4 org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /node4 [zk: localhost:2181(CONNECTED) 4] getAcl /node4 Insufficient permission : /node4 [zk: localhost:2181(CONNECTED) 5] addauth digest wfj:123456 [zk: localhost:2181(CONNECTED) 6] getAcl /node4 'digest,'wfj:rljj942QO396u5a6EO/22EozxsI= : cdrwa
多種授權模式
同一個節點同時使用多種授權模式
[zk: localhost:2181(CONNECTED) 1] addauth digest wfj:123456 [zk: localhost:2181(CONNECTED) 2] setAcl /node5 ip:127.0.0.1:cdwa,auth:itcast:cdrwa [zk: localhost:2181(CONNECTED) 3] getAcl /node5 'ip,'127.0.0.1 : cdwa 'digest,'wfj:rljj942QO396u5a6EO/22EozxsI= : cdrwa
ACL超級管理員
zookeeper的權限管理模式有一種叫做super,該模式提供一個超管可以方便的訪問任何權限的節點。例如在忘記密碼時,可以通過超管來對節點進行操作。
假設這個超管是: super:admin,需要先為超管生成密碼的密文
[root@d477dbe7959e ~]# echo -n super:admin |openssl dgst -binary -sha1 |openssl base64 xQJmxLMiHGwaqBvst5y6rkB6HQs=
找到zookeeper目錄下的 bin/zkServer.sh服務器腳本文件,找到如下一行:
root@667afe193621:/apache-zookeeper-3.7.0-bin/bin# cat zkServer.sh | grep -nA3 nohup 164: nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \ 165- "-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \ 166- -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \ 167- -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
這就是腳本中啟動zookeeper的命令,默認只有以上兩個配置項,我們需要加一個超管的配置項
"-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs=" \
修改之后這條命令就變成了如下所示:
root@667afe193621:/apache-zookeeper-3.7.0-bin/bin# sed -i '165a\ \ \ \ "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs=" \\' zkServer.sh root@667afe193621:/apache-zookeeper-3.7.0-bin/bin# cat zkServer.sh | grep -nA4 nohup 164: nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \ 165- "-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \ 166- "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs=" \ 167- -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \ 168- -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
然后重啟zookeeper。
create /node6 "node6" [zk: localhost:2181(CONNECTED) 6] setAcl /node6 ip:192.168.126.1: [zk: localhost:2181(CONNECTED) 7] ls /node6 Insufficient permission : /node6 [zk: localhost:2181(CONNECTED) 8] addauth digest super:admin [zk: localhost:2181(CONNECTED) 9] delete /node6