欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ZK实现SASL认证+Kafka连接ZK

程序员文章站 2022-07-14 12:02:28
...

ZK实现SASL认证+Kafka连接ZK

关键词:zk sasl kfaka 未授权认证

参考文档:

  • 搭建Kafka集群时, 对ZooKeeper认证与权限控制
    http://ohmycat.me/2019/05/08/kafka-with-zookeeper-authentication.html
  • SASL authentication for ZooKeeper.
    https://cwiki.apache.org/confluence/display/ZOOKEEPER/ZooKeeper+and+SASL

服务器IP列表:

  • 192.168.132.11
  • 192.168.132.12
  • 192.168.132.13

镜像版本:

  • zookeeper:3.6.1
  • wurstmeister/kafka:2.13-2.6.0

1. zookeeper

1.1 设置环境变量

# 备份配置文件
cp -p ~/.bashrc ~/.bashrc.20201218

# 编辑~/.bashrc,在文件尾部增加如下内容:
ls_iface=`ls -l /sys/class/net/ |grep -v virtual |grep root|gawk '{print $9}'`
MYIP=`ip -h -4 -o address |grep $ls_iface|gawk '{print $4}'|sed 's/\// /'|gawk '{print $1}'`
IMAGE_NAME=`echo $MYIP |gawk -F. '{print $4}'`
export MYIP IMAGE_NAME

# 为每台服务器设置ZKID。
# 注意:每台服务器的ID必需不同且与配置文件中的ZOO_SERVERS的server.x的x要匹配
export myid=1

1.2 让环境变量生效

source ~/.bashrc

# 检查环境变量是否效
echo "IP:$MYIP 容器序号:$IMAGE_NAME 服务器ID:$myid"

1.3 (可选)设置防火墙

firewall-cmd --permanent --add-port=2888/tcp
firewall-cmd --permanent --add-port=3888/tcp
firewall-cmd --permanent --add-port=2181/tcp
firewall-cmd --permanent --add-port=9092/tcp
firewall-cmd --permanent --add-port=2182/tcp
firewall-cmd --reload

1.4 创建存放zk数据的目录

mkdir -p /myhome/zk/data
mkdir -p /myhome/zk/datalog
mkdir -p /myhome/zk/conf/jaas

1.5 创建启动脚本~/zk-kafka/firststartzk.sh,内容如下:

#!/bin/bash

case ${myid} in
1)
docker run -d --name=myzk_${IMAGE_NAME} \
--restart=always \
-p 2888:2888 \
-p 3888:3888 \
-p 2181:2181 \
-e ZOO_MY_ID=${myid} \
-e ZOO_SERVERS="server.1=0.0.0.0:2888:3888;2181 server.2=192.168.132.12:2888:3888;2181 server.3=192.168.132.13:2888:3888;2181" \
-v /myhome/zk/data:/data \
-v /myhome/zk/datalog:/datalog \
-v /etc/localtime:/etc/localtime \
zookeeper:3.6.1
;;
2)
docker run -d --name=myzk_${IMAGE_NAME} \
--restart=always \
-p 2888:2888 \
-p 3888:3888 \
-p 2181:2181 \
-e ZOO_MY_ID=${myid} \
-e ZOO_SERVERS="server.1=192.168.132.11:2888:3888;2181 server.2=0.0.0.0:2888:3888;2181 server.3=192.168.132.13:2888:3888;2181" \
-v /myhome/zk/data:/data \
-v /myhome/zk/datalog:/datalog \
-v /etc/localtime:/etc/localtime \
zookeeper:3.6.1
;;
3)
docker run -d --name=myzk_${IMAGE_NAME} \
--restart=always \
-p 2888:2888 \
-p 3888:3888 \
-p 2181:2181 \
-e ZOO_MY_ID=${myid} \
-e ZOO_SERVERS="server.1=192.168.132.11:2888:3888;2181 server.2=192.168.132.12:2888:3888;2181 server.3=0.0.0.0:2888:3888;2181" \
-v /myhome/zk/data:/data \
-v /myhome/zk/datalog:/datalog \
-v /etc/localtime:/etc/localtime \
zookeeper:3.6.1
;;
*)
echo "can not get myid value"
;;
esac


1.6 启动ZK集群,获取配置文件

cd ~/zk-kafka
./firststartzk.sh

# 拷贝ZK配置文件
docker cp myzk_${IMAGE_NAME}:/conf /myhome/zk

# 停止容器
docker stop myzk_${IMAGE_NAME}
docker rm myzk_${IMAGE_NAME}

1.7 修改配置文件/myhome/zk/conf/zoo.cfg

实现server-server 和 client-server认证

tee -a >>/myhome/zk/conf/zoo.cfg<<EOF

# server-server authentication
quorum.auth.enableSasl=true
quorum.auth.learnerRequireSasl=true
quorum.auth.serverRequireSasl=true
quorum.auth.learner.saslLoginContext=QuorumLearner
quorum.auth.server.saslLoginContext=QuorumServer
quorum.cnxn.threads.size=6

