ZooKeeper的ACL权限控制

1.认识一下控制命令

要了解ZooKeeper的ACL权限控制,首先我们需要了解一下ZooKeeper客户端的权限控制的命令:

1、创建zk节点时,可以同时指定权限信息(可选)

create [-s] [-e] [-c] [-t ttl] path [data] [acl]

2、根据路径设置节点的权限(对一个已存在的节点)

setAcl [-s] [-v version] [-R] path acl

3、根据路径获取节点的权限

getAcl [-s] path

4、认证授权信息的命令(auth格式为用户名:密码, 密码为明文密码)

addauth scheme auth

那么 createsetAclacl 应该是什么样的格式呢?

[zk: localhost:2181(CONNECTED) 0] create /test
Created /test
[zk: localhost:2181(CONNECTED) 1] setAcl /test acl
acl does not have the form scheme:id:perm
Acl is not valid : /test
  1. 首先,创建一个新节点/test
  2. 然后,用setAcl为节点/test设置权限
  3. 接着,我们读这段报错acl does not have the form scheme:id:perm

我们知道了 acl 应该由三部分组成:scheme, id, perm。

2. ACL 权限控制

Zookeeper 的 ACL 权限控制,可以控制节点的读写操作,保证数据的安全性,Zookeeper ACL 权限设置分为 3 部分组成,分别是:权限模式(Scheme)、授权对象(ID)、权限信息(Permission)。最终组成⼀条例如scheme:id:permission 格式的 ACL 请求信息。

ZooKeeper 可以给每个节点设置不同的权限控制。

2.1 权限 Permission

首先,我们可能关心,对于某个数据节点,到底有哪些细分的权限呢?

权限就是指我们可以在数据节点上执⾏的操作种类(CRUD),如下所示:在 ZooKeeper 中已经定义好的权限有 5 种:

  1. 数据节点(c: create)创建权限,授予权限的对象可以在数据节点下创建⼦节点;
  2. 数据节点(w: wirte)更新权限,授予权限的对象可以更新该数据节点;
  3. 数据节点(r: read)读取权限,授予权限的对象可以读取该节点的内容以及⼦节点的列表信息;
  4. 数据节点(d: delete)删除权限,授予权限的对象可以删除该数据节点的⼦节点;
  5. 数据节点(a: admin)管理者权限,授予权限的对象可以对该数据节点体进⾏ ACL 权限设置。

1 和 4 其实就对应zk命令 createdelete;
2 和 3 主要对应zk命令 setget;
5 主要对应zk命令 setAclgetAcl;

2.2 权限模式 Scheme

接着,我们就该了解,到底有哪些授权的模式?而授权对象(ID)其实是和权限模式(Scheme)对应使用的。

  1. 所有人可用模式(world:anyone:perm): world模式只有一个授权对象id,anyone,表示任何一个人都有权限。

  2. 仅当前认证用户可用模式(auth:user:password:perm): auth模式的授权对象是当前认证用户。

    • 提供此方案是为了方便用户创建znode,然后将对该znode的访问限制为仅该用户,这是一个常见的用例;
    • 如果没有通过身份验证的用户,则使用身份验证方案设置ACL将失败;
  3. 口令认证模式(digest:user:password:perm): digest模式使用 username:password 字符串生成MD5散列,然后将其用作授权对象ID。

    • 这里的 password 不是明文,而是 base64编码(SHA1摘要算法(明文密码))的结果。因此和 addauth 的使用习惯不相同;
    • 这里面还有一种特殊情况,就是认证 超级管理员 的口令后,ZooKeeper客户端可以对 ZooKeeper 上的任意数据节点进⾏任意操作;
  4. IP认证模式:ip(ip:addr:perm 或者 ip:addr/bits:perm)模式使用客户端主机ip作为授权对象ID。

    • 可以针对⼀个 IP 或者⼀段 IP 地址授予某种权限。
    • ⽐如我们可以让⼀个 IP 地址为“ip:192.168.0.110”的机器对服务器上的某个数据节点具有写⼊的权限。
    • 或者也可以通过“ip:192.168.0.1/24”给⼀段 IP 地址的机器赋权。
  5. SSL安全认证模式:x509模式,使用安全端口时,客户端将自动进行身份验证,并设置x509方案的身份验证信息。

    • 如果对这种方式感兴趣,见参考文档 ZooKeeper安全认证机制:SSL 阅读

3. 实战

3.1 如何获取加密的密码?

我们已经知道了 digest认证模式需要用到 base64编码的 SHA1密码,那么怎么获取呢?

