Kafka linux(centos7)安装配置kerberos并在另一台机器上使用Java服务接收消息

2020-08-03 09:15:07 浏览数 (1)

项目需要将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

0 人点赞