Kafka 添加 Kerberos 认证详细流程

背景

上一章节介绍了 Kerberos 服务端和客户端的部署过程,本章节继续介绍 Kafka 添加 Kerberos 认证的部署流程,及 Java API 操作的注意事项。

sasl.kerberos.service.name 配置的含义

Kafka 添加 Kerberos 部署的核心是 Kafka 服务端的 Principal 配置,它的 primary 部分必须配置在 properties 文件的 sasl.kerberos.service.name 属性中,而主机名部分必须保证 Kafka IP 的域名在 /etc/hosts 文件中存在。

对 Kafka 客户端来说,合起来就是,sasl.kerberos.service.name 的值/Kafka IP 或者 Kafka IP 对应的主机名称@Realm 这三项拼接的成目标服务的 Principal,必须保证它在 KDC 数据库中。

搜了好久都没有看到这个配置项的解释,反复操作后终于理解了这个属性的含义。

例如,请求目标 Kafka IP 是 192.168.xx.1 ,Kafka 客户端发起 Kerberos 认证时,向 KDC 发送 AS_REQ,目标服务的 Principal 的计算过程如下:

1)如果 /etc/hosts 文件中存在目标主机的域名,那么请求服务的 Principal 就是 sasl.kerberos.service.name/主机名称@Realm

2) 如果 /etc/hosts 文件中不存在目标主机的域名,那么请求服务的 Principal 就是 sasl.kerberos.service.name/目标IP@Realm

从 KDC 的日志看到这个结果:

例如,我这个请求过程,Client 端主机配置了目标 Kafka IP 的的域名为 oracle ,这里Kerberos 票据认证过程就是这个。

结论就是, 针对客户端和服务端,这两个配置的含义分别是:

1、Kafka 客户端最重要的 sasl.kerberos.service.name + 目标 IP 的域名必须存在 KDC 认证数据库中。

2、Kafka 服务端 sasl.kerberos.service.name + 本机域名,必须是 jaas.config 文件中的 KafkaServer 的 principal 的值。

主机域名准备

Kerberos 的 Principals 组成规则是:

username/fully.<qualified.domain.name@YOUR_REALM.COM>

作为服务端一般都是需要配置域名的,最好是客户端和服务端都配置服务器 IP 的域名,且必须统一,才能保证 Kerberos 认证流程正确,否则很容易出现 Not found in Kerberos database 的问题。

对于Kafka 集群来说,集群主机的 Principal 的 username 相同,但是主机域名不同,客户端维护集群节点的域名,sasl.kerberos.service.name 配置就是各节点的 username

Kafka Kerberos 认证环境搭建之前,必须先在客户端和服务器端的 /etc/hosts 文件中配置 Kafka Server IP 的域名。网上很多搭建教程,都是 Kafka 客户端和 Kafka 服务同主机,所以不会出现域名配置导致的问题。

角色 IP Principal
Client 192.168.10.101 <hello-kafka-client@MY_KDC.COM>
Server 192.168.10.102 hello-kafka-server/oracle@MY_KDC.COM

这里 IP 随便写的,Kafka Client 的 IP 不需要配置域名,在 192.168.10.101 上维护目标服务器的域名,添加在 /etc/hosts 文件中,参考如下:

typescript 复制代码
192.168.10.102 oracle

在 Kafka 客户端主机上部署一份 kafka ,用于启动消费者应用;服务端正常部署 Kafka ,且在 kafka 主目录下创建一个 kerberos 文件夹,放 Kerberos 认证相关的配置文件。

KDC 注册客户端和服务端

第零步,拷贝 krb5.conf。

拷贝 KDC 认证中心的 krb5.conf 文件到全部的 Kerberos 客户端,客户端最重要的系统环境变量就是 krb5.conf 文件的路径。所以,每个 KDC 的客户端都需要维护与 KDC 服务器端一致的 krb5.conf 文件,拷贝命令为:

typescript 复制代码
scp /etc/krb5.conf root@192.168.10.101:/opt/kafka-1.0.2/kerberos/krb5.conf