创建一个Maven项目,加入依赖:

<dependency>
  <groupId>org.apache.zookeeper</groupId>
  <artifactId>zookeeper</artifactId>
  <version>3.5.9</version>
</dependency>

然后,写一个Main程序:

import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;

import java.security.NoSuchAlgorithmException;

public class Main {

    public static void main(String[] args) throws NoSuchAlgorithmException {
        // 输出:reader:FIlPshmj74ilCpU6QOfBN00zY9w=
        System.out.println(DigestAuthenticationProvider.generateDigest("reader:reader"));
        // 输出:reader:JLVf6B6eexF5jTpORnfdSP/IFVk=,但这个是错误的
        // System.out.println(DigestAuthenticationProvider.generateDigest("reader"));
    }
}

易错点: DigestAuthenticationProvider.generateDigest 参数是 user:password 格式,而不是单纯的 password

  • 虽然,直接使用 reader 作为参数不会报错,但是你 addauth reader:reader path会一直验证失败。

3.2 setAcl授权和addauth认证

[zk: localhost:2181(CONNECTED) 0] create -e /test
Created /test
[zk: localhost:2181(CONNECTED) 1] setAcl /test digest:reader:FIlPshmj74ilCpU6QOfBN00zY9w=:r
[zk: localhost:2181(CONNECTED) 2] get /test
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /test
[zk: localhost:2181(CONNECTED) 3] addauth digest reader:reader
[zk: localhost:2181(CONNECTED) 4] get /test
null
[zk: localhost:2181(CONNECTED) 5] quit
  • 首先,创建一个临时数据结点 /test
  • 然后,设置口令认证访问该结点,
  • 在 addauth 之前,是没有权限读取 /test 的数据;但是在 addauth 之后,允许读操作,
  • 最后,退出当前客户端,临时节点 /test 会被清除。

然后,我们再看一下使用错误的密码摘要的情况:

3.3 create授权和addauth认证

创建节点的同时,进行授权,这个地方有个易错点:

[zk: localhost:2181(CONNECTED) 0] create -e /test digest:reader:FIlPshmj74ilCpU6QOfBN00zY9w=:r
Created /test
[zk: localhost:2181(CONNECTED) 1] get /test
digest:reader:FIlPshmj74ilCpU6QOfBN00zY9w=:r
[zk: localhost:2181(CONNECTED) 2] quit

你会发现,你没有 addauth 也得到了数据,但是数据和你的acl一样。

问题就在于,如果你想在创建节点的同时设置权限控制,那么你就必须初始化数据。否则,就会把acl字符串当成数据存储。

所以,我们调整一下:

[zk: localhost:2181(CONNECTED) 0] create -e /test data digest:reader:FIlPshmj74ilCpU6QOfBN00zY9w=:r
Created /test
[zk: localhost:2181(CONNECTED) 1] get /test
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /test
[zk: localhost:2181(CONNECTED) 2] addauth digest reader:reader
[zk: localhost:2181(CONNECTED) 3] get /test
data
[zk: localhost:2181(CONNECTED) 3] quit

3.4 能否给同一个结点设置多个ACL?

首先,我又准备了几个账号:

user:password user:digest
user1:pwd1 user1:a9l5yfb9zl8WCXjVmi5/XOC0Ep4=
user2:pwd2 user2:LJcj8Pt1rGm2pXKbdJDGH8+Bn+0=
user3:pwd3 user3:vTWpf7+XOMH/ifDkxE6KmhSUCpA=

操作如下:

[zk: localhost:2181(CONNECTED) 0] create /user1 LiLei digest:user1:a9l5yfb9zl8WCXjVmi5/XOC0Ep4=:ra
Created /user1
[zk: localhost:2181(CONNECTED) 1] get /user1
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /user1
[zk: localhost:2181(CONNECTED) 2] addauth digest user1:pwd1
[zk: localhost:2181(CONNECTED) 3] get /user1
LiLei
[zk: localhost:2181(CONNECTED) 4] getAcl /user1
'digest,'user1:a9l5yfb9zl8WCXjVmi5/XOC0Ep4=
: ra
[zk: localhost:2181(CONNECTED) 5] setAcl /user1 digest:user2:LJcj8Pt1rGm2pXKbdJDGH8+Bn+0=:rw
[zk: localhost:2181(CONNECTED) 6] getAcl /user1
Authentication is not valid : /user1
[zk: localhost:2181(CONNECTED) 7] addauth digest user2:pwd2
[zk: localhost:2181(CONNECTED) 8] getAcl /user1
'digest,'user2:x
: rw
[zk: localhost:2181(CONNECTED) 9] quit
  • 首先,创建数据结点/user1,并且授权口令 user1:pwd1 允许读取和管理权限;
  • 接着,使用 user1:pwd1 完成 addauth 授权认证,并读取到了 /user1 对应的数据和权限信息;
  • 然后,修改了 ACL,原先的 user1:pwd1 口令失效了;
  • 重新使用 user2:pwd2 完成 addauth 授权认证,再次读取权限信息,此时发现新的权限信息覆盖了原来的权限信息;

