上一章节介绍了 Kerberos 服务端和客户端的部署过程,本章节继续介绍 Kafka 添加 Kerberos 认证的部署流程,及 Java API 操作的注意事项。
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 文件中,参考如下:
192.168.10.102 oracle
在 Kafka 客户端主机上部署一份 kafka ,用于启动消费者应用;服务端正常部署 Kafka ,且在 kafka 主目录下创建一个 kerberos 文件夹,放 Kerberos 认证相关的配置文件。
第零步,拷贝 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 如下:

第三步,传输 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
第一步,准备 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 服务。 用新建的脚本 kafka-server-kerberos-start.sh 和 配置 kerberos-server.properties 启动 Kafka :
bin/kafka-server-start-kerberos.sh -daemon kerberos/kerberos-server.properties
第一步,准备 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 服务中心的日志文件是 /var/log/krb5kdc.log ,每次 Kerberos 认证都对应两条日志信息:

如果 Kafka 服务启动或者客户端启动失败,也可以查看该日志文件,常见的错误就是主机和域名、服务名称配置不一致,导致 Server not found in Kerberos database 异常。
另外,多域名问题,还没有找到解决办法。如果一个客户端的 krb5.conf 文件中配置多个 Realm ,默认只能有一个 Realm ,但是对于需要同时访问多个 Kafka 、多套认证 Realm 的应用来说,到底该怎么配置呢?
官方 Kerberos 资料,没有耐心看下去,网络上搜到的,照猫画虎实践下来,其实也能部署下来的,关键是 kerberos.service.name 这个属性,想了两天才想明白,还有主机域名配置等基础支持等,零零碎碎,以此留存网络笔记。
当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/
我有一个ModularSinatra应用程序,我正在尝试将Bootstrap添加到应用程序中。get'/bootstrap/application.css'doless:"bootstrap/bootstrap"end我在views/bootstrap中有所有less文件,包括bootstrap.less。我收到这个错误:Less::ParseErrorat/bootstrap/application.css'reset.less'wasn'tfound.Bootstrap.less的第一行是://CSSReset@import"reset.less";我尝试了所有不同的路径格式,但它
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
当谈到运行时自省(introspection)和动态代码生成时,我认为ruby没有任何竞争对手,可能除了一些lisp方言。前几天,我正在做一些代码练习来探索ruby的动态功能,我开始想知道如何向现有对象添加方法。以下是我能想到的3种方法:obj=Object.new#addamethoddirectlydefobj.new_method...end#addamethodindirectlywiththesingletonclassclass这只是冰山一角,因为我还没有探索instance_eval、module_eval和define_method的各种组合。是否有在线/离线资
我注意到类定义,如果我打开classMyClass,并在不覆盖的情况下添加一些东西我仍然得到了之前定义的原始方法。添加的新语句扩充了现有语句。但是对于方法定义,我仍然想要与类定义相同的行为,但是当我打开defmy_method时似乎,def中的现有语句和end被覆盖了,我需要重写一遍。那么有什么方法可以使方法定义的行为与定义相同,类似于super,但不一定是子类? 最佳答案 我想您正在寻找alias_method:classAalias_method:old_func,:funcdeffuncold_func#similartoca
我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主
我正在开发一个创建网络博客的RubyonRails项目。我希望将一个名为featured的boolean数据库字段添加到Post模型中。该字段应该可以通过我添加的事件管理界面进行编辑。我使用了以下代码,但我什至没有在网站上显示另一列。$railsgeneratemigrationaddFeaturedfeatured:boolean$rakedb:migrate我是RubyonRails的新手,非常感谢任何帮助。我的index.html.erb文件中的相关代码(views):FeaturedPost架构.rb:ActiveRecord::Schema.define(:version=>
假设我有一个这样的单例类:classSettingsincludeSingletondeftimeout#lazy-loadtimeoutfromconfigfile,orwhateverendend现在,如果我想知道使用什么超时,我需要编写如下内容:Settings.instance.timeout但我宁愿将其缩短为Settings.timeout使这项工作有效的一个明显方法是将设置的实现修改为:classSettingsincludeSingletondefself.timeoutinstance.timeoutenddeftimeout#lazy-loadtimeoutfromc