与策展人一起使用ACL

时间:2016-11-04 16:37:35

标签: java apache-zookeeper apache-curator

使用CuratorFramework,有人可以解释我的能力:

  1. 创建新路径
  2. 设置此路径的数据
  3. 获取此路径
  4. 使用用户名foo和密码bar?那些不了解这个用户/通行证的人将无法做任何事情。

    出于此问题的目的,我不关心通过明文发送的SSL或密码。

2 个答案:

答案 0 :(得分:14)

Apache Curator中的ACL用于访问控制。因此,ZooKeeper不提供任何身份验证机制,如clients who don't have correct password cannot connect to ZooKeeper or cannot create ZNodes。它可以做的是阻止未经授权的客户端访问特定的Znode / ZNode。为此,您必须设置CuratorFramework实例,如下所述。请记住,这将保证,使用给定ACL创建的ZNode可以由同一客户端或呈现相同身份验证信息的客户端再次访问。

首先,您应该按如下方式构建CuratorFramework instane。这里,connectString表示您的集合中的zookeeper服务器的ip and port组合的逗号分隔列表。

CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
                .connectString(connectString)
                .retryPolicy(new ExponentialBackoffRetry(retryInitialWaitMs, maxRetryCount))
                .connectionTimeoutMs(connectionTimeoutMs)
                .sessionTimeoutMs(sessionTimeoutMs);
    /*
     * If authorization information is available, those will be added to the client. NOTE: These auth info are
     * for access control, therefore no authentication will happen when the client is being started. These
     * info will only be required whenever a client is accessing an already create ZNode. For another client of
     * another node to make use of a ZNode created by this node, it should also provide the same auth info.
     */
    if (zkUsername != null && zkPassword != null) {
        String authenticationString = zkUsername + ":" + zkPassword;
        builder.authorization("digest", authenticationString.getBytes())
                .aclProvider(new ACLProvider() {
                    @Override
                    public List<ACL> getDefaultAcl() {
                        return ZooDefs.Ids.CREATOR_ALL_ACL;
                    }

                    @Override
                    public List<ACL> getAclForPath(String path) {
                        return ZooDefs.Ids.CREATOR_ALL_ACL;
                    }
                });
    }

CuratorFramework client = builder.build();

现在你必须开始它。

client.start();

创建路径。

client.create().withMode(CreateMode.PERSISTENT).forPath("/your/ZNode/path");

此处,CreateMode指定您要创建的节点类型。可用类型为PERSISTENT,EPHEMERAL,EPHEMERAL_SEQUENTIAL,PERSISTENT_SEQUENTIAL,CONTAINERJava Docs

如果您不确定/your/ZNode之前的路径是否已存在,您也可以创建它们。

client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/your/ZNode/path");

设置数据

您可以在创建ZNode或更高版本时设置数据。如果要在创建时设置数据,请将数据作为byte数组作为第二个参数传递给forPath()方法。

client.create().withMode(CreateMode.PERSISTENT).forPath("/your/ZNode/path","your data as String".getBytes());

如果你以后再做,(数据应该以字节数组的形式给出)

client.setData().forPath("/your/ZNode/path",data);

<强>最后

我不明白你的意思get this pathApache Curator是一个java客户端(比Curator Recipes更多)在后台使用Apache Zookeeper并隐藏Zookeeper的边缘情况和复杂性。在Zookeeper中,他们使用ZNodes的概念来存储数据。您可以将其视为Linux目录结构。所有ZNodePaths都应以/(root)开头,您可以根据需要继续指定目录,如ZNodePaths。例如:/someName/another/test/sample

ZNode structure

如上图所示,ZNode以树形结构组织。每个ZNode可以存储多达1MB的数据。因此,如果要检索存储在ZNode中的数据,则需要知道该ZNode的路径。 (就像您应该知道数据库的表和列以便检索数据一样)。

如果要在给定路径中检索数据,

client.getData().forPath("/path/to/ZNode");

当你想与策展人合作时,你必须知道这一切。

还有一件事

Apache Curator中的ACL用于访问控制。也就是说,如果您按如下方式设置ACLProvider

new ACLProvider() {
    @Override
    public List<ACL> getDefaultAcl () {
        return ZooDefs.Ids.CREATOR_ALL_ACL;
    }

    @Override
    public List<ACL> getAclForPath (String path){
        return ZooDefs.Ids.CREATOR_ALL_ACL;
    }
}

只有具有与创建者相同的凭据的客户端才能在以后获得对相应ZNode的访问权限。 Autherization详细信息设置如下(请参阅客户端构建示例)。还有其他可用的ACL模式,如OPEN_ACL_UNSAFE,如果将其设置为ACLProvider,则不执行任何访问控制。