综上所述,同一个znode不支持多个 ACL。

3.5 多次addauth可以获取权限合集?

实验如下:

[zk: localhost:2181(CONNECTED) 0] create /user2 Lisa digest:user2:LJcj8Pt1rGm2pXKbdJDGH8+Bn+0=:ra
Created /user2
[zk: localhost:2181(CONNECTED) 1] create /user3 Simon digest:user3:vTWpf7+XOMH/ifDkxE6KmhSUCpA=:ra
Created /user3
[zk: localhost:2181(CONNECTED) 2] addauth digest user2:pwd2
[zk: localhost:2181(CONNECTED) 3] get /user2
Lisa
[zk: localhost:2181(CONNECTED) 4] get /user3
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /user3
[zk: localhost:2181(CONNECTED) 5] addauth digest user3:pwd3
[zk: localhost:2181(CONNECTED) 7] get /user2
Lisa
[zk: localhost:2181(CONNECTED) 8] get /user3
Simon
[zk: localhost:2181(CONNECTED) 9] quit

由此可见,addauth 会取当前客户端认证后获取的权限合集。

3.6 权限受限怎么办?

  • 第一个方法是禁用 ACL 权限控制
  • 第二个方法是超级管理员模式

本文主要说的是 Docker 容器运行的 ZooKeeper 如何处理?

3.6.1 禁用 ACL 权限控制

★ 可以通过配置文件zoo.cfg中添加skipACL=yes进⾏配置,默认是no,可以配置为true, 则配置过的 ACL 将不再进⾏权限检测:

首先,用 docker images 查看下载的镜像:

如图所示,30993cacc7c9 就是 zookeeper:3.5.9 的 镜像ID。

# 简单解释一下参数:
# --name是给启动的容器取的名字,以后启动容器可以使用这个名字来启动
# -p 宿主主机端口:容器端口, 2181 是 zookeeper 的默认端口号, 因为宿主机已经有其他zookeeper容器占用了2181,所以此处改为2281
# --restart always 表示容器如果关闭退出就是重启
# -d 表示容器以后台守护进程启动
# -v 宿主机文件路径:容器文件路径
# 末尾的 30993cacc7c9 表示镜像ID
docker run --name zookeeper-1 -p 2281:2181 --restart always -d -v D:\DockerContainer\zookeeper\zoo.cfg:/conf/zoo.cfg 30993cacc7c9

然后 D:\DockerContainer\zookeeper\zoo.cfg 文件内容为:

skipACL=yes
dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
standaloneEnabled=true
admin.enableServer=true
server.1=localhost:2888:3888;2181

接着,登入容器 docker exec -it zookeeper-1 bash,启动zk客户端:

然后,做操作都不需要权限了:

[zk: localhost:2181(CONNECTED) 0] create /test data digest:user1:a9l5yfb9zl8WCXjVmi5/XOC0Ep4=:w
Created /test
[zk: localhost:2181(CONNECTED) 1] get /test
data
[zk: localhost:2181(CONNECTED) 2] delete /test

★ 可以通过设置额外配置参数skipACL=yes进⾏配置,默认是no,可以配置为true, 则配置过的ACL将不再进⾏权限检测

docker run --name=zookeeper-2 -p 2381:2181 --restart always -d -e ZOO_CFG_EXTRA="skipACL=yes" 30993cacc7c9

★ 可以通过添加JVM参数-Dzookeeper.skipACL=yes进⾏配置,默认是no,可以配置为true, 则配置过的ACL将不再进⾏权限检测

docker run --name=zookeeper-3 -p 2481:2181 --restart always -d -e JVMFLAGS="-Dzookeeper.skipACL=yes" 30993cacc7c9

3.6.2 超级管理员super

设置zk启动时的JVM参数为 -Dzookeeper.DigestAuthenticationProvider.superDigest=super1:WqkSAJNIl+iMSE0y/0xAI3lPT5o= 指定超管账号口令为 super1:admin

