概述
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要更为常用一些。
- auth 与 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:2181(CONNECTED) 0] create /testDir/testAcl test-data
# 创建一个子节点
Created /testDir/testAcl
[zk: localhost:2181(CONNECTED) 1] 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:2181(CONNECTED) 9] setAcl /testDir/testAcl auth::crw
[zk: localhost:2181(CONNECTED) 10] setAcl /testDir/testAcl auth:test:test:crw
[zk: localhost:2181(CONNECTED) 11] 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-01 /usr/local/zookeeper-3.4.11/bin]# vim zkServer.sh
# 找到nohup那一行,加入以下内容
"-Dzookeeper.DigestAuthenticationProvider.superDigest=user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s="
注:user1是用户名,后面那一大串是加密后的密文密码
如下图:
2、修改完之后,需要重启zookeeper服务才能生效
[root@study-01 /usr/local/zookeeper-3.4.11/bin]# ./zkServer.sh restart
3、使用超级管理员用户
[root@study-01 ~]# 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的服务可以访问相关的节点,防止混乱
最后
以上就是忧伤酒窝为你收集整理的什么?Zookeeper | ACL权限控制的全部内容,希望文章能够帮你解决什么?Zookeeper | ACL权限控制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复