# client-server authentication
requireClientAuthScheme=sasl
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
authProvider.2=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
authProvider.3=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
EOF

1.8 创建JAAS配置文件/myhome/zk/conf/jaas/zk_server.conf,内容如下:

此文件中的Server用于客户端(比如zkClient.sh或kafka)连接,QuorumServer和QuorumLearner用于服务端之间的连接

tee -a >/myhome/zk/conf/jaas/zk_server.conf<<EOF
Server{
    org.apache.zookeeper.server.auth.DigestLoginModule required
    user_test="test123";
};

QuorumServer {
    org.apache.zookeeper.server.auth.DigestLoginModule required
    user_test="test123";
};

QuorumLearner {
    org.apache.zookeeper.server.auth.DigestLoginModule required
    username="test"
    password="test123";
};
EOF

1.9 创建JAAS配置文件/myhome/zk/config/jaas/zk_client.conf,增加如下内容:

此文件用于客户端软件连接(比如zkClient.sh或kafka)

tee -a >/myhome/zk/config/jaas/zk_client.conf<<EOF
Client {
       org.apache.zookeeper.server.auth.DigestLoginModule required
       username="test"
       password="test123";
};
EOF

1.10 创建正式启动ZK的脚本~/zk-kafka/startzk.sh

#!/bin/bash

case ${myid} in
1)
docker run -d --name=myzk_${IMAGE_NAME} \
--restart=always \
-p 2888:2888 \
-p 3888:3888 \
-p 2181:2181 \
-e ZOO_MY_ID=${myid} \
-e ZOO_SERVERS="server.1=0.0.0.0:2888:3888;2181 server.2=192.168.132.12:2888:3888;2181 server.3=192.168.132.13:2888:3888;2181" \
-e SERVER_JVMFLAGS="-Djava.security.auth.login.config=/conf/jaas/zk_server.conf" \
-e CLIENT_JVMFLAGS="-Djava.security.auth.login.config=/conf/jaas/zk_client.conf" \
-v /myhome/zk/data:/data \
-v /myhome/zk/datalog:/datalog \
-v /etc/localtime:/etc/localtime \
-v /myhome/zk/conf:/conf \
zookeeper:3.6.1
;;
2)
docker run -d --name=myzk_${IMAGE_NAME} \
--restart=always \
-p 2888:2888 \
-p 3888:3888 \
-p 2181:2181 \
-e ZOO_MY_ID=${myid} \
-e ZOO_SERVERS="server.1=192.168.132.11:2888:3888;2181 server.2=0.0.0.0:2888:3888;2181 server.3=192.168.132.13:2888:3888;2181" \
-e SERVER_JVMFLAGS="-Djava.security.auth.login.config=/conf/jaas/zk_server.conf" \
-e CLIENT_JVMFLAGS="-Djava.security.auth.login.config=/conf/jaas/zk_client.conf" \
-v /myhome/zk/data:/data \
-v /myhome/zk/datalog:/datalog \
-v /etc/localtime:/etc/localtime \
-v /myhome/zk/conf:/conf \
zookeeper:3.6.1
;;
3)
docker run -d --name=myzk_${IMAGE_NAME} \
--restart=always \
-p 2888:2888 \
-p 3888:3888 \
-p 2181:2181 \
-e ZOO_MY_ID=${myid} \
-e ZOO_SERVERS="server.1=192.168.132.11:2888:3888;2181 server.2=192.168.132.12:2888:3888;2181 server.3=0.0.0.0:2888:3888;2181" \
-e SERVER_JVMFLAGS="-Djava.security.auth.login.config=/conf/jaas/zk_server.conf" \
-e CLIENT_JVMFLAGS="-Djava.security.auth.login.config=/conf/jaas/zk_client.conf" \
-v /myhome/zk/data:/data \
-v /myhome/zk/datalog:/datalog \
-v /etc/localtime:/etc/localtime \
-v /myhome/zk/conf:/conf \
zookeeper:3.6.1
;;
*)
echo "can not get myid value"
;;
esac

1.11 启动ZK并查看日志

cd ~/zk-kafka
./startzk.sh

# 查看日志
docker logs -f myzk_${IMAGE_NAME}
或
docker logs -f myzk_${IMAGE_NAME} |grep Sasl

输出类似如下:

