天天看點

什麼?Zookeeper | ACL權限控制

ZooKeeper 作為一個分布式協調架構,内部存儲的都是一些分布式系統運作時狀态的中繼資料,尤其是一些涉及到

分布式鎖

master選舉

分布式協調

等應用場景的資料,資料的通路權限涉及到 ZooKeeper 運作時安全。為了保障 ZooKeeper 的資料安全,提供了一套完整的

ACL(Access Control List)

權限控制機制來保障資料的安全。

權限 ACL 介紹

ACL 的實作和 UNIX 的實作非常相似:它

采用權限位來控制哪些操作被允許,哪些操作被禁止

。但是和标準的 UNIX 權限不同的是,Znode 沒有限制使用者(user,即檔案的所有者),組(group)和其他(world)。Zookeepr 是沒有所有者的概念的。

每個 ZNode 的ACL是獨立的,且子節點不會繼承父節點的ACL

。例如:Znode /app對于 ip 為172.16.16.1隻有隻讀權限,而/app/status是world可讀,那麼任何人都可以擷取 /app/status。是以在 Zookeeper 中權限是沒有繼承和傳遞關系的,

每個Znode 的權限都是獨立存在的

Zookeeper 支援可插拔的權限認證方案,分為三個次元:scheme,user,permission。通常表示為

[scheme:id:permissions]

,其中 Scheme 表示使用何種方式來進行通路控制(使用何種權限驗證機制),Id代表使用者,Permission表示有什麼權限(權限組合字元串)。下面分别說說這三個次元:

一個 ZooKeeper 的節點( znode )存儲兩部分内容:資料和狀态,狀态中包含 ACL 資訊。建立一個 znode 會産生一個 ACL 清單,清單中每個 ACL 包括以上三個次元。
ACL 的構成-scheme(權限模式)

scheme 有以下幾種類型:

  • world

    :world下隻有一個id,即隻有一個使用者,也就是anyone,那麼組合的寫法就是 world:anyone:[permissions]
  • ip

    :當設定為ip指定的ip位址,此時限制ip進行通路,比如 ip:192.168.77.130:[permissions]。也可以通過配置IP網段的方式,例如 “ip:192.168.28.1/24:[permissions]”,表示針對192.168.28.*整個IP段進行權限控制。
  • auth

    :代表認證登入,需要注冊使用者擷取權限後才可以登入通路,形式為 auth:userpassword:[permissions]
  • digest

    :需要對密碼加密才能通路,組合形式為:digest:username:BASE64(SHA1(password)):[permissions]。具體的實作是由DigestAuthenticationProvider.generateDigest()方法來保證的。
    • auth 與 digest 的差別就是,前者使用明文密碼進行登入,後者使用密文密碼進行登入。

      setAcl /path auth:lee:lee:cdrwa

      setAcl /path digest:lee:BASE64(SHA1(password)):cdrwa

      是等價的,在通過

      addauth digest lee:lee

      後都能操作指定節點的權限。在實際情況中,digest要更為常用一些。
  • super

    :代表超級管理者,擁有所有的權限,可以操作ZooKeeper上的任意節點資料。
注意的是, exists 操作和 getAcl 操作并不受 ACL 許可控制,是以任何用戶端可以查詢節點的狀态和節點的 ACL 。
ACL 的構成-id(授權對象)

對于不同的scheme,授權的對象是不同的:

  • IP模式:授權對象通常是一個ip位址或者是一個ip段;
  • Digest模式:授權對象通常是自定義中的username;
  • World模式:授權對象是anyone;
  • Super模式:授權對象和Digest中的相同;
ACL 的構成-permissions(權限)

權限字元串縮寫

crdwa

  • CREATE

    :建立子節點權限(允許對子節點 Create 操作);
  • READ

    :通路節點/子節點權限(允許對本節點 GetChildren 和 GetData 操作);
  • WRITE

    :設定節點資料權限(允許對本節點 SetData 操作);
  • DELETE

    :删除子節點權限(允許對子節點 Delete 操作);
  • ADMIN

    :管理者權限(允許對本節點 setAcl 操作);
