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 的日志看到这个结果:

Kafka 认证三:添加 Kerberos 认证详细流程_第1张图片

例如,我这个请求过程,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 文件中,参考如下:

192.168.10.102 oracle

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

KDC 注册客户端和服务端

第零步,拷贝 krb5.conf。

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

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 认证的代码为:

System.setProperty("java.security.krb5.conf", krb5Conf);

第一步,注册 Kerberos 帐号。

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

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

addprinc hello-kafka-client
addprinc hello-kafka-server/oracle

操作结果如下:

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

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 如下:

Kafka 认证三:添加 Kerberos 认证详细流程_第2张图片

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

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 ,编辑认证配置相关的内容:

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,编辑内容如下:

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 配置信息:

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 认证三:添加 Kerberos 认证详细流程_第3张图片

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

bin/kafka-server-start-kerberos.sh -daemon kerberos/kerberos-server.properties

Kafka 客户端部署 Kerberos

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

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,编辑内容如下:

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 配置信息:

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"

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

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 认证三:添加 Kerberos 认证详细流程_第4张图片
如果 Kafka 服务启动或者客户端启动失败,也可以查看该日志文件,常见的错误就是主机和域名、服务名称配置不一致,导致 Server not found in Kerberos database 异常。

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

启示录

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

你可能感兴趣的:(项目开发问题,kafka,java,Kerberos,认证)