当前Kafka security主要包含3大功能:认证(authentication)、信道加密(encryption)和受权(authorization)。信道加密就是为client到broker、broker到broker以及工具脚本与broker之间的数据传输配置SSL;认证机制主要是指配置SASL,而受权是经过ACL接口命令来完成的。
本文搭建过程不涉及Kerberos,并且因为运行在内网环境,SSL加密也不是很必要。只是基于SASL + ACL来构建secured Kafka集群。
本次搭建的Kafka集群版本为2.60,注意不同版本可能略有不同,具体需要以官网配置为准
1.1 编写server_jaas文件
要配置SASL和ACL,咱们须要在broker端进行两个方面的设置。首先是建立包含全部认证用户信息的JAAS文件。本例中,咱们假设有3个用户:admin, reader和writer,其中admin是管理员,reader用户读取Kafka集群中topic数据,而writer用户则负责向Kafka集群写入消息。咱们假设这3个用户的密码分别与用户名相同(在实际场景中,管理员须要单独把密码发给各自的用户),编辑JAAS文件内容:
KafkaServer {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="admin"
password="admin"
user_admin="admin"
user_reader="reader"
user_writer="writer";
};
保存该文件为kafka_server_jaas.conf。同时把该文件的完整路径做为一个JVM参数传递给Kafka的启动脚本kafka-server-start.sh。不过因为bin/kafka-server-start.sh只接收server.properties的位置,再也不接收其余任何参数,故咱们须要修改该启动脚本。具体作法以下:
cp bin/kafka-server-start.sh bin/secured-kafka-server-start.sh
vim secured-kafka-server-start.sh
把secured-kafka-server-start.sh最后一行:
exec $base_dir/kafka-run-class.sh $EXTRA_ARGS kafka.Kafka "$@"
改为
exec $base_dir/kafka-run-class.sh $EXTRA_ARGS -Djava.security.auth.login.config=/opt/server/kafka_2.13-2.6.0/config/kafka_server_jaas.conf kafka.Kafka "$@"
1.2 修改server.properties文件
添加一些内容
# 配置ACL入口类网上的版本基本上都是配置为kafka.security.auth.SimpleAclAuthorizer,
#但是这个class.name在2.4版本以后已经被废除,这点有个大坑,最后还得去Kafka官网查看对应版本参数配置
authorizer.class.name=kafka.security.authorizer.AclAuthorizer
# 本例使用SASL_PLAINTEXT
listeners=SASL_PLAINTEXT://Ip:port
security.inter.broker.protocol= SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=PLAIN
sasl.enabled.mechanisms=PLAIN
# 设置本例中admin为超级用户
super.users=User:admin
完成上述两步以后,我们就可以启动Kafka集群了
2.1 创建topic
因为使用kafka-topics.sh脚本直接链接Zookeeper,故不受ACL的限制。因此不管是否配置了security,用户都可以使用kafka-topics来管理topic。
./kafka-topics.sh --zookeeper 10.91.3.145:2181,10.91.3.68:2181,10.91.3.92:2181/kafka --create topic test1 --replication-factor 1 --partitions 3
2.2 配置producer
我们先启动一个console-producer来生产消息,发现无法连接broker
root@bdp-galileo-zk-1 bin]# ./kafka-console-consumer.sh --bootstrap-server 10.91.3.145:9092 --topic test
[2022-04-25 15:29:51,051] WARN [Consumer clientId=consumer-console-consumer-33101-1, groupId=console-consumer-33101] Bootstrap broker 10.91.3.145:9092 (id: -1 rack: null) disconnected (org.apache.kafka.clients.NetworkClient)
[2022-04-25 15:29:51,451] WARN [Consumer clientId=consumer-console-consumer-33101-1, groupId=console-consumer-33101] Bootstrap broker 10.91.3.145:9092 (id: -1 rack: null) disconnected (org.apache.kafka.clients.NetworkClient)
[2022-04-25 15:29:51,853] WARN [Consumer clientId=consumer-console-consumer-33101-1, groupId=console-consumer-33101] Bootstrap broker 10.91.3.145:9092 (id: -1 rack: null) disconnected (org.apache.kafka.clients.NetworkClient)
下面为writer用户配置写入test topic的权限
首先编辑一个JAAS文件writer_jaas.conf
KafkaClient {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="writer"
password="writer";
};
然后将writer_jaas.conf文件以参数的形式传递给kafka-console-consumer.sh脚本
cp bin/kafka-console-producer.sh bin/writer-kafka-console-producer.sh
$ vi bin/writer-kafka-console-producer.sh
把该文件中的这行:
exec $(dirname $0)/kafka-run-class.sh kafka.tools.ConsoleProducer "$@"
修改成下面这行,而后保存退出
exec $(dirname $0)/kafka-run-class.sh -Djava.security.auth.login.config=/opt/server/kafka_2.13-2.6.0/config/writer_jaas.conf kafka.tools.ConsoleProducer "$@"
然后创建一个producer.config为该console producer指定如下两个属性:
vim producer.config
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
接着使用writer-kafka-console-producer.sh试着生产消息
$ bin/writer-kafka-console-producer.sh --broker-list 10.91.3.145:9092 --topic test1 --producer.config producer.config
>hello, kafka
[2022-04-25 16:29:51,051] WARN Error while fetching metadata with correlation id 1 : {test=UNKNOWN_TOPIC_OR_PARTITION} (org.apache.kafka.clients.NetworkClient)
[2022-04-25 16:29:51,064] WARN Error while fetching metadata with correlation id 3 : {test=UNKNOWN_TOPIC_OR_PARTITION} (org.apache.kafka.clients.NetworkClient)
依然有错误,不过错误变成“没法获取元数据”了。这说明运行的console producer经过了认证,可是没有经过受权,所以咱们须要配置ACL来让writer用户有权限写入topic:
bin/kafka-acls.sh --authorizer-properties zookeeper.connect=10.91.3.145:2181,10.91.3.68:2181,10.91.3.92:2181/kafka --add --allow-principal User:writer --allow-host * --operation Write --topic test1
接着我们就可以愉快的生产消息了,不过子曰,数据未消费之前就不算生产成功。所以我们还需要配置消费者
2.3 配置consumer
和reader类似,首先建立reader用户的JAAS文件reader_jaas.conf,
KafkaClient {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="reader"
password="reader";
};
然后拷贝一份新的console consumer来指定上面的reader_jaas.conf:
cp bin/kafka-console-consumer.sh bin/reader-kafka-console-consumer.sh
vi bin/reader-kafka-console-consumer.sh
把该文件中的这行:
exec $(dirname $0)/kafka-run-class.sh kafka.tools.ConsoleConsumer "$@"
修改成下面这行,而后保存退出
exec $(dirname $0)/kafka-run-class.sh -Djava.security.auth.login.config=/Users/huxi/SourceCode/newenv/reader_jaas.conf kafka.tools.ConsoleConsumer "$@"
然后建立一个consumer.config为该console producer指定如下3个属性:
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
group.id=test-group
最后给readr赋予test1 topic的读取权限
./kafka-acls.sh --authorizer-properties zookeeper.connect=10.91.3.145:2181,10.91.3.68:2181,10.91.3.92:2181/kafka --add --allow-principal User:reader --operation Read --topic test1 --group test-group
然后就可以正常消费了。
#注意该版本必须使用--consumer.config参数指定consumer.config配置文件,而不能用--consumer-property。这点也是个坑
./reader-kafka-console-consumer.sh --bootstrap-server 10.91.3.145:9092 --topic test1 --consumer.config consumer.config