ACL 指令
  • getAcl

    :擷取某個節點的ACL權限資訊;
  • setAcl

    :設定某個節點的ACL權限資訊;
  • addauth

    :輸入認證授權資訊,注冊時輸入明文密碼(登入),但是在zk的系統裡,密碼是以加密後的形式存在的;

ACL 指令行操作

ACL 指令行 world

使用 getAcl 指令擷取某個節點的acl權限資訊,示例:

[zk: localhost:(CONNECTED) ] create /testDir/testAcl test-data     # 建立一個子節點
Created /testDir/testAcl
[zk: localhost:(CONNECTED) ] getAcl /testDir/testAcl       # 擷取該節點的acl權限資訊
'world,'anyone      # 預設為world
: cdrwa
           

使用 setAcl 指令設定某個節點的acl權限資訊,示例:

[zk: localhost:2181(CONNECTED) 2] setAcl /testDir/testAcl world:anyone:crwa     # 設定該節點的acl權限
cZxid = 0x67
ctime = Tue Aug 28 13:12:29 CST 2018
mZxid = 0x67
mtime = Tue Aug 28 13:12:29 CST 2018
pZxid = 0x67
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 9
numChildren = 0
[zk: localhost:2181(CONNECTED) 3] getAcl /testDir/testAcl
'world,'anyone
: crwa      # 設定成功後,該節點就少了d權限
[zk: localhost:2181(CONNECTED) 4] create /testDir/testAcl/xyz xyz-data      # 建立子節點
Created /testDir/testAcl/xyz
[zk: localhost:2181(CONNECTED) 5] delete /testDir/testAcl/xyz       # 删除該子節點
Authentication is not valid : /testDir/testAcl/xyz      # 由于沒有d權限,是以提示無法删除
           

設定其他的權限也是如此,在此就不做示範了。

ACL 指令行 auth

使用 auth 來設定權限的時候,需要在 zk 裡注冊一個使用者才可以。示例:

[zk: localhost:2181(CONNECTED) 6] addauth digest user1:123456       # 需要先添加一個使用者
[zk: localhost:2181(CONNECTED) 7] setAcl /testDir/testAcl auth:user1:123456:crwa    # 然後才可以拿着這個使用者去設定權限
cZxid = 0x67
ctime = Tue Aug 28 13:12:29 CST 2018
mZxid = 0x67
mtime = Tue Aug 28 13:12:29 CST 2018
pZxid = 0x69
cversion = 1
dataVersion = 0
aclVersion = 2
ephemeralOwner = 0x0
dataLength = 9
numChildren = 1
[zk: localhost:2181(CONNECTED) 8] getAcl /testDir/testAcl
'digest,'user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=     # 密碼是以密文的形式存儲的
: crwa
           

如果設定了權限後,再次進行設定,就可以不用加上使用者名和密碼了。而且就算是使用其他使用者進行設定,也隻會根據第一次設定的使用者來進行配置:

[zk: localhost:(CONNECTED) ] setAcl /testDir/testAcl auth::crw
[zk: localhost:(CONNECTED) ] setAcl /testDir/testAcl auth:test:test:crw
[zk: localhost:(CONNECTED) ] getAcl /testDir/testAcl
'digest,'user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=     # 依舊是第一次設定的使用者
: crw
           
ACL 指令行 digest

由于之前使用 auth 做實驗的時候已經登入了使用者 ,是以在使用 digest 做實驗前,需要先退出一下用戶端,再重新連接配接,這樣之前登入的使用者就會自動退出。退出使用者後才能使用 digest 設定權限,示例:

