6.1 使用ACL

2018-06-01 18:47:58.0

    每次创建znode节点时,必须设置访问权限,而且子节点并不会继承父节点的访问权限。访问权限的检查也是基于每个znode节点的,即使无权访问某个节点的父节点,也不妨碍他可以访问这个节点。

    ZooKeeper通过访问控制表(ACL)来控制访问权限。一个ACL的形式如下:

    scheme:auth-info。

    scheme:对应了一组内置的鉴权模式;
    auth-info:对于特定模式的鉴权信息

    ZooKeeper通过检查客户端进程访问每个节点时提交上来的授权信息来保证安全性。如果一个进程没有提供鉴权信息,或者鉴权信息与要请求的znode节点的信息不匹配,进程就会收到一个权限错误。

    建立会话以后,需要通过addAuthInfo方法来增加鉴权信息

public void addAuthInfo(String scheme, byte auth[]);

6.1.1 内置的鉴权模式

    ZooKeeper提供了4种内置鉴权模式,分别是

    1、world:anyone,READ|WRITE|CREATE|DELETE|ADMIN
    2、super:
    3、digest:id:pass,READ|WRITE|CREATE|DELETE|ADMIN
    4、ip:10.11.12.0/24,READ

    之前使用过的OPEN_ACL_UNSAFE常量,所使用的策略就是第一种,看一下源码:

public final ArrayList<ACL> OPEN_ACL_UNSAFE = new ArrayList<ACL>(
                Collections.singletonList(new ACL(Perms.ALL, ANYONE_ID_UNSAFE)));
int ALL = READ | WRITE | CREATE | DELETE | ADMIN;
public final Id ANYONE_ID_UNSAFE = new Id("world", "anyone");

    而world这种模式,只能用anyone这种auth-info

    另一种特殊的内置模式为管理员所使用的super模式,该模式不会被列入到ACL中,但可以用于ZooKeeper的鉴权。一个客户端通过super鉴权模式连接到ZooKeeper后, 不会被任何节点的ACL所限制。

    另外两个主要使用的鉴权模式是digest和ip。

    看一下digestg与ip的测试代码:

public class ACLTest {
    final static String SCHEME_DIGEST = "digest";

    public static void main(String[] args) throws KeeperException, InterruptedException, NoSuchAlgorithmException {
        createAndSetACL();
        access("digest", "xuyh:123456", "/apps/ins-c-platform");
        access(null, null, "/apps/blacklist");

    }

    public static void createAndSetACL() throws KeeperException, InterruptedException, NoSuchAlgorithmException {
        ZKClient zkClient = ZKClient.instance();
        //world:anyone:READ|WRITE|CREATE|DELETE|ADMIN
        zkClient.create("/apps", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

        //digest:xuyh:123:READ|WRITE|CREATE|DELETE|ADMIN
        List<ACL> aclList = acl("digest", "xuyh:123456", ZooDefs.Perms.ALL);
        zkClient.create("/apps/ins-c-platform", "c-data".getBytes(), aclList, CreateMode.PERSISTENT);


        List<ACL> aclList1 = acl("ip", "127.0.0.1/24", ZooDefs.Perms.READ | ZooDefs.Perms.WRITE);
        zkClient.create("/apps/blacklist", "192.168.1.1".getBytes(), aclList1, CreateMode.PERSISTENT);

    }

    public static List<ACL> acl(String scheme, String idPass, int perms) throws NoSuchAlgorithmException {
        if (SCHEME_DIGEST.equals(scheme)) {
            idPass = DigestAuthenticationProvider.generateDigest(idPass);
        }
        Id id = new Id(scheme, idPass);
        ACL acl = new ACL(perms, id);

        List<ACL> aclList = new ArrayList<>();
        aclList.add(acl);
        return aclList;
    }

    //java -cp ./lib/jline-0.9.94.jar:./lib/log4j-1.2.16.jar:lib/netty-3.10.5.Final.jar:lib/slf4j-api-1.6.1.jar:lib/slf4j-log4j12-1.6.1.jar:lib/log4j-1.2.16.jar:zookeeper-3.4.10.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider xuyh:123456
    public static void access(String scheme, String authInfo, String path) throws KeeperException, InterruptedException {
        ZKClient zkClient = ZKClient.instance();
        if (SCHEME_DIGEST.equals(scheme)) {
            //只有digest模式才需要通过addAuthInfo添加
            zkClient.addAuthInfo(scheme, authInfo.getBytes());
        }
        byte[] d = zkClient.getData(path, false, null);
        System.out.println(new String(d));
    }

    public void clean() {

    }
}

    其中READ|WRITE|CREATE|DELETE|ADMIN前四个好理解,最后一个,是修改ACL的权限。

    ip鉴权模式需要提供网络地址和掩码,因为需要通过客户端的地址进来ACL策略的检查,客户端在使用ip模式的ACL策略访问znode节点时,不需要调用addAuthInfo方法。

6.1.2 SASL和Kerberos

    ZooKeeper提供的默认鉴权方式还有些问题。例如新的开发人员加入或旧的开发人员离开,都需要变更所有涉及的ACL,可以通过组来避免这种情况;另外,如果想修改开发人员的密码,目前的情况,也需要修改所有涉及的ACL策略;最后,如果网络变更,ip也不是最好的方式。

    SASL(Simple Authentication and Security Layer)简单认证与安全层,它将底层的鉴权模式抽象为一个框架,因此应用程序可以使用SASL框架和它支持的各种协议。在ZooKeeper中,SASL常常使用Kerberos协议。在使用SASL模式时,sasl作为模式名,id则使用客户端的Kerberos的ID.

    SASL是ZooKeeper的扩展鉴权模式,因此需要通过配置参数或Java系统中的参数激活。如果采用ZooKeeper的配置文件方式,需要使用authProvider.XXX配置参数,如果需要通过系统参数方式,需要使用zookeeper.authProvider.XXX作为参数,XXX一般采用以0开始的一个数字,参数值为org.apache.zookeeper.server.auth.SASLAuthenticationProvider

kdc集群主从搭建(kerberos相关) - CSDN博客

6.1.3 增加新的鉴权模式

    目前ZooKeeper中内置鉴权模式有world/super/digest/ip,已经实现了的扩展模式有sasl。

    ZooKeeper中还可以使用其他的任何鉴权模式。对于激活新的鉴权模式来说只是简单的编码问题。在org.apache.zookeeper.server.auth包中提供了一个名为AuthenticationProvider的接口类,可以实现自己的鉴权模式,