Zookeeper 入门实战(4)--开启 Kerberos 认证
本主要介绍在 Zookeeper 中如何配置 Kerberos 认证,文中所使用到的软件版本:Java 1.8.0_191、Zookeeper 3.6.3、Kerberos 1.15.1。
1、Kerberos 安装
要使用 Kerberos 服务,需先安装 Kerberos,安装方法可参考:Kerberos 入门实战(2)--Kerberos 安装及使用。
2、Client-Server 的 Kerberos 认证
Client-Server 的 Kerberos 认证主要用于客户端与 Zookeeper 服务端的相互认证。
2.1、单节点 Client-Server 的 Kerberos 认证
2.1.1、创建 keytab
在安装 Kerberos 的机器上进入 kadmin(Kerberos 服务端上使用 kadmin.local,安装了 Kerberos Client 的机器上可以使用 kadmin),然后执行如下命令分别创建服务端和客户端的 keytab:
kadmin.local: add_principal -randkey zk-server/pxc2@ABC.COM #pxc2 为安装 Zookeeper 的主机名 kadmin.local: add_principal -randkey zk-client@ABC.COM kadmin.local: xst -k /root/zk-server.keytab zk-server/pxc2@ABC.COM kadmin.local: xst -k /root/zk-client.keytab zk-client@ABC.COM
2.1.2、配置
A、拷贝 krb5.conf 及 keytab 文件到安装 Zookeeper 的机器,这里把文件都放到 Zookeeper 的 conf 目录下。
B、修改 zoo.cfg,增加如下配置:
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider jaasLoginRenew=3600000 sessionRequireClientSASLAuth=true #客户端必须 SASL 认证
C、新建 jaas.conf 文件,该文件也放到 Zookeeper 的 conf 目录下。
Server { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab="/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/zk-server.keytab" storeKey=true useTicketCache=false principal="zk-server/pxc2@ABC.COM"; }; #客户端配置,方便 zkCli.sh 使用 Client { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab="/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/zk-client.keytab" storeKey=true useTicketCache=false principal="zk-client@ABC.COM"; };
D、新建 java.env 文件;该文件主要用于指定 jaas 文件位置,也放到 Zookeeper 的 conf 目录下。
export SERVER_JVMFLAGS="-Djava.security.auth.login.config=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/jaas.conf -Djava.security.krb5.conf=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/krb5.conf" export CLIENT_JVMFLAGS="${CLIENT_JVMFLAGS} -Djava.security.auth.login.config=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/jaas.conf -Djava.security.krb5.conf=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/krb5.conf -Dzookeeper.server.principal=zk-server/pxc2@ABC.COM"
SERVER_JVMFLAGS 是服务端(zkServer.sh)的配置
CLIENT_JVMFLAGS 是客户端(zkClis.sh)的配置,zookeeper.server.principal 参数用于配置服务端 principal(默认为 zookeeper/localhost@{realm},可能不存在)
2.1.3、启动并测试
配置完成后就可以启动 Zookeeper 了:
bin/zkServer.sh start
启动完成后可以使用 zkCli.sh 来测试:
bin/zkCli.sh
2.1.4、java 程序连接 Zookeeper
java 可以使用 JAAS 来进行 Kerberos 认证,需要 JAAS 配置文件、keytab 文件及 Kerberos 配置文件。
A、配置文件
JAAS 配置文件(zk-client-jaas.conf):
Client { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab="D:\\workspaceidea\\demo\\demo\\src\\main\\resources\\kerberos\\zk-client.keytab" storeKey=true useTicketCache=false principal="zk-client@ABC.COM"; };
keytab 文件:
从 Kerberos 服务器上拷贝到目标机器,拷贝路径即为 JAAS 配置中间配置的路径:D:\\workspaceidea\\demo\\demo\\src\\main\\resources\\kerberos\\zk-client.keytab。
Kerberos 配置文件(krb5.conf):
从 Kerberos 服务器上拷贝 /etc/krb5.conf 到目标机器即可。
B、引入依赖
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.6.3</version> </dependency>
C、样例程序
package com.abc.demo.general.zookeeper; import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; /** * Zookeeper 客户端 Kerberos 认证 */ public class ZookeeperKerberosCase { private static String connectString = "10.49.196.11:2181"; private static int sessionTimeout = 200 * 1000; private ZooKeeper zooKeeper; @Before public void before() { System.setProperty("java.security.auth.login.config", "D:\\workspaceidea\\demo\\demo\\src\\main\\resources\\kerberos\\zk-client-jaas.conf"); System.setProperty("java.security.krb5.conf", "D:\\workspaceidea\\demo\\demo\\src\\main\\resources\\kerberos\\krb5.conf"); System.setProperty("zookeeper.server.principal", "zk-server/pxc2@ABC.COM"); //设置 Zookeeper 的 principal try { zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { } }); System.out.println(zooKeeper.getState()); } catch (IOException e) { e.printStackTrace(); } } @After public void after() throws Exception { zooKeeper.close(); } @Test public void getData() throws Exception { Stat stat = new Stat(); byte[] data = zooKeeper.getData("/javatest/node1", false, stat); System.out.println(new String(data)); System.out.println(stat); } }
2.2、集群 Client-Server 的 Kerberos 认证
假设 Zookeeper 集群的机器信息如下:
ip | 主机名 |
10.49.196.10 | pxc1 |
10.49.196.11 | pxc2 |
10.49.196.12 | pxc3 |
2.2.1、创建 keytab
在安装 Kerberos 的机器上进入 kadmin(Kerberos 服务端上使用 kadmin.local,安装了 Kerberos Client 的机器上可以使用 kadmin),然后执行如下命令分别创建服务端和客户端的 keytab:
kadmin.local: add_principal -randkey zk-server/pxc1@ABC.COM kadmin.local: add_principal -randkey zk-server/pxc2@ABC.COM kadmin.local: add_principal -randkey zk-server/pxc3@ABC.COM kadmin.local: add_principal -randkey zk-client@ABC.COM kadmin.local: xst -k /root/zk-server.keytab zk-server/pxc1@ABC.COM kadmin.local: xst -k /root/zk-server.keytab zk-server/pxc2@ABC.COM kadmin.local: xst -k /root/zk-server.keytab zk-server/pxc3@ABC.COM kadmin.local: xst -k /root/zk-client.keytab zk-client@ABC.COM
2.2.2、配置
A、拷贝 krb5.conf 及 keytab 文件到所有安装 Zookeeper 的机器,这里把文件都放到 Zookeeper 的 conf 目录下。
B、修改 zoo.cfg,增加如下配置:
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
jaasLoginRenew=3600000
sessionRequireClientSASLAuth=true #客户端必须 SASL 认证
C、新建 jaas.conf 文件,该文件也放到 Zookeeper 的 conf 目录下。
Server {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/zk-server.keytab"
storeKey=true
useTicketCache=false
principal="zk-server/pxc1@ABC.COM"; #这里不同的主机上,需修改为本机的主机名
};
#客户端配置,方便 zkCli.sh 使用
Client {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/zk-client.keytab"
storeKey=true
useTicketCache=false
principal="zk-client@ABC.COM";
};
D、新建 java.env 文件;该文件主要用于指定 jaas 文件位置,也放到 Zookeeper 的 conf 目录下。
export SERVER_JVMFLAGS="-Djava.security.auth.login.config=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/jaas.conf -Djava.security.krb5.conf=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/krb5.conf"
export CLIENT_JVMFLAGS="${CLIENT_JVMFLAGS} -Djava.security.auth.login.config=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/jaas.conf -Djava.security.krb5.conf=/home/hadoop/app/apache-zookeeper-3.6.3-bin/conf/krb5.conf -Dzookeeper.server.principal=zk-server/pxc1@ABC.COM" #这里不同的主机上,需修改为本机的主机名
SERVER_JVMFLAGS 是服务端(zkServer.sh)的配置
CLIENT_JVMFLAGS 是客户端(zkClis.sh)的配置,zookeeper.server.principal 参数用于配置服务端 principal(默认为 zookeeper/localhost@{realm},可能不存在)
2.2.3、启动并测试
配置完成后就可以启动 Zookeeper 集群了:
bin/zkServer.sh start
启动完成后可以使用 zkCli.sh 来测试:
bin/zkCli.sh
2.2.4、java 程序连接 Zookeeper
java 可以使用 JAAS 来进行 Kerberos 认证,需要 JAAS 配置文件、keytab 文件及 Kerberos 配置文件。
A、配置文件
JAAS 配置文件(zk-client-jaas.conf):
Client {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="D:\\workspaceidea\\demo\\demo\\src\\main\\resources\\kerberos\\zk-client.keytab"
storeKey=true
useTicketCache=false
principal="zk-client@ABC.COM";
};
keytab 文件:
从 Kerberos 服务器上拷贝到目标机器,拷贝路径即为 JAAS 配置中间配置的路径:D:\\workspaceidea\\demo\\demo\\src\\main\\resources\\kerberos\\zk-client.keytab。
Kerberos 配置文件(krb5.conf):
从 Kerberos 服务器上拷贝 /etc/krb5.conf 到目标机器即可。
B、配置 hosts 文件
在 hosts 文件中添加:
10.49.196.10 pxc1 10.49.196.11 pxc2 10.49.196.12 pxc3
C、引入依赖
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.6.3</version> </dependency>
D、样例程序
package com.abc.demo.general.zookeeper; import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; /** * Zookeeper 客户端 Kerberos 认证 */ public class ZookeeperKerberosCase { /** * 使用ip访问也可以:10.49.196.10:2181,10.49.196.11:2181,10.49.196.12:2181。 * 但 hosts 文件还是要配置的,Zookeeper 客户端会查找 ip 对应的主机名作为 Zookeeper 服务的 principal 的 instance 部分, * 如果找不到对应的主机名就使用 ip 代替,这会导致找不到对应的 principal。 */ private static String connectString = "pxc1:2181,pxc2:2181,pxc3:2181"; private static int sessionTimeout = 200 * 1000; private ZooKeeper zooKeeper; @Before public void before() { System.setProperty("java.security.auth.login.config", "D:\\workspaceidea\\demo\\demo\\src\\main\\resources\\kerberos\\zk-client-jaas.conf"); System.setProperty("java.security.krb5.conf", "D:\\workspaceidea\\demo\\demo\\src\\main\\resources\\kerberos\\krb5.conf");//Zookeeper 服务的 principal 的 primary 部分 System.setProperty("zookeeper.sasl.client.username", "zk-server"); try { zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override public void process(WatchedEvent watchedEvent) { } }); System.out.println(zooKeeper.getState()); } catch (IOException e) { e.printStackTrace(); } } @After public void after() throws Exception { zooKeeper.close(); } @Test public void getData() throws Exception { Stat stat = new Stat(); byte[] data = zooKeeper.getData("/javatest/node1", false, stat); System.out.println(new String(data)); System.out.println(stat); } }
3、Server-Server 的 Kerberos 认证
在主节点选举阶段,集群中的所有服务器都将参与以达到规定的票数;默认情况下,此通信不经过身份验证。Zookeeper 也支持在集群的服务器之间启用 Kerberos 认证,这里就不介绍了,详细说明可参考官网文档:https://cwiki.apache.org/confluence/display/ZOOKEEPER/Server-Server+mutual+authentication。