authorization("digest", authorizationString.getBytes())

稍后将使用它们来控制对给定ZNode的访问。

简而言之,如果您想阻止他人干扰您的ZNode,您可以将ACLProvider设置为返回CREATOR_ALL_ACL并将授权设置为digest,如上所示。只有使用相同授权字符串("username:password")的CuratorFramework实例才能访问这些ZNode。但它不会阻止其他人在不干扰你的路径中创建ZNode。

希望你找到你想要的东西: - )

答案 1 :(得分:0)

这不是原始问题的一部分,但是我想我会分享一个我想出的解决方案,其中使用的凭据确定访问级别。

我没有太多运气找到任何示例并一直停留在此页面上,因此也许会对其他人有所帮助。我仔细阅读了Curator Framework的源代码,幸运的是,那里的org.apache.curator.framework.recipes.leader.TestLeaderAcls类为我指明了正确的方向。

因此在此示例中:

  1. 一个可以在多个应用程序中使用的通用客户端,只需从ZK读取数据即可。
  2. 另一个管理客户端可以读取,删除和更新ZK中的节点。
  3. 只读或管理员访问权限取决于所使用的凭据。

完全控制的管理员客户端

    import java.security.NoSuchAlgorithmException;
    import java.util.ArrayList;
    import java.util.List;
    import org.apache.curator.RetryPolicy;
    import org.apache.curator.framework.CuratorFramework;
    import org.apache.curator.framework.CuratorFrameworkFactory;
    import org.apache.curator.framework.api.ACLProvider;
    import org.apache.curator.retry.ExponentialBackoffRetry;
    import org.apache.zookeeper.ZooDefs;
    import org.apache.zookeeper.data.ACL;
    import org.apache.zookeeper.data.Id;
    import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;

    public class AdminClient {

        protected static CuratorFramework client = null;

        public void initializeClient() throws NoSuchAlgorithmException {
            String zkConnectString = "127.0.0.1:2181";
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
            final List<ACL> acls = new ArrayList<>();

            //full-control ACL
            String zkUsername = "adminuser";
            String zkPassword = "adminpass";
            String fullControlAuth = zkUsername + ":" + zkPassword;
            String fullControlDigest = DigestAuthenticationProvider.generateDigest(fullControlAuth);
            ACL fullControlAcl = new ACL(ZooDefs.Perms.ALL, new Id("digest", fullControlDigest));
            acls.add(fullControlAcl);

            //read-only ACL
            String zkReadOnlyUsername = "readuser";
            String zkReadOnlyPassword = "readpass";
            String readOnlyAuth = zkReadOnlyUsername + ":" + zkReadOnlyPassword;
            String readOnlyDigest = DigestAuthenticationProvider.generateDigest(readOnlyAuth);
            ACL readOnlyAcl = new ACL(ZooDefs.Perms.READ, new Id("digest", readOnlyDigest));
            acls.add(readOnlyAcl);

            //create the client with full-control access
            client = CuratorFrameworkFactory.builder()
                .connectString(zkConnectString)
                .retryPolicy(retryPolicy)
                .authorization("digest", fullControlAuth.getBytes())
                .aclProvider(new ACLProvider() {
                    @Override
                    public List<ACL> getDefaultAcl() {
                        return acls;
                    }

                    @Override
                    public List<ACL> getAclForPath(String string) {
                        return acls;
                    }
                })
                .build();
            client.start();
            //Now create, read, delete ZK nodes
        }
    }

只读客户端

    import java.security.NoSuchAlgorithmException;
    import org.apache.curator.RetryPolicy;
    import org.apache.curator.framework.CuratorFramework;
    import org.apache.curator.framework.CuratorFrameworkFactory;
    import org.apache.curator.retry.ExponentialBackoffRetry;

    public class ReadOnlyClient {

        protected static CuratorFramework client = null;

        public void initializeClient() throws NoSuchAlgorithmException {
            String zkConnectString = "127.0.0.1:2181";
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
            String zkReadOnlyUsername = "readuser";
            String zkReadOnlyPassword = "readpass";
            String readOnlyAuth = zkReadOnlyUsername + ":" + zkReadOnlyPassword;
            client = CuratorFrameworkFactory.builder()
                    .connectString(zkConnectString)
                    .retryPolicy(retryPolicy)
                    .authorization("digest", readOnlyAuth.getBytes())
                    .build();
            client.start();
            //Now read ZK nodes
        }
    }