[zk: localhost:2181(CONNECTED) 2] create /names/testDigest digest-data      # 建立子節點
Created /names/testDigest
[zk: localhost:2181(CONNECTED) 3] addauth digest user1:123456       # 添加使用者
[zk: localhost:2181(CONNECTED) 4] getAcl /names/testDigest
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 5] setAcl /names/testDigest digest:user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=:crwa   # 使用digest來設定權限
cZxid = 0x72
ctime = Tue Aug 28 14:37:05 CST 2018
mZxid = 0x72
mtime = Tue Aug 28 14:37:05 CST 2018
pZxid = 0x72
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 11
numChildren = 0
[zk: localhost:2181(CONNECTED) 6] getAcl /names/testDigest
'digest,'user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=
: crwa
           

可以看到,digest 和 auth 除了一個使用明文一個使用密文之外,其他都是一緻的,是以它倆的差別就隻是密文和明文的差別。線上上環境中,一般使用 digest 比較多,因為密文安全一些。

ACL 指令行 ip

這種方式和限制 ip 是一樣的,就是設定隻允許某一個 ip 有權限操作。示例:

[zk: localhost:2181(CONNECTED) 7] create /names/testip ip-data      # 建立子節點
Created /names/testip
[zk: localhost:2181(CONNECTED) 8] getAcl /names/testip
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 9] setAcl /names/testip ip:192.168.190.129:cdrwa     # 使用ip來設定權限
cZxid = 0x74
ctime = Tue Aug 28 15:03:56 CST 2018
mZxid = 0x74
mtime = Tue Aug 28 15:03:56 CST 2018
pZxid = 0x74
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0
[zk: localhost:2181(CONNECTED) 10] getAcl /names/testip
'ip,'192.168.190.129        # 隻允許這個ip擁有該節點的cdrwa權限
: cdrwa
[zk: localhost:2181(CONNECTED) 11] get /names/testip
Authentication is not valid : /names/testip     # 由于本機的ip不是192.168.190.129,是以擷取失敗
           
ACL 指令行 super超級管理者

基本所有的系統都會擁有一個超級管理者使用者,zk也不例外。當我們給一些節點設定了權限,但是卻發現設定錯誤了,導緻節點無法正常通路,那麼這時候普通使用者是無法解決這種問題的,隻能使用超級管理者使用者來重新設定權限或删除節點。是以本節簡單示範一下,如何配置管理者使用者:

1、修改 zkServer.sh 增加super管理者

[root@study- /usr/local/zookeeper-./bin]# vim zkServer.sh  # 找到nohup那一行,加入以下内容
"-Dzookeeper.DigestAuthenticationProvider.superDigest=user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s="
           
注:user1是使用者名,後面那一大串是加密後的密文密碼

如下圖:

什麼?Zookeeper | ACL權限控制

2、修改完之後,需要重新開機zookeeper服務才能生效 3、使用超級管理者使用者

[[email protected] ~]# zkCli.sh
[zk: localhost:2181(CONNECTED) 9] ls /names/ip  # ls一個無權限的節點
Authentication is not valid : /names/ip   # 可以看到,權限不夠
[zk: localhost:2181(CONNECTED) 10] addauth digest user1:123456  # 登入超級管理者使用者,這裡登入用的是明文密碼
[zk: localhost:2181(CONNECTED) 11] ls /names/ip  # 然後再次ls
[]   # 這次就可以ls到了
[zk: localhost:2181(CONNECTED) 12] get /names/ip   # 也可以get資訊
ip-data
cZxid = 0x51
ctime = Mon Apr 23 21:02:42 CST 2018
mZxid = 0x51
mtime = Mon Apr 23 21:02:42 CST 2018
pZxid = 0x51
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0
[zk: localhost:2181(CONNECTED) 13] delete /names/testip  # 删除節點也可以
           
ACL 的常用使用場景
  • 開發/測試環境分離,開發者無權操作測試庫的節點,隻能讀取
  • 生産環境上控制指定ip的服務可以通路相關的節點,防止混亂

繼續閱讀