项目需要将kafka配上kerberos,从来没接触过,靠着一堆教程勉强跑通
先说下网络环境,kafka服务器的IP为192.168.100.83 下文记做Linux 跑Java服务的IP为192.168.62.116 下文记做mac
首先要将两个机器的hosts互相添加主机名
在不添加主机名的情况下 没有成功 这步还是很重要的
linux的: hadoop03是跟着教程起的名字 无特殊含义 指向本机 并添加mac的主机名
代码语言:javascript复制[root@localhost kafka_2.12-2.4.0]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.100.83 hadoop03
192.168.62.116 mac
mac的: 主要是添加了linux的主机名
代码语言:javascript复制$ cat /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
192.168.100.83 hadoop03
配置Linux的kerberos
kerberos的身份认证包含三部分 名字/主机名@域名 这里我把域名配置为了HADOOP.COM
代码语言:javascript复制#安装服务
[root]# yum install krb5-server krb5-workstation krb5-libs
#安装完成后会生成该配置文件
#编辑配置文件
[root~]# vim /etc/krb5.conf
# Configuration snippets may be placed in this directory as well
includedir /etc/krb5.conf.d/
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
dns_lookup_realm = false
ticket_lifetime = 24h
#需要修改的地方
renew_lifetime = 7d
forwardable = true
rdns = false
pkinit_anchors = FILE:/etc/pki/tls/certs/ca-bundle.crt
#需要修改的地方
default_realm = HADOOP.COM
default_ccache_name = KEYRING:persistent:%{uid}
#需要修改的地方
[realms]
HADOOP.COM = {
kdc = hadoop03
admin_server = hadoop03
}
#需要修改的地方
[domain_realm]
.hadoop.com = HADOOP.COM
hadoop.com = HADOOP.COM
然后创建数据库 期间需要输入两次密码 不要忘记
代码语言:javascript复制[root]# kdb5_util create -s
Loading random data
Initializing database '/var/kerberos/krb5kdc/principal' for realm 'HADOOP.COM',
master key name 'K/M@HADOOP.COM'
You will be prompted for the database Master Password.
It is important that you NOT FORGET this password.
Enter KDC database master key: <==输入一次密码
Re-enter KDC database master key to verify: <==再输入一次
#执行后可以看看是否有这些文件生成
[root]# ll /var/kerberos/krb5kdc/
-rw-------. 1 root root 22 4月 29 2017 kadm5.acl
-rw-------. 1 root root 451 4月 29 2017 kdc.conf
-rw-------. 1 root root 8192 11月 27 12:04 principal
-rw-------. 1 root root 8192 11月 27 12:04 principal.kadm5
-rw-------. 1 root root 0 11月 27 12:04 principal.kadm5.lock
-rw-------. 1 root root 0 11月 27 12:04 principal.ok
添加一个管理员 修改如下文件
代码语言:javascript复制[root@kdc ~]# vim /var/kerberos/krb5kdc/kadm5.acl
*/admin@HADOOP.COM *
其实就只有将原本的 EXAMPLE.COM 改成我们的 kerberos 领域而已。另外想要管理 KDC 的资料库有两种方式, 一种直接在 KDC 本机上面直接执行,可以不需要密码就登入资料库管理;一种则是需要输入帐密才能管理
这两种管理方式分别是:
kadmin.local:需要在 KDC server 上面运作,无须密码即可管理资料库 kadmin:可以在任何一台 KDC 领域的系统上面运作,但是需要输入管理员密码
我们想要让 KDC 用户端也能够『使用 root 身份来登入 KDC 资料库的管理』,这个身份在 KDC 裡面被称为『 root/admin 』
在 KDC server 上面使用 kadmin.local 来执行底下的指令,以建立好相关的帐号
代码语言:javascript复制[root@kdc ~]# kadmin.local
Authenticating as principal root/admin@HADOOP.COM with password.
kadmin.local: ? # 可以使用 ? 来了解所有的指令用途
Available kadmin.local requests:
add_principal, addprinc, ank
Add principal
delete_principal, delprinc
Delete principal
modify_principal, modprinc
Modify principal
rename_principal, renprinc
Rename principal
change_password, cpw Change password
get_principal, getprinc Get principal
list_principals, listprincs, get_principals, getprincs
List principals
....(其他省略)....
kadmin.local: addprinc root/admin
WARNING: no policy specified for root/admin@HADOOP.COM; defaulting to no policy
Enter password for principal "root/admin@HADOOP.COM": <==输入管理员密码
Re-enter password for principal "root/admin@HADOOP.COM": <==再输入一次
Principal "root/admin@HADOOP.COM" created.
kadmin.local: listprincs
K/M@HADOOP.COM
kadmin/admin@HADOOP.COM
kadmin/changepw@HADOOP.COM
kadmin/@HADOOP.COM
kiprop/hadoop03@HADOOP.COM
krbtgt/HADOOP.COM@HADOOP.COM
root/admin@HADOOP.COM <==这就是管理员的功能设定!
kadmin.local: exit
配置完成后 启动服务 并测试是否启动成功
代码语言:javascript复制[root@kdc ~]# systemctl start kadmin krb5kdc
[root@kdc ~]# systemctl enable kadmin krb5kdc
#测试命令
[root@kdc ~]# kadmin
Authenticating as principal root/admin@BOOK.VBIRD with password.
Password for root/admin@HADOOP.COM: <==需要输入密码
kadmin: listprincs <==随便使用一个命令测试一下
K/M@HADOOP.COM
kadmin/admin@HADOOP.COM
kadmin/changepw@HADOOP.COM
kadmin/hadoop03@HADOOP.COM
kiprop/hadoop03@HADOOP.COM
krbtgt/HADOOP.COM@HADOOP.COM
root/admin@HADOOP.COM
kadmin: exit
账户配置
需要两个账户 一个用来启动kafka 一个用来给mac使用
首先进入kafka的目录 假定以下操作均在kafka目录下
代码语言:javascript复制kadmin.local -q 'addprinc -randkey kafka/hadoop03@HADOOP.COM'
kadmin.local -q "xst -k kafka.keytab -norandkey kafka/hadoop03"
kadmin.local -q 'addprinc -randkey mac/mac@HADOOP.COM'
kadmin.local -q "xst -k kafka_mac.keytab -norandkey mac/mac"
之后会在当前目录下生成两个keytab文件 分别对应两个账户
Kafka配置
修改kafka的配置文件
代码语言:javascript复制vim config/server.properties
//修改这一句 这里我尝试过使用IP而不是hostname 可以启动但是mac连不上
listeners=SASL_PLAINTEXT://hadoop03:9092
//新增以下
authorizer.class.name = kafka.security.auth.SimpleAclAuthorizer
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=GSSAPI
sasl.enabled.mechanisms=GSSAPI
//上面账户是kafka/**@***什么什么的 这里就需要写kafka
sasl.kerberos.service.name=kafka
super.users=User:kafka
新建一个jaas文件 具体干嘛的我也不清楚 只知道需要连接就要一个jaas.conf 和一个keytab
代码语言:javascript复制touch ./config/kafka_server_jaas.conf
vim ./config/kafka_server_jaas.conf
#文件内容如下
#由于zookeeper使用的是内置的 没有进行加密操作 也就没有配置zk的
KafkaServer {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
#指定为上述生成的keytab
keyTab="kafka.keytab"
#这里对应上面的用户
principal="kafka/hadoop03@HADOOP.COM";
};
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
#指定为上述生成的keytab
keyTab="kafka.keytab"
#这里对应上面的用户
principal="kafka/hadoop03@HADOOP.COM"
useTicketCache=true;
};
修改kafka的启动脚本
代码语言:javascript复制#修改bin目录下kafka-run-class.sh,
vim bin/kafka-run-class.sh
#在exec $JAVA 后面增加kerberos启动参数,然后就可以用正常的脚本启动服务jaas的路径记得修改
-Djava.security.krb5.conf=/etc/krb5.conf -Djava.security.auth.login.config=/opt/kafka/config/kafka_server_jaas.conf
启动kafka后 为了方便命令行操作 分别在config/consumer.properties config/producer.properties 中添加
security.protocol=SASL_PLAINTEXT sasl.mechanism=GSSAPI sasl.kerberos.service.name=kafka
这样命令行就可以直接通过校验了
在命令行进行测试:
代码语言:javascript复制#创建topic
bin/kafka-topics.sh --zookeeper hadoop03:2181 --create --topic test_topic --partitions 1 --replication-factor 1
#启动生产者
bin/kafka-console-producer.sh --topic test_topic --broker-list hadoop03:9092 --producer.config config/producer.properties
#在另一个窗口启动消费者
bin/kafka-console-consumer.sh --bootstrap-server hadoop03:9092 --topic test_topic --consumer.config config/consumer.properties
Java端的调用
首先需要拷贝一份linux中的/etc/krb5.conf 与 kafka_mac.keytab 到mac中
代码语言:javascript复制System.setProperty("java.security.auth.login.config","/Users/abc/data/kafka_client_jaas.conf");
System.setProperty("java.security.krb5.conf","/Users/abc/data/krb5.conf");
#debug开关
System.setProperty("sun.security.krb5.debug", "true");
Properties props = new Properties();
#这里如果写IP 会报错 只有和kafka配置文件中写的一样才行 不知道为什么 props.put("bootstrap.servers", "hadoop03:9092");
props.put("group.id", "kafka_read");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
#需要额外添加的配置
props.put("sasl.mechanism","GSSAPI");
props.put("sasl.kerberos.service.name","kafka");
props.put("security.protocol","SASL_PLAINTEXT");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
Set<String> set = new HashSet<>();
set.add("test_topic");
consumer.subscribe(set);
其中kafka_client_jaas.conf 是mac创建的,内容为:
代码语言:javascript复制// Kafka client authentication
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
keyTab="/Users/abc/data/kafka_mac.keytab"
principal="mac/mac@HADOOP.COM";
};
可以看出 mac与linux两台机器具有相同的krb5.conf文件 在mac中 jaas文件中的keytab 指向了对应身份生成的keytab 且principal值也要是对应的值 在linux中的kafka中 jaas情况相同
然后启动消费者 并使其无限循环打印输出 但是又一个问题来了 控制台报错:GroupAuthorizationException: Not authorized to access group 又是一顿百度 最后的解决办法为:
执行kafka脚本:分别为mac与匿名用户添加权限
bin/kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:2181 --allow-principal User:mac --consumer --topic=* --group=* --add
bin/kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:2181 --allow-principal User:ANONYMOUS --consumer --topic=* --group=* --add
经过一下午的折腾 终于能收到消息了 太不容易了
授权生产权限的命令为:
./kafka-acls.sh --authorizer-properties zookeeper.connect=localhost:2181/kafka --allow-principal User:ANONYMOUS --producer --topic=* --add
参考文章:
https://www.cnblogs.com/xiaodf/p/5968178.html
http://linux.vbird.org/linux_enterprise/kerberos.php
https://blog.csdn.net/ahzsg1314/article/details/54140909
https://blog.csdn.net/catcher92/article/details/86705970