zookeeper ACL 权限验证

  

转载地址:http://www.wuzesheng.com/?p=2438


Access Control在分布式系统中重要性是毋庸置疑的,今天这篇文章来介绍一下Zookeeper中的Access Control(ACL)。

  • 1. 概述
    传统的文件系统中,ACL分为两个维度,一个是属组,一个是权限,子目录/文件默认继承父目录的ACL。而在Zookeeper中,node的ACL是没有继承关系的,是独立控制的。Zookeeper的ACL,可以从三个维度来理解:一是scheme; 二是user; 三是permission,通常表示为scheme:id:permissions, 下面从这三个方面分别来介绍:

    (1)scheme: scheme对应于采用哪种方案来进行权限管理,zookeeper实现了一个pluggable的ACL方案,可以通过扩展scheme,来扩展ACL的机制。zookeeper-3.4.4缺省支持下面几种scheme:

    • world: 它下面只有一个id, 叫anyone, world:anyone代表任何人,zookeeper中对所有人有权限的结点就是属于world:anyone的
    • auth: 它不需要id, 只要是通过authentication的user都有权限(zookeeper支持通过kerberos来进行authencation, 也支持username/password形式的authentication)
    • digest: 它对应的id为username:BASE64(SHA1(password)),它需要先通过username:password形式的authentication
    • ip: 它对应的id为客户机的IP地址,设置的时候可以设置一个ip段,比如ip:192.168.1.0/16, 表示匹配前16个bit的IP段
    • super: 在这种scheme情况下,对应的id拥有超级权限,可以做任何事情(cdrwa)

    另外,zookeeper-3.4.4的代码中还提供了对sasl的支持,不过缺省是没有开启的,需要配置才能启用,具体怎么配置在下文中介绍。

    • sasl: sasl的对应的id,是一个通过sasl authentication用户的id,zookeeper-3.4.4中的sasl authentication是通过kerberos来实现的,也就是说用户只有通过了kerberos认证,才能访问它有权限的node.

    (2)id: id与scheme是紧密相关的,具体的情况在上面介绍scheme的过程都已介绍,这里不再赘述。

    (3)permission: zookeeper目前支持下面一些权限:

    • CREATE(c): 创建权限,可以在在当前node下创建child node
    • DELETE(d): 删除权限,可以删除当前的node
    • READ(r): 读权限,可以获取当前node的数据,可以list当前node所有的child nodes
    • WRITE(w): 写权限,可以向当前node写数据
    • ADMIN(a): 管理权限,可以设置当前node的permission
  • 2. 实现
    如前所述,在zookeeper中提供了一种pluggable的ACL机制。具体来说就是每种scheme对应于一种ACL机制,可以通过扩展scheme来扩展ACL的机制。在具体的实现中,每种scheme对应一种AuthenticationProvider。每种AuthenticationProvider实现了当前机制下authentication的检查,通过了authentication的检查,然后再进行统一的permission检查,如此便实现了ACL。所有的AuthenticationProvider都注册在ProviderRegistry中,新扩展的AuthenticationProvider可以通过配置注册到ProviderRegistry中去。下面是实施检查的具体实现:

  • void checkACL(ZooKeeperServer zks, List<acl> acl, int perm,
       List<id> ids) throws KeeperException.NoAuthException {
     if (skipACL) {
       return;
     }
     if (acl == null || acl.size() == 0) {
       return;
     }
     for (Id authId : ids) {
       if (authId.getScheme().equals("super")) {
         return;
       }
     }
     for (ACL a : acl) {
       Id id = a.getId();
       if ((a.getPerms() & perm) != 0) {
         if (id.getScheme().equals("world")
             && id.getId().equals("anyone")) {
           return;
         }   
         AuthenticationProvider ap = ProviderRegistry.getProvider(id
             .getScheme());
         if (ap != null) {
           for (Id authId : ids) {
             if (authId.getScheme().equals(id.getScheme())
                 && ap.matches(authId.getId(), id.getId())) {
               return;
             }   
           }   
         }   
       }   
     }
     throw new KeeperException.NoAuthException();
    }



  • 3. server配置
    • 可以通过下面两种方式把新扩展的AuthenticationProvider注册到ProviderRegistry:
      配置文件:在zookeeper的配置文件中,加入authProvider.$n=$classname即可
      JVM参数:启动Zookeeper的时候,通过-Dzookeeper.authProvider.$n=$classname的方式,把AuthenticaitonProvider传入
      在上面的配置中, $n是为了区分不同的provider的一个序号,只要保证不重复即可,没有实际的意义,通常用数字1,2,3等
    • 4. 管理ACL
      可以通过zookeeper client来管理ACL, zookeeper的发行包中提供了一个cli工具zkcli.sh,可以通过它来进行acl管理,

Zookeeper提供了几种认证方式 
* world:有个单一的ID,anyone,表示任何人。 
* auth:不使用任何ID,表示任何通过验证的用户(是通过ZK验证的用户?连接到此ZK服务器的用户?)。 
* digest:使用 用户名:密码 字符串生成MD5哈希值作为ACL标识符ID。权限的验证通过直接发送用户名密码字符串的方式完成, 
* ip:使用客户端主机ip地址作为一个ACL标识符,ACL表达式是以 addr/bits 这种格式表示的。ZK服务器会将addr的前bits位与客户端地址的前bits位来进行匹配验证权限。 

digest方式比较适合我们的业务,因此采用此种方式对Zookeeper进行权限控制。 

创建节点数据时: 
Java代码   收藏代码
  1. List<ACL> acls = new ArrayList<ACL>(2);     
  2.   
  3. Id id1 = new Id("digest", DigestAuthenticationProvider.generateDigest("admin:admin123"));  
  4. ACL acl1 = new ACL(ZooDefs.Perms.ALL, id1);  
  5.   
  6. Id id2 = new Id("digest", DigestAuthenticationProvider.generateDigest("guest:guest123"));  
  7. ACL acl2 = new ACL(ZooDefs.Perms.READ, id2);  
  8.   
  9. acls.add(acl1);  
  10. acls.add(acl2);  
  11.   
  12. ZooKeeper zk = new ZooKeeper("127.0.0.1:2181"10000new DefaultWatcher());  
  13. zk.create("/test"new byte[0], acls, CreateMode.PERSISTENT);  

登录Zookeeper读取节点数据时: 
Java代码   收藏代码
  1. ZooKeeper zk = new ZooKeeper("127.0.0.1:2181"10000new DefaultWatcher());  
  2. zk.addAuthInfo("digest""guest:guest123".getBytes());  
  3. byte[] value = zk.getData("/test"nullnew Stat());  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值