ACL
ACL,即访问控制列表,是一种相对来说比较新颖且更细粒度的权限管理方式,可以针对任意用户和组进行细粒度的权限控制。目前绝大部分Unix系统都已经支持了ACL方式的权限控制,Linux 也从2.6版本的内核开始支持这个特性。
ZooKeeper的ACL权限控制和Unix/Linux操作系统中的ACL有一些区别,可以从三个方面来理解ACL机制,分别是:权限模式( Scheme)、 授权对象(ID)和权限(Permission)
,通常使用“scheme:id:permission
” 来标识一个有效的ACL信息。
权限模式;
权限模式用来确定权限验证过程中使用的检验策略。在ZooKeeper中,开发人员使用最多的就是以下四种权限模式。
-
IP
IP模式通过IP地址粒度来进行权限控制,例如配置了“ip:192. 168.0.110”,即表示权限控制都是针对这个IP地址的。同时,IP模式也支持按照网段的方式进行配置,例如“ip:192.168.0.1/24” 表示针对192.168.0.*这个IP段进行权限控制。 -
Digest
Digest是最常用的权限控制模式,也更符合我们对于权限控制的认识,其以类似于“username:password”形式的权限标识来进行权限配置,便于区分不同应用来进行权限控制。
当我们通过“username:password”形式配置了权限标识后,ZooKeeper 会对其先后进行两次编码处理,分别是SHA-1算法加密和BASE64编码,其具体实现由DigestAuthenticationProvider.generateDigest(String idPassword)函数进行封装
public class DigestAuthenticationProviderUsage {
public static void main(String[] args) throws NoSuchAlgorithmException {
System.out.println(DigestAuthenticationProvider.generateDigest("foo:zk-book"));
}
}
foo:kWN6aNSbjcKWPqjiV7cg0N24raU=
-
World
World是一种最开放的权限控制模式,从其名字中也可以看出,事实上这种权限控制方式几乎没有任何作用,数据节点的访问权限对所有用户开放,即所有用户都可以在不进行任何权限校验的情况下操作ZooKeeper上的数据。另外,World 模式也可以看作是一种特殊的Digest模式,它只有一个权限标识,即“world:anyone" -
Super
Super模式,顾名思义就是超级用户的意思,也是一种特殊的Digest模式。在Super模式下,超级用户可以对任意ZooKeeper上的数据节点进行任何操作。
授权对象ID:
授权对象指的是权限赋予的用户或一个指定实体,例如IP 地址或是机器等。在不同的权限模式下,授权对象是不同的:
权限:Permission
权限就是指那些通过权限检查后可以被允许执行的操作。在ZooKeeper中,所有对数据的操作权限分为以下五大类:
CREATE (C) :
数据节点的创建权限,允许授权对象在该数据节点下创建子节点。DELETE(D):
子节点的删除权限,允许授权对象删除该数据节点的子节点。READ(R):
数据节点的读取权限,允许授权对象访问该数据节点并读取其数据内容或子节点列表等。WRITE(W):
数据节点的更新权限,允许授权对象对该数据节点进行更新操作。ADMIN (A) :
数据节点的管理权限,允许授权对象对该数据节点进行ACL相关的设置操作。
权限扩展体系
我们已经讲解了ZooKeeper 默认提供的IP、 Digest、 World 和Super这四种权限模式,在绝大部分的场景下,这四种权限模式已经能够很好地实现权限控制的目的。同时,ZooKeeper提供了特殊的权限控制插件体系,允许开发人员通过指定方式对ZooKeeper的权限进行扩展。这些扩展的权限控制方式就像插件一样插入到ZooKeeper 的权限体系中去,因此在ZooKeeper的官方文档中,也称该机制为“Pluggable ZooKeeperAuthentication"
实现自定义权限控制器:
要实现自定义权限控制器非常简单,ZooKeeper定义了一个标准权限控制器需要实现的接口: org.apache. zookeeper . server . auth. AuthenticationProvider
public interface AuthenticationProvider {
String getScheme();
KeeperException.Code handleAuthentication(ServerCnxn cnxn, byte authData[]);
boolean matches(String id, String aclExpr);
boolean isAuthenticated();
boolean isValid(String id);
}
用户可以基于该接口来进行自定义权限控制器的实现。事实上,在前面内容中提到的几个权限模式,对应的就是ZooKeeper 自带的Diges tAuthenticationProvider和IPAuthenticationProvider两个权限控制器。
注册自定义权限控制器:
完成自定义权限控制器的开发后,接下去就需要将该权限控制器注册到ZooKeeper服务器中去了。ZooKeeper支持通过系统属性和配置文件两种方式来注册自定义的权限控制
- 系统属性 -Dzookeeper.zuthProvider.X
在Zookeeper启动参数中配置类似于如下的系统属性:
-Dzookeeper.authProvider.1=com.zkbook.CustomAuthenticationProvider
- 配置文件方式
在zoo.cfg配置文件中配置类似于如下的配置项:
authProvider.1=com.zkbook.CustomAuthenticationProvider
对于权限控制器的注册,ZooKeeper采用了延迟加载的策略,即只有在第一次处理包含权限控制的客户端请求时,才会进行权限控制器的初始化。同时,ZooKeeper 还会将所有的权限控制器都注册到ProviderRegistry中去。在具体的实现中,ZooKeeper首先会将DigestAuthenticationProvider和IPAuthenticationProvider这两个默认的控制器初始化,然后通过扫描zookeeper . authProvider 。这一系统属性,获取到所有用户配置的自定义权限控制器,并完成其初始化。
ACL管理
设置ACL:
通过zkCli脚本登录ZooKeeper服务器后,可以通过两种方式进行ACL的设置。一种是在数据节点创建的同时进行ACL权限的设置,命令格式如下:
create [-s] [-e] path data acl
一种是在创建结点后设置ACl
setAcl path acl
Super模式的用法:
要使用管理员权限,首先需要在Zookeeper服务器上开启Super模式,方法是在Zookeeper服务器启动的时候,添加如下系统属性:
-Dzookeeper.DigestAuthenticationProvider.superDigest=foo:kWN6aNSbjcKwPqjiV7cg0N24raU=
其中,“foo” 代表了一个超级管理员的用户名;“kWN6aNSbjcK WPqjiV7cg0N24raU=”是可变的,由ZooKeeper 的系统管理员来进行自主配置,此例中使用的是“ foo:zk-book"的编码。完成对ZooKeeper服务器的Super模式的开启后,就可以在应用程序中使用了。