docker run --name=zookeeper-4 -p 2581:2181 --restart always -d -e JVMFLAGS="-Dzookeeper.DigestAuthenticationProvider.superDigest=super1:WqkSAJNIl+iMSE0y/0xAI3lPT5o=" 30993cacc7c9

接着,登入容器并启动zk客户端:

以下实验部分:

[zk: localhost:2181(CONNECTED) 0] create /test data digest:user1:a9l5yfb9zl8WCXjVmi5/XOC0Ep4=:w
Created /test
[zk: localhost:2181(CONNECTED) 1] get /test
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /test
[zk: localhost:2181(CONNECTED) 2] addauth digest super1:admin
[zk: localhost:2181(CONNECTED) 3] get /test
data
[zk: localhost:2181(CONNECTED) 4] quit
  • 我们允许用户 user1 对路径为 /test 的节点进行数据的修改;
  • 我们获取数据时,提示没有权限;
  • 此时,赋予当前客户端超级管理员权限;
  • 超级管理员的所有操作都会跳过权限检查。

简单的客户端代码:

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;

public class Test {

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        Watcher connectedWatcher = event -> {
            if (Watcher.Event.KeeperState.SyncConnected.equals(event.getState())
                    && Watcher.Event.EventType.None.equals(event.getType())
                    && event.getPath() == null) {
                System.out.println("========= ZooKeeper connected ==========");
                latch.countDown();
            }
        };
        try (ZooKeeper zk = new ZooKeeper("localhost:2581", 30, connectedWatcher)) {
            latch.await();
            try {
                byte[] data = zk.getData("/test", null, null);
                Optional.ofNullable(data).map(String::new).ifPresent(value -> System.out.println("Node /test data: " + value));
            } catch (KeeperException e) {
                System.out.println("Something wrong:" + e.getMessage());
            }
            zk.addAuthInfo("digest", "super1:admin".getBytes());
            System.out.println("========= after addauth super ==========");
            try {
                byte[] data = zk.getData("/test", null, null);
                Optional.ofNullable(data).map(String::new).ifPresent(value -> System.out.println("Node /test data: " + value));
            } catch (KeeperException e) {
                System.out.println("Something wrong:" + e.getMessage());
            }
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

执行结果:

========= ZooKeeper connected ==========
Something wrong:KeeperErrorCode = NoAuth for /test
========= after addauth super ==========
Node /test data: data

参考文档

ZooKeeper ACLPermissions 阅读
ZooKeeper安全认证机制:SSL 阅读
Docker ZooKeeper 官方文档 阅读
docker windows下挂载目录和文件 阅读
Zookeeper Acl权限 超级用户权限 怎么跳过ACL密码/账户验证 阅读

原文地址:https://www.cnblogs.com/kendoziyu/p/14980978.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


#一、什么是ZooKeeper**ZooKeeper是一个分布式服务协调框架**,提供了分布式数据一致性的解决方案,基于ZooKeeper的**数据结构,Watcher,选举机制**等特点,可以**实现数据的发布/订阅,软负载均衡,命名服务,统一配置管理,分布式锁,集群管理**等等。#二、为什么使用ZooKeeperZooKeeper能保证:*
2.ZooKeeper介绍2.1.ZooKeeper由来正式介绍ZooKeeper之前,我们先来看看ZooKeeper的由来,还挺有意思的。下面这段内容摘自《从Paxos到ZooKeeper》第四章第一节,推荐大家阅读一下:ZooKeeper最早起源于雅虎研究院的一个研究小组。在当时,研究人员发现,在雅虎内部很
Zookeeper概述1.ZooKeeper最为主要的使⽤场景,是作为分布式系统的分布式协同服务。2.分布式系统中每台服务器的算力和资源都是有限的,但是我们通过分布式系统组成集群就可以对算力和资源进行无限扩张,但是分布式节点间的协调就成了问题。3.就像我们的开发团队之间的协作一
环境:1.VMware®Workstation12Pro 2.CentOS7 3.zookeeper-3.4.6安装步骤1.下载zookeeper本文使用的zookeeper下载地址如下(大家也可以下载其它版本)链接:https://pan.baidu.com/s/1Ab9F53jNy7upsrYHCacWrw 提取码:jqyn 
###1\.面试官:工作中使用过Zookeeper嘛?你知道它是什么,有什么用途呢?**小菜鸡的我:***有使用过的,使用ZooKeeper作为**dubbo的注册中心**,使用ZooKeeper实现**分布式锁**。*ZooKeeper,它是一个开放源码的**分布式协调服务**,它是一个集群的管理者,它将简单易用的接口提供给用户。*
##2\.ZooKeeper介绍###2.1\.ZooKeeper由来正式介绍ZooKeeper之前,我们先来看看ZooKeeper的由来,还挺有意思的。下面这段内容摘自《从Paxos到ZooKeeper》第四章第一节,推荐大家阅读一下:>ZooKeeper最早起源于雅虎研究院的一个研究小组。在当时,研究人员发现,在雅虎内部很
环境准备:windows:jdk8+nginx+ab压测centos7:redis+zookeeper3.3.6ab下载链接:https://www.apachelounge.com/download/测试思路:windows下使用springboot编写秒杀接口,商品数据存在redis,运行三个服务,利用nginx做代理,使用ab分别测试单机锁,自实现zookeeper分布式锁和Curator
由于只有一台电脑,所以搭建一个伪集群(伪集群就是在一台电脑上模拟搭建集群,走不同端口启动,真实的情况在每台机器上搭建一个zookeeper或者每台机器两个zookeeper等),道理是一样的,只不过要注意别被防火墙或者安全组规则挡住了zookeeper节点间的通信,每个节点直接的网络要是通的。集群数
常用命令总结(linux运行.sh结尾的脚本,window运行.cmd结尾的脚本,一下均为linux运行的,直接将.sh改为.cmd即可):linux环境:1.启动ZK服务:bin/zkServer.shstart2.查看ZK服务状态:bin/zkServer.shstatus3.停止ZK服务:bin/zkServer.shstop4.重启ZK服务:bin/zkServer.shrest
Kubernetes简介Kubernetes(简称K8S,K和S之间有8个字母)是用于自动部署,扩展和管理容器化应用程序的开源系统。它将组成应用程序的容器组合成逻辑单元,以便于管理和服务发现。Kubernetes源自Google15年生产环境的运维经验,同时凝聚了社区的最佳创意和实践。Kubernetes具有如下特性:
###正文ZooKeeper很流行,有个基本的疑问:*ZooKeeper是用来做什么的?*之前没有ZK,为什么会诞生ZK?OK,解答一下上面的疑问:(下面是凭直觉说的)*ZooKeeper是用于简化分布式应用开发的,对开发者屏蔽一些分布式应用开发过程中的底层细节*ZooKeeper对外暴露简单的API,用于支持分
#一、什么是ZooKeeper**ZooKeeper是一个分布式服务协调框架**,提供了分布式数据一致性的解决方案,基于ZooKeeper的**数据结构,Watcher,选举机制**等特点,可以**实现数据的发布/订阅,软负载均衡,命名服务,统一配置管理,分布式锁,集群管理**等等。#二、为什么使用ZooKeeperZooKeeper能保证:*
点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人。文章不定期同步公众号,还有各种一线大厂面试原题、我的学习系列笔记。zoo.cfg即/usr/local/java/zookeeper/conf下的zoo_sample.cfgzoo.cfg内含参数:tickTime、initLimit、syncLimit、dataDir、dataLogDir、clientPort
正文ZooKeeper很流行,有个基本的疑问:ZooKeeper是用来做什么的?之前没有ZK,为什么会诞生ZK?OK,解答一下上面的疑问:(下面是凭直觉说的)ZooKeeper是用于简化分布式应用开发的,对开发者屏蔽一些分布式应用开发过程中的底层细节ZooKeeper对外暴露简单的API,用于支持分布式应用开
#**NO1:说说zookeeper是什么?**ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现(Chubby是不开源的),它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供
正文ZooKeeper很流行,有个基本的疑问:ZooKeeper是用来做什么的?之前没有ZK,为什么会诞生ZK?OK,解答一下上面的疑问:(下面是凭直觉说的)ZooKeeper是用于简化分布式应用开发的,对开发者屏蔽一些分布式应用开发过程中的底层细节ZooKeeper对外暴露简单的API,用于支持分布式应用开
NO1:说说zookeeper是什么?ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现(Chubby是不开源的),它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供
#**NO1:说说zookeeper是什么?**ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现(Chubby是不开源的),它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供
一、什么是ZooKeeperZooKeeper是一个分布式服务协调框架,提供了分布式数据一致性的解决方案,基于ZooKeeper的数据结构,Watcher,选举机制等特点,可以实现数据的发布/订阅,软负载均衡,命名服务,统一配置管理,分布式锁,集群管理等等。二、为什么使用ZooKeeperZooKeeper能保证:更新请求
#**NO1:说说zookeeper是什么?**ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现(Chubby是不开源的),它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供