1. 程式人生 > >ZooKeeper 筆記(5) ACL(Access Control List)訪問控制列表

ZooKeeper 筆記(5) ACL(Access Control List)訪問控制列表

總體來說,ZK的節點有5種操作許可權

CREATE、READ、WRITE、DELETE、ADMIN 也就是 增、刪、改、查、管理許可權,這5種許可權簡寫為crwda(即:每個單詞的首字元縮寫)

注:這5種許可權中,delete是指對子節點的刪除許可權,其它4種許可權指對自身節點的操作許可權

身份的認證有4種方式

world:預設方式,相當於全世界都能訪問
auth:代表已經認證通過的使用者(cli中可以通過addauth digest user:pwd 來添加當前上下文中的授權使用者)
digest:即使用者名稱:密碼這種方式認證,這也是業務系統中最常用的
ip:使用Ip地址認證

Cli命令列下可以這樣測試:

通過getAcl命令可以發現,剛建立的節點,預設是 world,anyone的認證方式,具有cdrwa所有許可權

繼續搗鼓:

先給/test增加了user1:+owfoSBn/am19roBPzR1/MfCblE的只讀(r)許可權控制,

說明:setAcl /test digest:使用者名稱:密碼:許可權 給節點設定ACL訪問許可權時,密碼必須是加密後的內容,這裡的+owfoSBn/am19roBPzR1/MfCblE=,對應的原文是12345 (至於這個密文怎麼得來的,後面會講到,這裡先不管這個),設定完Acl後,可以通過

getAcl /節點路徑 檢視Acl設定

然後get /test時,提示認證無效,說明訪問控制起作用了,接下來:

addauth digest user1:12345 給"上下文"增加了一個認證使用者,即對應剛才setAcl的設定

然後再 get /test 就能取到資料了

最後 delete /test 成功了!原因是:根節點/預設是world:anyone:crdwa(即:全世界都能隨便折騰),所以也就是說任何人,都能對根節點/進行讀、寫、建立子節點、管理acl、以及刪除子節點(再次映證了ACL中的delete許可權應該理解為對子節點的delete許可權)

剛才也提到了,setAcl /path digest這種方式,必須輸入密碼加密後的值,這在cli控制檯上很不方便,所以下面這種方式更常用:

注意加框的部分,先用addauth digest user1:12345 增加一個認證使用者,然後用 setAcl /test auth:user1:12345:r 設定許可權,跟剛才的效果一樣,但是密碼這裡輸入的是明文,控制檯模式下手動輸入更方便。

好了,揭開加密規則:

    static public String generateDigest(String idPassword)
            throws NoSuchAlgorithmException {
        String parts[] = idPassword.split(":", 2);
        byte digest[] = MessageDigest.getInstance("SHA1").digest(
                idPassword.getBytes());
        return parts[0] + ":" + base64Encode(digest);
    }

就是SHA1加密,然後base64編碼  

程式碼使用:

zookeeper有一個很好用的客戶端開源專案zkclient,官網地址為:http://github.com/zkclient ,其最新片0.7-dev已經支援ACL了(舊0.1版無此功能,所以推薦使用最新版),使用方法:

git clone https://github.com/sgroschupf/zkclient (把程式碼拉到本地)

修改

build.gradle 找到92行

uploadArchives {

    repositories.mavenDeployer {
        //repository(url: "file:///tmp/mavenRepo")
        repository(url: "http://172.21.129.56:8081/nexus/content/repositories/thirdparty/") {
            authentication(userName: admin, password: admin123)
        }
        beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
        pom.project {
            name 'ZkClient'
            packaging 'jar'
            description 'A zookeeper client, that makes life a little easier.'
            url 'https://github.com/sgroschupf/zkclient'
            licenses {
                license {
                    name 'The Apache Software License, Version 2.0'
                    url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    distribution 'repo'
                }
            }
            scm {
                url 'https://github.com/sgroschupf/zkclient'
                connection 'scm:git:git://github.com/sgroschupf/zkclient.git'
                developerConnection 'scm:git:https://github.com/sgroschupf/zkclient.git'
            }
            developers {
                developer {
                    id 'sgroschupf'
                    name 'Stefan Groshupf'
                }
                developer {
                    id 'pvoss'
                    name 'Peter Voss'
                }
                developer {
                    id 'jzillmann'
                    name 'Johannes Zillmann'
                }
            }
        }
    }
}

