官網地址
http://zookeeper.apache.org/doc/current/zookeeperProgrammers.html#sc_ZooKeeperAccessControl
概述
ACL全稱為Access Control List(訪問控制列表),用於控制資源的訪問權限。ZooKeeper使用ACL來控制對其znode(ZooKeeper數據樹的數據節點)的訪問。ACL實現與UNIX文件訪問權限非常相似:它使用權限位來允許/禁止針對節點的各種操作以及位應用的范圍。與標准UNIX權限不同,ZooKeeper節點不受用戶(文件所有者),組和world(其他)的三個標准范圍的限制。
zk利用ACL策略控制節點的訪問權限,如節點數據讀寫、節點創建、節點刪除、讀取子節點列表、設置節點權限等。
在傳統的文件系統中,一個文件擁有某個組的權限即擁有了組里的所有權限,文件或子目錄默認會繼承自父目錄的ACL。而在Zookeeper中,znode的ACL是沒有繼承關系的,每個znode的權限都是獨立控制的,只有客戶端滿足znode設置的權限要求時,才能完成相應的操作。Zookeeper的ACL,分為三個維度:scheme、id、permission,通常表示為:scheme:id:permission,schema代表授權策略,id代表用戶,permission代表權限。下面分別講述一下這三個屬性:
一、scheme
scheme即采取的授權策略,每種授權策略對應不同的權限校驗方式。下面是zk常用的幾種scheme:
world:默認方式,相當於全世界都能訪問
auth:不使用任何id,表示任何經過身份驗證的用戶。
digest:即用戶名:密碼這種方式認證,這也是業務系統中最常用的,使用username:password字符串生成MD5哈希,然后將其用作ACL的ID標識。通過以明文形式發送 例如:wangsaichao:123456 來完成身份驗證。在ACL中使用時,表達式將是wangsaichao:G2RdrM8e0u0f1vNCj/TI99ebRMw=。
ip:使用Ip地址認證
1> world
語法:world:anyone:cdrwa
創建節點默認的scheme,所有人都可以訪問。如下所示:
## 創建新的節點 /node01 [zk: localhost:2181(CONNECTED) 10] create /node01 234 Created /node01 # 查看ACL [zk: localhost:2181(CONNECTED) 11] getAcl /node01 'world,'anyone : cdrwa [zk: localhost:2181(CONNECTED) 12]
2> digest
語法:digest:username:BASE64(SHA1(password)):cdrwa
digest:是授權方式
username:BASE64(SHA1(password)):是id部分
cdrwa:權限部份
用戶名+密碼授權訪問方式,也是常用的一種授權策略。id部份是用戶名和密碼做sha1加密再做BASE64加密后的組合,比如設置一個節點的用戶名為wangsaichao,密碼為123456,則表示方式為:
原:wangsaicaho:BASE64(SHA1(123456))
正確:wangsaichao:G2RdrM8e0u0f1vNCj/TI99ebRMw=。
密碼加密需要用到zk的一個工具類來生成,如下所示:
java -Djava.ext.dirs=/Users/wangsaichao/Desktop/zookeeper-3.4.6/lib -cp /Users/wangsaichao/Desktop/zookeeper-3.4.6/zookeeper-3.4.6.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider wangsaichao:123456 wangsaichao:123456->wangsaichao:G2RdrM8e0u0f1vNCj/TI99ebRMw=
本文的Zookeeper安裝在:/Users/wangsaichao/Desktop/zookeeper-3.4.6,下面是演示創建節點,並添加授權信息操作節點的示例:
## 查看/根節點 [zk: localhost:2181(CONNECTED) 1] ls / [zookeeper] ## 創建節點/node [zk: localhost:2181(CONNECTED) 2] create /node 123 Created /node ## 設置權限 [zk: localhost:2181(CONNECTED) 3] setAcl /node digest:wangsaichao:G2RdrM8e0u0f1vNCj/TI99ebRMw=:cdrwa cZxid = 0x2 ctime = Sun Sep 09 16:25:51 CST 2018 mZxid = 0x2 mtime = Sun Sep 09 16:25:51 CST 2018 pZxid = 0x2 cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 3 numChildren = 0 ## 獲取節點剛剛設置的權限 [zk: localhost:2181(CONNECTED) 4] getAcl /node 'digest,'wangsaichao:G2RdrM8e0u0f1vNCj/TI99ebRMw= : cdrwa ## 沒有授權,創建子節點失敗 [zk: localhost:2181(CONNECTED) 5] create /node/child_01 234 Authentication is not valid : /node/child_01 ## 為當前session添加授權信息 [zk: localhost:2181(CONNECTED) 6] addauth digest wangsaichao:123456 ## 添加授權信息后,創建子節點成功 [zk: localhost:2181(CONNECTED) 7] create /node/child_01 234 Created /node/child_01 [zk: localhost:2181(CONNECTED) 8]
3> auth
scheme為auth時,不需要id。說的不需要id,但是還需要使用一個username:password的expression來表示這個權限,你也可以理解其實就是id,哈哈.
## 創建一個新的節點 /test_node1 [zk: localhost:2181(CONNECTED) 23] create /test_node1 121 Created /test_node1 ## 添加授權賬號 [zk: localhost:2181(CONNECTED) 24] addauth digest zookeeper:zookeeper ## 然后設置節點的ACL [zk: localhost:2181(CONNECTED) 25] setAcl /test_node1 auth:zookeeper:zookeeper:cdrwa cZxid = 0x13 ctime = Sun Sep 09 17:46:26 CST 2018 mZxid = 0x13 mtime = Sun Sep 09 17:46:26 CST 2018 pZxid = 0x13 cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 3 numChildren = 0 ## 查看剛才設置的ACL [zk: localhost:2181(CONNECTED) 26] getAcl /test_node1 'digest,'zookeeper:4lvlzsipXVaEhXMd+2qMrLc0at8= : cdrwa [zk: localhost:2181(CONNECTED) 27] 這里有一個坑,在使用auth授權時,一定要先執行addauth digest zookeeper:zookeeper然后再授權,否則將使用上一次的授權expression。下面舉個例子。執行多次addauth digest 用戶名:密碼 操作,在新的節點設置auth時,將都會生效。具體例子如下: ## 創建一個新的節點 /test_node2 [zk: localhost:2181(CONNECTED) 27] create /test_node2 234 Created /test_node2 ## 設置auth授權, 使用一個並不存在的 hello用戶,依然成功了 [zk: localhost:2181(CONNECTED) 28] setAcl /test_node2 auth:hello:hello:cdrwa cZxid = 0x15 ctime = Sun Sep 09 17:50:10 CST 2018 mZxid = 0x15 mtime = Sun Sep 09 17:50:10 CST 2018 pZxid = 0x15 cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 3 numChildren = 0 ## 查看ACL 竟然是之前的zookeeper用戶 [zk: localhost:2181(CONNECTED) 29] getAcl /test_node2 'digest,'zookeeper:4lvlzsipXVaEhXMd+2qMrLc0at8= : cdrwa ## 這個時候添加 hello 用戶 [zk: localhost:2181(CONNECTED) 30] addauth digest hello:hello ## 創建新的節點 /test_node3 [zk: localhost:2181(CONNECTED) 31] create /test_node3 456 Created /test_node3 ## 查看ACL 這個時候還是world [zk: localhost:2181(CONNECTED) 32] getAcl /test_node3 'world,'anyone : cdrwa ## 設置auth ACL [zk: localhost:2181(CONNECTED) 33] setAcl /test_node3 auth:hello:hello:cdrwa cZxid = 0x17 ctime = Sun Sep 09 17:53:14 CST 2018 mZxid = 0x17 mtime = Sun Sep 09 17:53:14 CST 2018 pZxid = 0x17 cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 3 numChildren = 0 ## 查看ACL 發現之前的zookeeper用戶也存在 [zk: localhost:2181(CONNECTED) 34] getAcl /test_node3 'digest,'zookeeper:4lvlzsipXVaEhXMd+2qMrLc0at8= : cdrwa 'digest,'hello:uXpRvPoy9gsHHSCo8uMtZmaXPIA= : cdrwa [zk: localhost:2181(CONNECTED) 35]
4> ip
基於客戶端IP地址校驗,限制只允許指定的客戶端能操作znode。
比如,設置某個節點只允許IP為127.0.0.1的客戶端能讀寫該寫節點的數據:ip:127.0.0.1:rw
## 給node節點添加新的ACL權限 [zk: localhost:2181(CONNECTED) 8] setAcl /node ip:127.0.0.1:cdrwa cZxid = 0x2 ctime = Sun Sep 09 16:25:51 CST 2018 mZxid = 0x2 mtime = Sun Sep 09 16:25:51 CST 2018 pZxid = 0x5 cversion = 1 dataVersion = 0 aclVersion = 2 ephemeralOwner = 0x0 dataLength = 3 numChildren = 1 ## 查看ACL [zk: localhost:2181(CONNECTED) 9] getAcl /node 'ip,'127.0.0.1 : cdrwa [zk: localhost:2181(CONNECTED) 10]
上面主要介紹了平時常用的三種scheme,除此之外,還有host、super、auth授權策略。
二、id
id是驗證模式,不同的scheme,id的值也不一樣。scheme為digest時,id的值為:username:BASE64(SHA1(password)),scheme為ip時,id的值為客戶端的ip地址。scheme為world時,id的值為anyone。scheme為auth時,id為 username:password。
三、permission
znode可以擁有的權限還記得之前的授權語句,如:
digest:username:BASE64(SHA1(password)):cdrwa中的cdrwa即是permission。
CREATE(r):創建子節點的權限
DELETE(d):刪除節點的權限
READ(r):讀取節點數據的權限
WRITE(w):修改節點數據的權限
ADMIN(a):設置子節點權限的權限
## 先在當前session中添加 wangsaichao:123456 用戶 [zk: localhost:2181(CONNECTED) 35] addauth digest wangsaichao:123456 ## 創建一個新的節點,並添加digest ACL(只能創建和刪除) 因為是digest 所以密碼為加密之后的 [zk: localhost:2181(CONNECTED) 36] create /test_node5 123 digest:wangsaichao:G2RdrM8e0u0f1vNCj/TI99ebRMw=:cd Created /test_node5 ## 沒有WRITE權限, 設置節點數據 失敗 [zk: localhost:2181(CONNECTED) 37] set /test_node5 234 Authentication is not valid : /test_node5 ## 沒有ADMIN權限,設置ACL失敗 [zk: localhost:2181(CONNECTED) 38] setAcl /test_node5 auth:wangsaichao:123456:cdrwa Authentication is not valid : /test_node5 ## 沒有READ權限, 讀取節點 失敗 [zk: localhost:2181(CONNECTED) 39] get /test_node5 Authentication is not valid : /test_node5 ## 具備CREATE權限,創建子節點成功 [[zk: localhost:2181(CONNECTED) 40] create /test_node5/child_01 123 Created /test_node5/child_01 ## 具備DELETE權限,可以刪除子節點 [zk: localhost:2181(CONNECTED) 41] delete /test_node5/child_01 [zk: localhost:2181(CONNECTED) 42]