scp /etc/krb5.conf root@192.168.10.102:/opt/kafka-1.0.2/kerberos/krb5.conf

Java API 添加 Kerberos 认证的代码为:

typescript 复制代码
System.setProperty("java.security.krb5.conf", krb5Conf);

第一步,注册 Kerberos 帐号。

需要到 Kerberos 数据库中注册 Kafka 的客户端和服务端,按刚刚表里面的 Principal 注册到默认域名 MY_KDC.COM 中。

在 Kerberos 服务器上,执行 kadmin.local 命令,输入下面操作,注册帐号:

typescript 复制代码
addprinc hello-kafka-client
addprinc hello-kafka-server/oracle

操作结果如下:

第二步,生成帐号的 keytab 文件。 对上面添加的两个 Kerberos 帐号,导出 keytab 文件:

typescript 复制代码
kadmin.local -q "xst -norandkey -k  /root/hello-kafka-client.keytab hello-kafka-client@MY_KDC.COM"

kadmin.local -q "xst -norandkey -k  /root/hello-kafka-server.keytab hello-kafka-server/oracle@MY_KDC.COM"

利用控制台命令 kadmin.local 导出 keytab 文件,客户端 keytab :

服务端 keytab 如下:

第三步,传输 keytab 文件。 将帐号的 keytab 文件远程传输到 Kafka 客户端和服务端,就是前面的 101 和 102 两台主机上。

typescript 复制代码
scp /root/hello-kafka-client.keytab root@192.168.10.101:/opt/kafka-1.0.2/kerberos/hello-kafka-client.keytab

scp /root/hello-kafka-server.keytab root@192.168.10.102:/opt/kafka-1.0.2/kerberos/hello-kafka-server.keytab

Kafka 服务器部署 Kerberos

第一步,准备 server-kerberos.properties 文件。 拷贝 Kafka config 目录下的 server.properties 文件,命名为 kerberos-server.properties ,编辑认证配置相关的内容:

typescript 复制代码
listeners=SASL_PLAINTEXT://192.168.10.102:9092
advertised.listeners=SASL_PLAINTEXT://192.168.10.102:9092

security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=GSSAPI
sasl.enabled.mechanisms=GSSAPI
sasl.kerberos.service.name=hello-kafka-server

主要就是上面的几项配置, sasl.kerberos.service.name=hello-kafka-server 就是当前 Kafka 的 keytab 文件中的 Principal 的 username 部分。

第二步,准备 server-jaas.conf 配置文件。 kerberos 目录下,创建文件 kafka-server-jaas.conf,编辑内容如下:

typescript 复制代码
KafkaServer {
   com.sun.security.auth.module.Krb5LoginModule required
   useKeyTab=true
   //不同的主机,需修改成不同的keytab文件
   keyTab="/opt/kafka-1.0.2/kerberos/hello-kafka-server.keytab"
   storeKey=true
   useTicketCache=false
   // Kafka Server 在 KDC 中的用户名全称
   principal="hello-kafka-server/oracle@MY_KDC.COM";
};

第三步,准备 kafka-server-kerberos-start.sh 文件,添加 Kerberos 认证配置。 拷贝 bin/kafka-server-start.sh 脚本,命名为 kafka-server-kerberos-start.sh,编辑最后一行,在最后一行代码之前,添加 Krb5 环境变量和 jaas.conf 配置信息:

typescript 复制代码
export KAFKA_OPTS="-Dzookeeper.sasl.client=false -Dzookeeper.sasl.client.username=zk-server 
-Djava.security.krb5.conf=/opt/kafka-1.0.2/kerberos/krb5.conf 
-Djava.security.auth.login.config=/opt/kafka-1.0.2/kerberos/kafka-server-jaas.conf"

第四步,启动 Kafka 服务。 用新建的脚本 kafka-server-kerberos-start.sh 和 配置 kerberos-server.properties 启动 Kafka :

