ThinkInOpenSource / zookeeper

zookeeper实践
Apache License 2.0
1 stars 0 forks source link

ACL权限控制 #2

Open luoxn28 opened 6 years ago

luoxn28 commented 6 years ago

zookeeper使用ACL来控制访问znode,ACL的实现和unix文件的权限实现类似:它采用权限位来控制哪些操作被允许,哪些操作被禁止;但是和unix不同的是,ACL没有所有者(user,文件所有者)、组(group)和其他(other)的概念。

zookeeper ACL支持的权限认证方案,分为3个维度,分别是scheme,user,permission。通常表示为scheme:id, permission,其中scheme表示使用何种方式来进行访问控制,Id代表用户,Permission表示有什么权限。

zookeeper支持如下权限,简单的说就是cdrwa(可以理解成CURD加上一个A)。

查看ACL权限使用命令 getAcl path: image

ACL内置的scheme有:

如果需要实现自己定义的Scheme,可以实现org.apache.zookeeper.server.auth.AuthenticationProvider接口。

一个使用ACL来创建znode的程序示例,zookeeper client使用的是curator

@Test
public void testAcl() throws Exception {
    ACL acl1 = new ACL(ZooDefs.Perms.CREATE,
            new Id("digest", DigestAuthenticationProvider.generateDigest("luo:123456")));
    ACL acl2 = new ACL(ZooDefs.Perms.READ,
            new Id("digest", DigestAuthenticationProvider.generateDigest("nan:123456")));

    List<ACL> aclList = new ArrayList<>();
    aclList.add(acl1);
    aclList.add(acl2);

    ZooKeeper zk = new ZooKeeper("192.168.85.128:2181", 3000,
            watchedEvent -> {
                System.out.println("watchEvent: " + watchedEvent);
            });

    String path = "/test";
    if (zk.exists(path, true) == null) {
        String result = zk.create(path, "acl测试".getBytes(), aclList, CreateMode.PERSISTENT);
        System.out.println(result);
    }

    zk.addAuthInfo("digest", "luo:123456".getBytes());
    zk.addAuthInfo("digest", "nan:123456".getBytes());

    byte[] data = zk.getData(path, true, null);
    System.out.println(new String(data));
}

注意,zookeeper中的每个znode节点的ACL都是独立的,也就是说子znode不会继承父节点的ACL。例如:Znode /app对于ip为172.16.16.1只有只读权限,而/app/status是world可读,那么任何人都可以获取/app/status,所以在Zookeeper中权限是没有继承和传递关系的,每个Znode的权限都是独立存在的。

虽然子znode和父znode的ACL权限是独立的,但是创建znode时父znode必须存在,否则会报异常,因为在创建子zonode时,会对父znode进行synchronized加锁,并更新父znode的cversion、pzxid等信息。

为什么zookeeper中znode节点的ACL权限没有继承和传递特性呢,而Linux的文件系统是有呢?我的理解是,Linux中的文件Node是类似于Node树的结构,比如/app/data路径,Linux中想要获取到data数据,首先需要到/app节点(该节点是目录),然后在获取该(目录)节点下的data文件数据;而zookeeper中数据是保存在内存中的,准确来说是保存在final ConcurrentHashMap<String /* path */, DataNode> nodes = new ConcurrentHashMap<String, DataNode>()中的,zookeeper想要获取到/app/data数据,直接根据/app/data路径直接就可以获取,不会跟路径/app的znode节点有关联。 还有一点,zookeeper的设计目标是分布式一致性解决方案,所以权限控制不是其关注的重点(虽然权限控制也是比较重要的~)。

参考资料: 1、https://blog.csdn.net/qianshangding0708/article/details/50114671