准备工作
配置kdc
配置kafka brokers
配置zookeeper
配置kafka客户端
常见问题
系统环境:Centos 7
在Kerberos的部署过程中,要求使用FQDN,即Hostname.DomainName
。
hostname的查看命令: hostname
domainname的查看命令:dnsdomainname
FQDN的查看命令:hostname -f
建议不修改 FQDN (此处提供一种设置Linux的FQDN的方法: /etc/hostname + /etc/hosts文件组合 ,首先在/etc/hostname文件中设置主机名, 假设是 sqq 然后在/etc/hosts文件中增加一行主机记录, 第一个字段是该主机的IP地址, 第二个字段是你希望设置的FQDN, 最后是刚刚设置的主机名, 如下 A.B.C.D sqq.example.com sqq 设置好之后, 通过hostname -F /etc/hostname更新主机名. 这时, 通过hostname -f看到的FQDN就应该是: sqq.example.com)
验证FQDN是否可用,直接ping hostname -f的结果
处理好FQDN的问题之后,开始搭建kdc服务器
执行如下命令
yum install -y krb5-server krb5-libs krb5-workstation
安装完成后,修改/etc/krb5.conf
,将realms
修改成需要使用的域,本例中就直接使用EXAMPLE.COM
安装完kdc之后,修改/etc目录下的krb5.conf。修改其中realms中两个属性值kdc,admin_server为主机ip
[realms]
EXAMPLE.COM = {
kdc = 12.1.3.4
admin_server = 12.1.3.4
}
随后执行以下命令创建kdc数据库
/usr/sbin/kdb5_util create -s
这个创建的过程会比较久,显示提示之后再输入两次密码,创建KDC数据库即完成。
创建完数据库之后开始新建 principal,每个角色都需要创建,包括每一个kafka broker、kafka client和zookeeper
执行以下命令进入交互模式
/usr/sbin/kadmin.local
执行以下命令创建 principal
addprinc -randkey {user}/{hostname}@{REALM}
ktadd -k /some/where/{keytabname}.keytab {user}/{hostname}@{REALM}
如果不写域 (上述@{REALM}部分),将使用默认域,默认域在krb5.conf中配置。
举例,若kafka节点broker0所在的机器hostname -f命令得到的值为broker0.example.com
,在Kerberos中对应的域为EXAMPLE.COM
,这个节点的管理者是alice
(这个管理者可以随便取,zookeeper例外,zookeeper的管理者默认为zookeeper,下面会有进一步说明)。这个节点的principal为alice/[email protected]
,命令为
addprinc -randkey alice/[email protected]
ktadd -k /root/kafka.keytab alice/[email protected]
ZooKeeper用“zookeeper”作为默认的服务名。如果您想修改的话,将系统参数zookeeper.sasl.client.username
设为合适的名字(例如,-Dzookeeper.sasl.client.username=zk)
zookeeper的principal创建,如果使用的是kafka自带的zookeeper则需要新建两个
addprinc -randkey zookeeper/[email protected]
ktadd -k /root/zk.keytab zookeeper/[email protected]
addprinc -randkey zookeeper/[email protected]
ktadd -k /root/zk.keytab zookeeper/[email protected]
现在我们应该有这些文件:
krb5.conf
zk.keytab
broker0.keytab
broker1.keytab
...
client.keytab
...
最后启动
/etc/init.d/krb5kdc start
/etc/init.d/kadmin start
这个步骤需要 krb5.conf 和 broker*.keytab zk.keytab
新建一个配置文件,这里假设名为kafka_server_jaas.conf
在这个文件中配置broker使用的SASL方式,keytab文件的位置和要使用的principal。
KafkaServer {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
keyTab="/location/of/your/broker0.keytab"
principal="kafka/[email protected]";
};
// Zookeeper client authentication ,使用kafka自带的zookeeper时需要将principal改为zookeeper/[email protected] 对应keyTab也要改
Client {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
keyTab="/location/of/your/zk.keytab"
principal="kafka/[email protected]";
};
同样的,修改broker的启动脚本,先复制出一份,这里是kafka-server-start-sasl.ssh
和kafka-run-classl-sasl.sh
修改kafka-server-start-sasl.ssh
,将最后一行的脚本改为kafka-run-class-sasl.sh
。修改kafka-run-class-sasl.sh
,增加启动参数'
-Djava.security.krb5.conf=/location/of/krb5.conf -Djava.security.auth.login.config=/location/of/kafka_server_jaas.conf
在server.properties
中配置SASL端口和SASL机制:
listeners=SASL_PLAINTEXT://host.name:port
security.inter.broker.protocol=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=GSSAPI
sasl.enabled.mechanisms=GSSAPI
sasl.kerberos.service.name=kafka
其中sasl.kerberos.service.name
要和principal的名称相同。
这个步骤需要krb5.conf
和zk.keytab
新建一个配置文件,这里假设名为zk-jaas.conf
在这个文件中配置zookeeper使用的JAAS方式(Krb5LoginModule),keytab文件的位置和要使用的principal。
Server {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="/root/zk.keytab"
storeKey=true
useTicketCache=false
principal="zookeeper/[email protected]";
};
修改zookeeper的配置,添加以下内容
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
requireClientAuthScheme=sasl
jaasLoginRenew=3600000
然后修改zookeeper的启动参数,将启动脚本另外复制一份,这里是zk-server-start-sasl.sh
和zk-run-class-sasl.sh
。修改zk-server-start-sasl.sh
,将最后一行的脚本改为zk-run-class-sasl.sh
。
修改zk-run-class-sasl.sh
,增加启动参数
-Djava.security.krb5.conf=/location/of/krb5.conf -Djava.security.auth.login.config=/location/of/zk-jaas.conf
然后使用zk-server-start-sasl.sh
启动zookeeper。
这个步骤需要krb5.conf
和client.keytab
新建一个配置文件,这里假设名为kafka_client_jaas.conf
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
useTicketCache=true
keyTab="/root/client.keytab"
principal="kafka-client/[email protected]";
};
在 producer.properties 和 consumer.properties中配置以下属性
security.protocol=SASL_PLAINTEXT
sasl.mechanism=GSSAPI
sasl.kerberos.service.name=kafka
然后修改producer和consumer的启动参数,将启动脚本另外复制一份,这里是kafka-producer-run-class.sh
和kafka-consumer-run-class.sh
。修改kafka-console-producer.sh
和kafka-console-consumer.sh
,将最后一行的脚本分别改为kafka-producer-run-class.sh
和kafka-consumer-run-class.sh
。
修改kafka-producer-run-class.sh
和kafka-consumer-run-class.sh
,增加启动参数
-Djava.security.krb5.conf=/location/of/krb5.conf -Djava.security.auth.login.config=/location/of/kafka_client_jaas.conf
使用以下命令分别启动producer和consumer
bin/kafka-console-producer.sh --broker-list 16.2.3.3:9092 --topic test --producer.config config/producer.properties
bin/kafka-console-consumer.sh --bootstrap-server 16.2.3.3:9092 --topic test -from-beginning --consumer.config config/consumer.properties
代码中配置
首先确保能使用主机名访问我们搭建的环境,本例中,我在本地windows系统中跑测试程序时,会将对应kdc服务器上/etc/hosts文件中记录的ip到主机名的对应关系添加到 C:\Windows\System32\drivers\etc\hosts 中
12.1.3.4 kdc.example.com
代码中添加
props.put("security.protocol", "SASL_PLAINTEXT");
props.put(SaslConfigs.SASL_MECHANISM, SaslConfigs.GSSAPI_MECHANISM);
props.put(SaslConfigs.SASL_KERBEROS_SERVICE_NAME, "kafka");
将krb5.conf,kafka_client_jaas.conf复制出来,在程序的启动参数中添加
-Djava.security.krb5.conf=C:\sqq\krb5.conf -Djava.security.auth.login.config=C:\sqq\kafka_client_jaas.conf
报错
javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7) - LOOKING_UP_SERVER)])
原因:KDC中没有对应的principal,是不是打错了,或者配置的主机名不正确。
可以查看kdc日志分析错误
kdc日志在/var/log/krb5kdc.log中可以看到
注:kafka 0.10.x的安全配置也同样如此
参考:
zookeeper配置kerberos认证的坑
Kerberos安装教程及使用详解
[5.1版本logstash到kafka输出的安全配置](https://www.elastic.co/guide/en/logstash/5.1/plugins-outputs-kafka.html)