typescript 复制代码
bin/kafka-server-start-kerberos.sh -daemon kerberos/kerberos-server.properties

Kafka 客户端部署 Kerberos

第一步,准备 client-kerberos.properties 文件。 拷贝 Kafka config 目录下的 consumer.properties 文件,命名为 client-kerberos.properties ,编辑认证配置相关的内容:

typescript 复制代码
bootstrap.servers=192.168.10.102:9092
group.id=test-consumer-group001
curity.protocol=SASL_PLAINTEXT
sasl.mechanism=GSSAPI
sasl.kerberos.service.name=hello-kafka-server

第二步,准备 client-jaas.conf 配置文件。 kerberos 目录下,创建文件 kafka-client-jaas.conf,编辑内容如下:

typescript 复制代码
KafkaClient {
   com.sun.security.auth.module.Krb5LoginModule required
   useKeyTab=true
   //不同的主机,需修改成不同的keytab文件
   keyTab="/opt/kafka-1.0.2/kerberos/hello-kafka-client.keytab"
   storeKey=true
   useTicketCache=false
   // Client 在KDC中的帐号
   principal="hello-kafka-client@MY_KDC.COM";
};

第三步,准备 kafka-server-kerberos-start.sh 文件,添加 Kerberos 认证配置。 拷贝 bin/kafka-console-consumer.sh 脚本,命名为 kerberos-kafka-console-consumer.sh,编辑最后一行,在最后一行代码之前,添加 Krb5 环境变量和 jaas.conf 配置信息:

typescript 复制代码
export KAFKA_OPTS="-Djava.security.krb5.conf=/opt/kafka-1.0.2/kerberos/krb5.conf 
-Djava.security.auth.login.config=/opt/kafka-1.0.2/kerberos/kafka-client-jaas.conf"

第四步,用第一步的配置文件,进行带认证的消费:

typescript 复制代码
bin/kerberos-kafka-console-consumer.sh --bootstrap-server 192.168.10.102:9092 --topic  my-topic --consumer.config=kerberos/client-kerberos.properties --from-beginning

KDC 日志查看认证过程

KDC 服务中心的日志文件是 /var/log/krb5kdc.log ,每次 Kerberos 认证都对应两条日志信息:

如果 Kafka 服务启动或者客户端启动失败,也可以查看该日志文件,常见的错误就是主机和域名、服务名称配置不一致,导致 Server not found in Kerberos database 异常。

另外,多域名问题,还没有找到解决办法。如果一个客户端的 krb5.conf 文件中配置多个 Realm ,默认只能有一个 Realm ,但是对于需要同时访问多个 Kafka 、多套认证 Realm 的应用来说,到底该怎么配置呢?

启示录

官方 Kerberos 资料,没有耐心看下去,网络上搜到的,照猫画虎实践下来,其实也能部署下来的,关键是 kerberos.service.name 这个属性,想了两天才想明白,还有主机域名配置等基础支持等,零零碎碎,以此留存网络笔记。

相关推荐
floret*2 小时前
用pyspark把kafka主题数据经过etl导入另一个主题中的有关报错
分布式·kafka·etl
william8233 小时前
Information Server 中共享开源服务中 kafka 的__consumer_offsets目录过大清理
分布式·kafka·开源
lzhlizihang5 小时前
Kafka一些常用的命令行操作【包含主题命令、生产者和消费者命令】
kafka
Hsu_kk5 小时前
Kafka 安装教程
大数据·分布式·kafka
苍老流年5 小时前
1. kafka分布式环境搭建
分布式·kafka
sj11637394035 小时前
Kafka参数了解
数据库·分布式·kafka
Hsu_kk6 小时前
Kafka Eagle 安装教程
分布式·kafka
CodingBrother6 小时前
Kafka 与 RabbitMQ 的联系
分布式·kafka·rabbitmq
大熊程序猿17 小时前
ubuntu 安装kafka-eagle
linux·ubuntu·kafka
星染xr17 小时前
kafka 生产经验——数据积压(消费者如何提高吞吐量)
分布式·kafka