Zookeeper的SASL认证最佳实践

7,717 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

Zookeeper系列笔记,带你入门到精通

概述

最近项目应客户要求Zookeeper需要认证,只有认证通过连接才能建立。但是有个比较尴尬的情况,我们项目本身也连接kafka,kafka之前做过kerborse认证。那么该如何做能让一个java进程存在多种认证方式呢?

Zookeeper Server搭建

本节讲解如何搭建基于SASL digest-md5方式的Zookeeper server。

  1. 下载zookeeper

下载地址:www.apache.org/dyn/closer.…

下载并且解压。

  1. 修改配置zoo.cfg

解压目录中的conf目录修改zoo.cfg, 如果没有的话,复制zoo_sample.cfg一份,命名为zoo.cfg, 添加sasl认证相关的配置:

sessionRequireClientSASLAuth=true

authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
  • sessionRequireClientSASLAuth: zk3.6.0版本中添加,为true时要求客户端连接zk时必须进行SASL认证才可以连接成功,也就是说没有进行SASL认证的匿名用户就无法连接了,相当于在连接时设置了一个登录密码。
  • authProvider.1: zk的认证方式,可以为ZooKeeper指定多个认证提供程序类。通常使用此参数指定SASLAuthenticationProvider
  1. 添加认证文件jaas.conf
Server {
       org.apache.zookeeper.server.auth.DigestLoginModule required 
       user_super="adminsecret"
       user_bob="bobsecret";
};
  • 提供了两个用户super和bob,他们的密码分别是"adminsecret"和"bobsecret"。
  • 请注意,上面的密码都是纯文本,所以除了ZooKeeper服务器进程用户之外,JAAS配置文件应该不能被其他人读取。
  1. 添加server启动参数java.env

在conf目录下添加java.env,内容如下:

SERVER_JVMFLAGS="-Djava.security.auth.login.config=/home/dev/soft/sasl/conf/jaas.conf"

指定jaas.conf的路径,zkServer启动的时候会读取java.env,作为启动参数。

  1. 启动

执行下面命令启动zkServer。

./bin/zkServer.sh start
  1. 通过zkCli验证

不做任何修改,直接执行./bin/zkCli.sh开启客户端,会报错如下

那怎么办呢?我们用java客户端演示一下。

JAVA客户端连接认证Zookeeper

  1. 创建认证文件jaas.conf

  1. 创建Zookeeper代码
@Before
    public void init() throws IOException, InterruptedException {
        System.setProperty("java.security.auth.login.config", "D:\Developer\CodeRepo\alvinlkk\awesome-java-full-demo\zookeeper-demo\zookeeper-sasl-demo\src\main\resources\jaas.conf");
        log.info("********************** start zk ..................");
        CountDownLatch countDownLatch = new CountDownLatch(1);
        zooKeeper = new ZooKeeper(ZK_ADDR, ZK_SESSION_TIMEOUT, event -> {
            log.info("%%%%%%%%%%%%%%%%%%%%%触发了事件:[{}]", event);
            countDownLatch.countDown();
        });
        countDownLatch.await();
    }
  • 关键步骤在于设置系统属性System.setProperty("java.security.auth.login.config", "D:\jaas.conf");
  1. 正常创建和读取节点
 @Test
    public void testGet() throws InterruptedException, KeeperException {
        Stat stat = new Stat();
        byte[] data = zooKeeper.getData("/node1", false, stat);
        log.info("获取到的数据是:" + new String(data));
        log.info("当前节点的版本:" + stat.getVersion());
    }
  • 设置jaas到系统属性中后,创建、读取节点就不会报错。

Kafka和Zookeeper同时认证

回到一开始的问题,Kafka的kerberos认证也是通过修改系统属性,如下图:

System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
System.setProperty("java.security.krb5.conf", "D:\krb5.conf");
System.setProperty("java.security.auth.login.config", "D:\jaas.conf");

那这样会不会和前面的zookeeper配置冲突呢?

实际情况不会,可以在jaas.cfg中写多份配置信息,通过前面的KafkaClient和Client做为区分,他们是Kafka和Zookeeper客户端默认的名字,也可以通过配置修改。

SASL相关知识

SASL是一种用来扩充C/S模式验证能力的机制认证机制, 全称Simple Authentication and Security Layer,常见的机制如下:

  • plain(较常用)

plain是最简单的机制,但同时也是最危险的机制,因为身份证书(登录名称与密码)是以base64字符串格式通过网络,没有任何加密保护措施。因此,使用plain机制时,你可能会想要结合tls。

  • login

login不是其正式支持的机制,但某些旧版的mua使用这种机制,所以cyrus sasl让你可选择其是否支持login机制。如果你的用户仍在使用这类老掉牙的mua,你必须在编译sasl函数库时,指定要包含login的支持。 login的证书交换过程类似plain。

  • otp

otp是一种使用“单次密码”的验证机制。此机制不提供任何加密保护,因为没必要每个密码都只能使用一次,每次联机都要改用新密码。smto client必须能够产生otp证书。

  • digest-md5(较常用)

使用这种机制时,client与server共享同一个隐性密码,而且此密码不通过网络传输。验证过程是从服务器先提出challenge(质询)开始, 客户端使用此challenge与隐性密码计算出一个response(应答)。不同的challenge,不可能计算出相同的response;任何拥 有secret password的一方,都可以用相同的challenge算出相同的response。因此,服务器只要比较客户端返回的response是否与自己算 出的response相同,就可以知道客户端所拥有的密码是否正确。由于真正的密码并没有通过网络,所以不怕网络监测。

  • kerberos

kerberos是一种网络型验证协议。除非你的网络已经使用kerberos,否则你应该用不到kerberos机制;相对的,如果你的网络已经架设了kerberos验证中心,sasl就能完美的将smtp验证整合进现有的体系。

总结

本文重点还是在于zookeeper如何进行认证,希望能够帮助到大家,文中的代码参考地址:github.com/alvinlkk/aw…

参考

cwiki.apache.org/confluence/…

www.cnblogs.com/slankka/p/1…

zookeeper.apache.org/doc/r3.6.3/…