把這一段幹掉,否則編譯時會出錯

然後(windows環境,把./gradew 換成gradlew)

./gradlew test (測試)

./gradlew jars (編譯生成jar包)

./gradlew install (安裝到本機maven倉庫)  

新建一個maven專案,pom.xml參考下面設定:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>yjmyzz</groupId>
 8     <artifactId>zkclient-demo</artifactId>
 9     <version>1.0</version>
10 
11     <dependencies>
12         <dependency>
13             <groupId>org.apache.zookeeper</groupId>
14             <artifactId>zookeeper</artifactId>
15             <version>3.4.6</version>
16         </dependency>
17 
18         <dependency>
19             <groupId>com.101te</groupId>
20             <artifactId>zkclient</artifactId>
21             <version>0.7</version>
22             <classifier>dev</classifier>
23         </dependency>
24 
25         <dependency>
26             <groupId>log4j</groupId>
27             <artifactId>log4j</artifactId>
28             <version>1.2.17</version>
29         </dependency>
30 
31     </dependencies>
32 
33 
34 </project>
View Code

然後寫一段程式碼測試一下:

package yjmyzz.zk;

import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class Main {

    private static final String zkAddress = "localhost:2181";
    private static final String testNode = "/test";
    private static final String readAuth = "read-user:123456";
    private static final String writeAuth = "write-user:123456";
    private static final String deleteAuth = "delete-user:123456";
    private static final String allAuth = "super-user:123456";
    private static final String adminAuth = "admin-user:123456";
    private static final String digest = "digest";

    private static void initNode() throws NoSuchAlgorithmException {
        ZkClient zkClient = new ZkClient(zkAddress);
        zkClient.addAuthInfo(digest, allAuth.getBytes());

        if (zkClient.exists(testNode)) {
            zkClient.delete(testNode);
            System.out.println("節點刪除成功!");
        }

        List<ACL> acls = new ArrayList<ACL>();
        acls.add(new ACL(ZooDefs.Perms.ALL, new Id(digest, DigestAuthenticationProvider.generateDigest(allAuth))));
        acls.add(new ACL(ZooDefs.Perms.READ, new Id(digest, DigestAuthenticationProvider.generateDigest(readAuth))));
        acls.add(new ACL(ZooDefs.Perms.WRITE, new Id(digest, DigestAuthenticationProvider.generateDigest(writeAuth))));
        acls.add(new ACL(ZooDefs.Perms.DELETE, new Id(digest, DigestAuthenticationProvider.generateDigest(deleteAuth))));
        acls.add(new ACL(ZooDefs.Perms.ADMIN, new Id(digest, DigestAuthenticationProvider.generateDigest(adminAuth))));
        zkClient.createPersistent(testNode, "test-data", acls);

        System.out.println(zkClient.readData(testNode));
        System.out.println("節點建立成功!");
        zkClient.close();
    }

    private static void readTest() {
        ZkClient zkClient = new ZkClient(zkAddress);

        try {
            System.out.println(zkClient.readData(testNode));//沒有認證資訊,讀取會出錯
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        try {
            zkClient.addAuthInfo(digest, adminAuth.getBytes());
            System.out.println(zkClient.readData(testNode));//admin許可權與read許可權不匹配,讀取也會出錯
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        try {
            zkClient.addAuthInfo(digest, readAuth.getBytes());
            System.out.println(zkClient.readData(testNode));//只有read許可權的認證資訊,才能正常讀取
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        zkClient.close();
    }

    private static void writeTest() {
        ZkClient zkClient = new ZkClient(zkAddress);

        try {
            zkClient.writeData(testNode, "new-data");//沒有認證資訊,寫入會失敗
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        try {
            zkClient.addAuthInfo(digest, writeAuth.getBytes());
            zkClient.writeData(testNode, "new-data");//加入認證資訊後,寫入正常
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        try {
            zkClient.addAuthInfo(digest, readAuth.getBytes());
            System.out.println(zkClient.readData(testNode));//讀取新值驗證
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        zkClient.close();
    }

    private static void deleteTest() {
        ZkClient zkClient = new ZkClient(zkAddress);
        //zkClient.addAuthInfo(digest, deleteAuth.getBytes());
        try {
            //System.out.println(zkClient.readData(testNode));
            zkClient.delete(testNode);
            System.out.println("節點刪除成功!");
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
        zkClient.close();
    }

//    private static void deleteTest2() throws IOException, InterruptedException, KeeperException {
//        //使用zookeeper原生的API進行刪除(注:delete許可權指有沒有許可權刪除子節點)
//        ZooKeeper zk = new ZooKeeper(zkAddress, 300000, new DemoWatcher());
//        zk.delete(testNode, -1);
//        System.out.println("節點刪除成功");
//        zk.close();
//    }
//
//    static class DemoWatcher implements Watcher {
//        @Override
//        public void process(WatchedEvent event) {
//            System.out.println("----------->");
//            System.out.println("path:" + event.getPath());
//            System.out.println("type:" + event.getType());
//            System.out.println("stat:" + event.getState());
//            System.out.println("<-----------");
//        }
//    }

    private static void changeACLTest() {
        ZkClient zkClient = new ZkClient(zkAddress);
        //注:zkClient.setAcl方法檢視原始碼可以發現,呼叫了readData、setAcl二個方法
        //所以要修改節點的ACL屬性,必須同時具備read、admin二種許可權
        zkClient.addAuthInfo(digest, adminAuth.getBytes());
        zkClient.addAuthInfo(digest, readAuth.getBytes());
        try {
            List<ACL> acls = new ArrayList<ACL>();
            acls.add(new ACL(ZooDefs.Perms.ALL, new Id(digest, DigestAuthenticationProvider.generateDigest(adminAuth))));
            zkClient.setAcl(testNode, acls);
            Map.Entry<List<ACL>, Stat> aclResult = zkClient.getAcl(testNode);
            System.out.println(aclResult.getKey());
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
        zkClient.close();
    }


    public static void main(String[] args) throws Exception {

        initNode();

        System.out.println("---------------------");

        readTest();

        System.out.println("---------------------");

        writeTest();

        System.out.println("---------------------");

        changeACLTest();

        System.out.println("---------------------");

        deleteTest();

        //deleteTest2();

    }
}

輸出結果:

test-data
節點建立成功!
---------------------
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /test
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /test
test-data
---------------------
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /test
new-data
---------------------
[31,s{'digest,'admin-user:mAlW21Phn07yOvWnKJYq2sCMoZw=}
]
---------------------
節點刪除成功!

從zkclient的使用結果看,與cli操作效果一樣。  

最後:關於多級節點之間的ACL,並非繼承關係,但是也有些一聯絡,這是初次接觸ACL中比較難理解的地方:

從這張圖上可以發現,子節點/a/b的控制權限範圍(全世界都能做任何事)可以超出父節點的範圍(僅限:user-a:pwd:a具有read/admin許可權)

繼續,看上面的這4條紅線標註的地方,從上向下一個個解釋:

紅線1:因為/a只有user-a:pwd-a有ra許可權,即:沒使用者具有c(create)許可權,所以不能建立子節點

紅線2:因為/a/b為world:anyone:cdrwa許可權,即無限制,所以在/a/b下建立子節點b1,地球人已經無法阻止,建立成功

紅線3:給/a/b/b1指定了user-b1:pwd-b1的da許可權(即:delete+admin)

(注:重溫下前面提到的setAcl 二種模式,

一種是setAcl /path digest:username:encrypedpwd:crwda 用這種方式時,encrypedpwd使用者必須是密文

另一種方式是先addauth digest:usrname:password 先把授權資訊加入上下文,這裡password用的是明文,然後再setAcl /path auth:username:password:crdwa

所以如果在cli控制檯測試,強烈建議用第二種方式,否則象上圖中的方式用錯了方式,pwd-b1在zk中被認為是密文,要解密出來幾乎不可能,所以設定後,相當於這個節點就廢了,因為你不知道密碼,要操作該節點時,提供不了正確的認證資訊)

紅線4:還是剛才的理由,因為/a/b為world:anyone:cdrwa,沒有限制,所以刪除其下的子節點不受阻擋。

從上圖可以看出,無法get父節點的內容,但是可以get子節點的內容,再次說明父、子節點的許可權沒直接關係,但是做delete時,上面的例子卻遇到了麻煩:

想刪除/a/b時,由於父節點/a的ACL列表裡,只有ra許可權,沒有d許可權,所以無法刪除子節點。想刪除/a時,發現下面還有子節點b,節點非空無法刪除,所以這個示例就無解了(因為根據前面的操作,密碼也還原不出來,也就無法修改ACL屬性),而根節點/也無法刪除,解決辦法,只能到data目錄裡清空所有資料,再重啟zk,但是這樣就相當於所有資料全扔了,所以在設計ACL時,對於delete許可權,要謹慎規劃,在測試zk叢集上做好測試,再轉到生產環境操作。

最後給一些許可權組合的測試結果:

要修改某個節點的ACL屬性,必須具有read、admin二種許可權

要刪除某個節點下的子節點,必須具有對父節點的read許可權,以及父節點的delete許可權

相關推薦

ZooKeeper 筆記(5) ACL(Access Control List)訪問控制列表

總體來說,ZK的節點有5種操作許可權: CREATE、READ、WRITE、DELETE、ADMIN 也就是 增、刪、改、查、管理許可權,這5種許可權簡寫為crwda(即:每個單詞的首字元縮寫) 注:這5種許可權中,delete是指對子節點的刪除許可權,其它4種許可權指對自身節點的操作許可權 身

What Is ACL (Access Control List) and How to Configure It?

Though the robust network promotes the connectivity among people at every comer of the globe, we may not enjoy its convenience or gain the information

[QNX]QNX_Linux具體許可權規劃之ACL(Access Control List)

鋒影 email:[email protected] 如果你認為本系列文章對你有所幫助,請大家有錢的捧個錢場,點選此處贊助,贊助額0.1元起步,多少隨意 ACL機制涉及兩條命令:setfacl 、getfacl ACL來源 owner,group,

ACL的三種訪問控制列表的概述及實驗配置

pro 訪問 type 概述 alt 結果 size 三層 routing ACL的概述 在路由器上讀取OSI七層模型的第三層及第四層包頭的信息根據定義好的規則,對包進行過濾 ACL的工作原理 有兩個方向出:已經過路由器的處理,正離開路由器接口的數據包入:已經到達路由器接口

CCNA學習筆記(五) 安全(訪問控制列表

訪問控制列表(ACL)例項詳解 引言 這篇文章介紹訪問控制列表的作用;分別介紹標準、擴充套件、命名訪問控制列表的配置和需要注意的問題。文章後半部分會例項演示一些高階訪問控制列表的配置,包括動態、反射、和基於時間的訪問控制列表(本文中所有配置都可以在GNS3中完成,使用

第10章 網路安全(5)_訪問控制列表ACL

6. 訪問控制列表ACL 6.1 標準訪問控制列表 (1)標準ACL   ①標準ACL是基於IP資料包的源IP地址作為轉發或是拒絕的條件。即,所有的條件都是基於源IP地址的。   ②基本不允許或拒絕整個協議組。它不區分IP流量型別。如Telnet、UDP等服務。 (2)實戰:只允

ZooKeeper zkclient ACL 訪問控制列表

存在的必要性 設計架構 acl 通過 [scheme:id:permissions] 構成 ZK的節點有5種操作許可權: 許可權組合字串 縮寫 crdwa  CREATE:建立子節點  READ:獲取節點、子節點  WRITE:設定節點資料  DELETE:

Cisco之訪問控制列表ACL

cisco acl 訪問控制列表(ACL)是應用在路由器接口的指令列表(即規則),這些規則表用來告訴路由器,哪些數據包可以接收,哪些包需要拒絕。其基本原理如下:ACL使用包過濾技術,在路由器上讀取OSI七層模型的第三層和第四層包頭中的信息,如源地址、目的地址、源端口、目的端口等,根據預先定義的規則,對包

linux acl訪問控制列表系統整理

acl mask 權限掩碼 acl######文件的訪問控制(acl)##########################

訪問控制列表ACL的配置與應用

訪問控制列表 標準acl 擴展acl 楊書凡 命名acl 訪問控制列表(Access Control List,ACL)是應用在路由器接口的指令列表(即規則)。這些指令列表用來告訴路由器,哪些數據包可以接收,哪些數據包需要拒絕。其基本原理如下:ACL使用包過濾技術,在路由器上讀取OS

路由交換基礎(四)——ACL訪問控制列表

per not 由器 地址 同時 擴展 數據包 而不是 需要 一、ACL1.作用訪問控制列表(Access Control List),是路由器和交換機接口的指令列表,用來控制端口進出的數據包。ACL可以過濾網絡中的流量,是控制訪問的一種網絡技術手段。配置ACL後,可以限制

華為-ACL訪問控制列表

華為 ACL 高級ACL 基本ACL ACL:access list 訪問控制列表 acl 兩種:基本acl(2000-2999):只能匹配源ip地址。 高級acl(3000-3999):可以匹配源ip、目標ip、源端口、目標端口等三層和四層的字段。 四個註意事項:註1:一個接口的同一個方

【華為HCNA】訪問控制列表ACL實例配置

華為訪問控制列表ACL案例配置 華為ACL訪問控制列表實例配置 華為ACL應用 ACL訪問控制列表 ACL應用場景 【華為HCNA】訪問控制列表ACL實例配置 ACL的概念訪問控制列表ACL(Access Control List)可以定義一系列不同的規則,設備根據這些規則對數據包進行分類

Azure終結點訪問控制列表ACL

雲計算 雲平臺 對於公有雲來說,用戶最關心的莫過於安全方面的問題了。借助本文,我們來了解下Azure中的訪問控制列表。首先我們來看下什麽是終結點訪問控制列表ACL?終結點訪問控制列表 (ACL) 是可用於 Azure 部署的安全增強。 利用 ACL,可以選擇允許還是拒絕虛擬機終結點的流量。 此數據包篩

第十三章 IP訪問控制列表ACL

ACL第十三章 IP訪問控制列表(ACL)為什麽要使用訪問列表管理網絡中逐步增長的 IP 數據當數據通過路由器時進行過濾訪問列表的應用允許、拒絕數據包通過路由器允許、拒絕Telnet會話的建立沒有設置訪問列表時,所有的數據包都會在網絡上傳輸什麽是訪問列表--(標準,擴展)標準檢查源地址通常允許、拒絕的是完整的

acl訪問控制列表

acl訪問控制列表(Access Control List,ACL) 是路由器和交換機接口的指令列表,用來控制端口進出的數據包。ACL適用於所有的被路由協議,如IP、IPX、AppleTalk等。信息點間通信和內外網絡的通信都是企業網絡中必不可少的業務需求,為了保證內網的安全性,需要通過安全策略來保障非授權用

ACL 訪問控制列表

網絡/安全 網絡管理 ACL 訪問控制列表 原理說明: ACL是網絡設備常用的安全技術,通過手動配置可以部署網絡安全策略,acl規則是檢查流量通信特征。一般從rule5開始建立(留給後續添加優先使用),匹配即停止,默認permit any。每接口。每協議,每方向只允許部署一個acl。 基本acl: 組

配置ACL訪問控制列表

序列 -o 兩個 過濾 重要 pro 讀取 sha gns ACL訪問控制列表理論部分:在學習過程中我們知道了網絡的聯通和通信,但是在實際環境中網絡管理員經常會面臨為難的局面,如必須拒絕那些不希望訪問的連接,同時又要允許正常的訪問。那麽這時就誕生了ACL(訪問控制列表)下面

神州數碼標準訪問控制列表配置(ACL

mit p地址 ces 要求 layer ip route 技術 font 配置 實驗要求:熟練掌握標準訪問控制列表配置方法 拓撲如下 R1 enable  進入特權模式 config  進入全局模式 hostname R1  修改名稱 interface s0/1 

訪問控制列表acl權限

entos 格式 我們 系統 開啟 mas 權限 ask brush 訪問控制列表:acl??acl在centos7xfs文件系統中是默認開啟的;在centos6,以及6之前的版本,在安裝操作系統之前創建的文件系統也是默認開啟acl的,在安裝操作系統之後創建的文件系統是默認