2020-12-26 03:38:33,964 [myid:1] - INFO  [main:[email protected]] - quorum.auth.enableSasl set to true
2020-12-26 03:38:33,964 [myid:1] - INFO  [main:[email protected]] - quorum.auth.serverRequireSasl set to true
2020-12-26 03:38:33,964 [myid:1] - INFO  [main:[email protected]] - quorum.auth.learnerRequireSasl set to true
2020-12-26 03:38:34,135 [myid:1] - INFO  [QuorumConnectionThread-[myid=1]-2:[email protected]] - Successfully authenticated learner: authenticationID=test;  authorizationID=test.
2020-12-26 03:38:34,136 [myid:1] - INFO  [QuorumConnectionThread-[myid=1]-1:[email protected]] - Successfully completed the authentication using SASL. server addr: /192.168.132.12:3888, status: SUCCESS
2020-12-26 03:38:34,136 [myid:1] - INFO  [QuorumConnectionThread-[myid=1]-2:[email protected]] - Successfully completed the authentication using SASL. learner addr: /192.168.132.12:55130
2020-12-26 03:38:34,138 [myid:1] - INFO  [QuorumConnectionThread-[myid=1]-3:[email protected]] - Successfully authenticated learner: authenticationID=test;  authorizationID=test.
2020-12-26 03:38:34,138 [myid:1] - INFO  [QuorumConnectionThread-[myid=1]-3:[email protected]] - Successfully completed the authentication using SASL. learner addr: /192.168.132.13:35982
2020-12-26 03:38:34,373 [myid:1] - INFO  [QuorumPeer[myid=1](plain=0.0.0.0:2181)(secure=disabled):[email protected]] - Successfully completed the authentication using SASL. server addr: /192.168.132.13:2888, status: SUCCESS

1.12 进入容器

docker exec -it myzk_${IMAGE_NAME} /bin/bash

# 执行客户端工具
bin/zkCli.sh

输出类似如下:

Welcome to ZooKeeper!
JLine support is enabled
2020-12-26 04:01:15,121 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):[email protected]] - Client successfully logged in.
2020-12-26 04:01:15,126 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):[email protected]] - Client will use DIGEST-MD5 as SASL mechanism.
[zk: localhost:2181(CONNECTING) 0] 2020-12-26 04:01:15,173 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):[email protected]] - Opening socket connection to server localhost/127.0.0.1:2181.
2020-12-26 04:01:15,174 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):[email protected]] - SASL config status: Will attempt to SASL-authenticate using Login Context section 'Client'
2020-12-26 04:01:15,182 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):[email protected]] - Socket connection established, initiating session, client: /127.0.0.1:40366, server: localhost/127.0.0.1:2181
2020-12-26 04:01:15,206 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):[email protected]] - Session establishment complete on server localhost/127.0.0.1:2181, session id = 0x100003c85fe0000, negotiated timeout = 30000

# 如果提示符出现connected字样,则说明连接服务端成功
[zk: localhost:2181(CONNECTED) 0]

# 列出所有子节点
zk > ls -R /

到此为止,实现了ZK的server-server 和 client-server的认证

2. kafka

2.1 创建存放数据的目录

mkdir -p /myhome/kafka/data
mkdir -p /myhome/kafka/logs
mkdir -p /myhome/kafka/jaas

2.2 创建JAAS配置文件/myhome/kafka/jaas/zk_client.conf,增加如下内容:

tee -a >>/myhome/kafka/jaas/zk_client.conf<<EOF
Client {
       org.apache.zookeeper.server.auth.DigestLoginModule required
       username="test"
       password="test123";
};
EOF

2.3 启动kafka

docker run -d --name=mykafka_${IMAGE_NAME} \
--restart=always \
-p 9092:9092 \
-v /etc/localtime:/etc/localtime \
-v /myhome/kafka/data:/kafka \
-v /myhome/kafka/logs:/opt/kafka/logs \
-v /myhome/kafka/jaas:/mnt \
-e KAFKA_ADVERTISED_HOST_NAME=${MYIP} \
-e HOST_IP=${MYIP} \
-e KAFKA_ADVERTISED_PORT=9092 \
-e KAFKA_ZOOKEEPER_CONNECT=192.168.132.11:2181,192.168.132.12:2181,192.168.132.13:2181 \
-e KAFKA_BROKER_ID=${myid} \
-e KAFKA_OPTS="-Djava.security.auth.login.config=/mnt/zk_client.conf" \
-e KAFKA_ZOOKEEPER_SET_ACT=true \
wurstmeister/kafka:2.13-2.6.0

2.4 查看日志

docker logs -f mykafka_${IMAGE_NAME}

2.5 验证kafka

# 进入容器
docker exec -it mykafka_${IMAGE_NAME} /bin/bash

cd /opt/kafka

# 创建topic
bin/kafka-topics.sh --create --zookeeper ${MYIP}:2181 --replication-factor 1 --partitions 1 --topic test

# 查看Topic
bin/kafka-topics.sh --list --zookeeper ${MYIP}:2181

# 生产者:向Kafka发送消息
bin/kafka-console-producer.sh --broker-list 0.0.0.0:9092 --topic test

# 消费者: 消费刚刚发送的消息
bin/kafka-console-consumer.sh --bootstrap-server 0.0.0.0:9092 --topic test --from-beginning

2.6 验证ZK

# 进入容器
docker exec -it myzk_${IMAGE_NAME} /bin/bash

# 执行客户端工具
bin/zkCli.sh

# 列出所有子节点
zk> ls -R /

# 查看之前创建的主题:test的ACL
zk> getAcl /brokers/topics/test

输出如下:

# 表示采用了sasl认证,用户名是test,权限是cdrwa(即全部权限)
'sasl,'test
: cdrwa
# 表示任意人均可访问,权限是r(即只读)
'world,'anyone
: r