Kafka3.4 SASL/kerberos ACL 證以及 SSL 加密連接
序
前面我們使用 kafka3.3.1 on zookeeper
的模式進行多網(wǎng)段監(jiān)聽的 kafka
集群,順便搭建起 kafkaui
后發(fā)現(xiàn)一些問題,我們 kafka
集群沒有連接認(rèn)證,萬一誰知道了我們的 kafka
連接地址,豈不是隨隨便便就能消費數(shù)據(jù)、清空數(shù)據(jù)、胡亂修改數(shù)據(jù)了嗎?
所以本章節(jié)進行認(rèn)證連接的搭建,參考官網(wǎng):
https://kafka.apache.org/documentation/#security
認(rèn)證類型
如果對 Kafka
連接協(xié)議有疑問的,請優(yōu)先查看 Kafka SASL ACL SSL 分別代表什么意思。
測試環(huán)境
版本信息
Kafka 3.4
CDH 6.3.2
Zookeeper 3.4.5
Krb5kdc 已經(jīng)啟動
服務(wù)器規(guī)劃信息
環(huán)境檢查項
- 關(guān)閉
selinux
- 關(guān)閉防火墻
- 如有條件請配置好
ansible
,在本文中bigdata_cluster
代指udmax0[1-4].udmax.com
Krb5Kdc 安裝配置
如果已經(jīng)安裝 krb5kdc
可忽略這部分內(nèi)容。
在主節(jié)點 udmax01.udmax.com
安裝 krb5 server
,使用如下命令:
yum install krb5-server krb5-libs krb5-auth-dialog krb5-workstation openldap-clients -y
如果速度過慢可以更改
yum
源。
其他節(jié)點只需要安裝執(zhí)行環(huán)境:
ansible bigdata_cluster -m shell -a 'yum install krb5-workstation krb5-libs -y '
更改 /var/kerberos/krb5kdc/kdc.conf
文件,如果不存在則創(chuàng)建:
[kdcdefaults]
kdc_ports = 88
kdc_tcp_ports = 88
[realms]
UDMAX.COM = {
#master_key_type = aes256-cts
acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal camellia256-cts:normal camellia128-cts:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
max_life = 3d
max_renewable_life = 7d
}
這里 reaml
叫做 UDMAX.COM
,后續(xù)大量地方會使用到。
更改 /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 = UDMAX.COM
default_cache_name = KEYRING:persistent:%{uid}
[realms]
UDMAX.COM = {
kdc = udmax01.udmax.com
admin_server = udmax01.udmax.com
}
[domain_realm]
.udmax.com = UDMAX.COM
udmax.com = UDMAX.COM
需要注意的有:
-
default_realm
指向realms
中的一項 -
realm
中的kdc
和admin_server
都指向我們的主節(jié)點。
配置完畢后分發(fā)文件:
ansible bigdata_cluster -m copy -a "src=/etc/krb5.conf dest=/etc/krb5.conf"
如果沒有
ansible
,請使用scp
命令。
初始化 kdc database
:
kdb5_util create –r UDMAX.COM -s
Enter KDC database master key:
這里需要輸入密碼,在這篇文章中稱之為
{{kdc_master_key}}
。
開啟 krb5kdc
服務(wù):
systemctl start krb5kdc
systemctl status krb5kdc
Kafka 3.4 安裝
# 先安裝scala
curl -fL https://github.com/coursier/coursier/releases/latest/download/cs-x86_64-pc-linux.gz | gzip -d > cs && chmod +x cs && ./cs setup
# 或者離線安裝包
wget https://downloads.lightbend.com/scala/2.12.17/scala-2.12.17.tgz
ansible bigdata_cluster -m shell -a "mkdir -p /usr/scala/"
ansible bigdata_cluster -m copy -a "src=scala-2.12.17.tgz dest=/usr/scala/scala-2.12.17.tgz"
ansible bigdata_cluster -m shell -a "cd /usr/scala/; tar -zxvf scala-2.12.17.tgz"
# 環(huán)境變量
vim /etc/profile.d/scala.sh
export SCALA_HOME=/usr/scala/scala-2.12.17
export SCALA_PATH=${SCALA_HOME}/bin
export PATH=${PATH}:${SCALA_PATH}
ansible bigdata_cluster -m copy -a "src=/etc/profile.d/scala.sh dest=/etc/profile.d/scala.sh"
解壓離線安裝包,規(guī)劃安裝路徑:
mkdir /component/kafka/
cd /component/kafka
wget https://downloads.apache.org/kafka/3.4.0/kafka_2.12-3.4.0.tgz
tar -zxvf kafka_2.12-3.4.0.tgz
注冊 Kafka 的 kerberos 用戶
# 創(chuàng)建kafka用戶
addprinc -randkey kafka/udmax01@UDMAX.COM
addprinc -randkey kafka/udmax02@UDMAX.COM
addprinc -randkey kafka/udmax03@UDMAX.COM
addprinc -randkey kafka/udmax04@UDMAX.COM
# 導(dǎo)出票據(jù),可以導(dǎo)到一個文件中,或者分開也行
xst -norandkey -k /etc/security/keytab/kafkaX.keytab kafka/udmax01@UDMAX.COM
xst -norandkey -k /etc/security/keytab/kafkaX.keytab kafka/udmax02@UDMAX.COM
xst -norandkey -k /etc/security/keytab/kafkaX.keytab kafka/udmax03@UDMAX.COM
xst -norandkey -k /etc/security/keytab/kafkaX.keytab kafka/udmax04@UDMAX.COM
此時生成的 kafkaX.keytab
文件需要分發(fā)到各個服務(wù)器上:
ansible bigdata_cluster -m copy -a "src=/etc/security/keytab/kafkaX.keytab dest=/etc/security/keytab/"
在 9092 端口開啟 SASL_PLAINTEXT 認(rèn)證
首先,我們可以先配置一個 SASL_PLAINTEXT
認(rèn)證,這里采用 SASL/GSSAPI
進行,主體就是剛剛生成的 kafka
。
配置文件更改
conf/server.properties
備份相關(guān)文件
# 備份
cd /component/kafka/kafka_2.12-3.4.0/config
cp server.properties server.properties.backup
修改 server.properties
中的內(nèi)容:
broker.id=001102
reserved.broker.max.id=255255
listeners=SASL_PLAINTEXT://udmax02.udmax.com:9092
advertised.listeners=SASL_PLAINTEXT://udmax02.udmax.com:9092
inter.broker.listener.name=SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol=GSSAPI
sasl.kerberos.service.name=kafka
auto.create.topics.enable=false
delete.topic.enable=true
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
log.dirs=/component/kafka/kafka-logs
num.partitions=1
num.recovery.threads.per.data.dir=1
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.retention.hours=168
log.retention.check.interval.ms=300000
zookeeper.connect=udmax02.udmax.com:2181,udmax03.udmax.com:2181,udmax04.udmax.com:2181
zookeeper.connection.timeout.ms=18000
group.initial.rebalance.delay.ms=0
注意 listeners
中為 Kafka broker
監(jiān)聽的地址,這里監(jiān)聽了端口 9092
,協(xié)議使用的為 SASL_PLAINTEXT
。而 sasl.mechanism.inter.broker.protocol
指定的 SASL
使用 GSSAPI
。那么對應(yīng)的 SASL
相關(guān)配置為:
sasl.mechanism.inter.broker.protocol=GSSAPI
sasl.kerberos.service.name=kafka
這里表明使用
SASL/GSSAPI(Kerberos)
進行身份驗證,并且采用的principal
名為kafka
conf/kerberos/krb5_kafka.conf
該文件以及目錄不存在,需要創(chuàng)建:
# 將krb5.conf 抽離一個出來,主要是某些krb5.conf可能有問題(特別是CDH接管后)。
cp /etc/krb5.conf conf/kerberos/krb5_kafka.conf
# 主要的內(nèi)容如下:
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[kdc]
profile = /var/kerberos/krb5kdc/kdc.conf
[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 = UDMAX.COM
default_ccache_name = KEYRING:persistent:%{uid}
storeKey=false
[realms]
UDMAX.COM = {
kdc = udmax01.udmax.com
admin_server = udmax01.udmax.com
}
[domain_realm]
.udmax.com = UDMAX.COM
udmax.com = UDMAX.COM
conf/kerberos/client.properties
用于在服務(wù)器環(huán)境內(nèi)進行連接,因為當(dāng)前需要連接 kafka
集群,所以都需要認(rèn)證。
我們開啟了端口 9092
,為 SASL_PLAINTEXT
,所以連接時也需要配置對應(yīng)的連接認(rèn)證,GSSAPI
對應(yīng)的就是 com.sun.security.auth.module.Krb5LoginModule
認(rèn)證:
security.protocol=SASL_PLAINTEXT
sasl.mechanism=GSSAPI
sasl.kerberos.service.name=kafka
sasl.jaas.config=com.sun.security.auth.module.Krb5LoginModule required \
useKeyTab=true \
keyTab="/etc/security/keytab/kafkaX.keytab" \
principal="kafka/udmax02.udmax.com@UDMAX.COM" \
renewTGT=true \
storeKey=false \
useTicketCache=true;
這里使用的 principal
為最高權(quán)限的 kafka
用戶,一般來說應(yīng)當(dāng)設(shè)置為租戶。比如這樣的配置:
security.protocol=SASL_PLAINTEXT
sasl.mechanism=GSSAPI
sasl.kerberos.service.name=kafka
sasl.jaas.config=com.sun.security.auth.module.Krb5LoginModule required \
useKeyTab=true \
keyTab="/etc/security/keytab/udmax.keytab" \
principal="udmax@UDMAX.COM" \
renewTGT=true \
storeKey=false \
useTicketCache=true;
注意 sasl.kerberos.service.name
應(yīng)當(dāng)是連接 kafka broker
的名稱,也是 server.properties
中的 sasl.kerberos.service.name
。
conf/kerberos/kafka_server_jaas.conf
當(dāng) kafka broker
啟動的時候,會根據(jù)該文件獲取自身的 SASL
信息,可以理解為當(dāng) Kafka
集群啟動時,他們也需要互相認(rèn)證對方是否合法。常規(guī)內(nèi)容如下:
KafkaServer {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
useTicketCache=false
keyTab="/etc/security/keytab/kafkaX.keytab"
principal="kafka/udmax02.udmax.com@UDMAX.COM";
};
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
useTicketCache=false
principal="kafka/udmax02.udmax.com@UDMAX.COM"
keyTab="/etc/security/keytab/kafkaX.keytab";
};
Client {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
useTicketCache=false
principal="kafka/udmax02.udmax.com@UDMAX.COM"
keyTab="/etc/security/keytab/kafkaX.keytab";
};
請注意每個 kafka broker
的 principal
應(yīng)當(dāng)與自己的服務(wù)器名 hostname
一致。
Client {}
中的內(nèi)容為 kafka broker
連接 zookeeper
時需要的認(rèn)證信息,如果 zookeeper
未開啟認(rèn)證,則不需要相關(guān)配置。值得注意的是作者在測試時發(fā)現(xiàn)CDH 6.3.2中的Zookeeper顯示開啟認(rèn)證,實際情況并沒有。
執(zhí)行文件配置
到此我們相關(guān)的配置已經(jīng)配置完畢,但是常用的啟停程序還需要統(tǒng)一更改。
涉及到的啟動程序包括:
- bin/kafka-server-start.sh
- bin/kafka-console-consumer.sh
- bin/kafka-console-producer.sh
- bin/kafka-topics.sh
- bin/kafka-acls.sh
其實就是我們會在環(huán)境中使用到的 shell
都需要進行更改,更改的方式也很簡單在上述文件的倒數(shù)第二行加上我們設(shè)定的環(huán)境變量:
export KAFKA_OPTS="-Dzookeeper.sasl.client=ture -Dzookeeper.sasl.client.username=kafka -Djava.security.krb5.conf=/component/kafka/kafka_2.12-3.4.0/config/kerberos/krb5_kafka.conf -Djava.security.auth.login.config=/component/kafka/kafka_2.12-3.4.0/config/kerberos/kafka_server_jaas.conf"
如果 zookeeper 未開啟 sasl 請將
-Dzookeeper.sasl.client
設(shè)置為false
。
此時如果 SASL_PLAINTEXT
已經(jīng)足夠,則不需要繼續(xù)開啟 SSL
認(rèn)證,跳到 啟動 Kafka
即可。
在 9094 端口開啟 SASL_SSL 認(rèn)證
在剛剛的配置中,已經(jīng)使用 SASL/GSSAPI
完成了身份驗證,現(xiàn)在添加 SSL
傳輸加密。
在 SSL
中,我們還需要生成證書以及兩個 jks
文件。
生成證書并配置
創(chuàng)建文件夾進行操作
ansible bigdata_cluster -m shell -a " mkdir -p /opt/ca "
cd /opt/ca
每個 broker 生成 server.keystore.jks
先在每臺服務(wù)器生成 server.keystore.jks
文件,使用命令:
keytool -keystore server.keystore.jks \
-alias udmax01 \
-validity 36500 \
-genkey \
-keypass {{ssl.key.password}} \
-keyalg RSA \
-dname "CN=udmax01.udmax.com,OU=yd,O=yd,L=beijing,S=beijing,C=cn" \
-ext SAN=IP:{{內(nèi).網(wǎng).i.p}},IP:{{外.網(wǎng).i.p}},DNS:udmax01.udmax.com,DNS:udmax01 \
-storepass {{ssl.keystore.password}}
注意:
-
-dname
中的CN
要與每臺服務(wù)器名hostname
一致 -
-ext
中對應(yīng)ip
以及DNS
最好寫全,{{內(nèi).網(wǎng).i.p}}
與{{外.網(wǎng).i.p}}
是代指如192.168.1.100
。 -
-keypass
與-storepass
在后續(xù)需要用到,本文使用{{ssl.key.password}}
和{{ssl.keystore.password}}
進行代指。
在主節(jié)點生成 CA 證書
通過 openssl
生成證書,如果沒有可以進行安裝:
yum install openssl -y
使用如下命令創(chuàng)建 CA 證書:
openssl req -new -x509 -keyout ca-key -out ca-cert -days 36500 \
-passin pass:{{openssl_password}} -passout pass:{{openssl_password}} \
-subj "/C=CN/ST=Beijing/L=Beijing/O=yd/CN=ud"
注意:
- pass 中的密碼也被
{{openssl_password}}
代替。
生成后進行分發(fā)文件:
ansible bigdata_cluster -m copy -a " src=ca-cert dest=/opt/ca/ "
ansible bigdata_cluster -m copy -a " src=ca-key dest=/opt/ca/ "
ansible bigdata_cluster -m shell -a " ls -ltr /opt/ca "
此時的 /opt/ca
目錄中有如下文件:
途中 old 文件可以忽略
每個 broker 通過 CA 證書創(chuàng)建客戶端信任證書
# 創(chuàng)建 client.truststore.jks
keytool -keystore client.truststore.jks -alias UdmaxCA -import -file ca-cert -storepass {{ssl.keystore.password}} -keypass {{ssl.key.password}}
# 創(chuàng)建 server.keystore.jks
keytool -keystore server.keystore.jks -alias udmax01 -certreq -file cert-file -storepass {{ssl.keystore.password}} -keypass {{ssl.key.password}}
# 創(chuàng)建 cert-signed 后續(xù)進行蓋章
openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days 36500 -CAcreateserial -passin pass:{{openssl_password}}
# 將 ca-cert 導(dǎo)入server.keystore.jks
keytool -keystore server.keystore.jks -alias UdmaxCA -import -file ca-cert -storepass {{ssl.keystore.password}} -keypass {{ssl.key.password}}
# 將 cert-signed 導(dǎo)入server.keystore.jks
keytool -keystore server.keystore.jks -alias udmax01 -import -file cert-signed -storepass {{ssl.keystore.password}} -keypass {{ssl.key.password}}
此時就已經(jīng)完成了 SSL
文件的準(zhǔn)備:
實操截圖如下(為了區(qū)分證書,每臺的 alias
進行改動,其實根本也沒必要):
Kafka SSL 配置
conf/server.properties
相關(guān)的 SSL
配置為:
ssl.keystore.location=/opt/ca/server.keystore.jks
ssl.truststore.location=/opt/ca/server.truststore.jks
ssl.keystore.password={{ssl.keystore.password}}
ssl.key.password={{ssl.key.password}}
ssl.client.auth=required
其他文件
由于 SSL
其實涉及到加解密的過程,一般只是對外使用,在內(nèi)網(wǎng)環(huán)境可以不開啟,所以內(nèi)網(wǎng)中的各類 shell
連接 9092
端口,無需再進行 SSL
配置,如果需要請參考后續(xù) Java SASL_SSL 程序連接 Demo
。
開啟 ACL
如果需要開啟 ACL
請優(yōu)先開啟 SASL
,ACL
配置為:
authorizer.class.name=kafka.security.authorizer.AclAuthorizer
super.users=User:kafka
開啟了 ACL 認(rèn)證,采用
kafka
自帶的授權(quán)驗證,其中超級用戶名叫做kafka
。
啟動 Kafka
使用如下命令進行啟動:
bin/kafka-server-start.sh -daemon /component/kafka/kafka_2.12-3.4.0/config/server.properties
使用如下命令查看 topics
信息:
/component/kafka/kafka_2.12-3.4.0/bin/kafka-topics.sh --describe --bootstrap-server udmax02.udmax.com:9092 --command-config /component/kafka/kafka_2.12-3.4.0/config/kerberos/client.properties
可能剛剛創(chuàng)建,并未有 topic 信息,但查看是否有報錯。
使用如下命令查看 kafka broker
日志:
tailf /component/kafka/kafka_2.12-3.4.0/logs/server.log
Java SASL_SSL 程序連接 Demo
package com.huangyichun;
import org.apache.kafka.clients.CommonClientConfigs;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.config.SslConfigs;
import java.util.Properties;
public class KafkaConnectionProducerSaslSsl {
private static final String TOPIC_NAME = "test-topic";
public static void main(String[] args) {
System.setProperty("java.security.krb5.conf", "src/main/resources/krb5_kafka.conf");
System.setProperty("java.security.auth.login.config", "src/main/resources/kafka_client_kafka.conf");
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "udmax02.udmax.com:9094,udmax03.udmax.com:9094,udmax04.udmax.com:9094");
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
props.put(ProducerConfig.COMPRESSION_TYPE_CONFIG, "gzip");
props.put(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG, "src/main/resources/ca/client.truststore.jks");
props.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG, "{{ssl.truststore.password}}");
props.put(SslConfigs.SSL_TRUSTSTORE_TYPE_CONFIG, "JKS");
props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SASL_SSL");
props.put("sasl.kerberos.service.name", "kafka");
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
try {
for (int i = 0; i < 1000; i++) {
Thread.sleep(5000L);
ProducerRecord<String, String> record = new ProducerRecord<>(TOPIC_NAME, "key" + (i / 10), "message: " + i);
producer.send(record);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
其中 kafka_client_udmax.conf
中的內(nèi)容為:
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
rdns = false
useKeyTab=true
storeKey=true
useTicketCache=false
principal="udmax@UDMAX.COM"
keyTab="src/main/resources/keytab/udmax.keytab";
};
報錯錦集
Could not login: the client is being asked for a password, but the Kafka client code does not currently support obtaining a password from the user. not available to garner authentication information from the user
keytab
文件與 principal
密碼不匹配。
Not authorized to access topics [XXX]
沒有權(quán)限訪問 XXX
topic,被 ACL 擋住,使用 kafka-acl.sh
進行賦權(quán)。
General SSLEnginge problem, No name matching xxxx.xxx.xx found
SSL 無法找到匹配的 server
證書,大概率是在生成 server.keystore.jks
時將 CN
填寫錯誤,請?zhí)顚懨颗_ hostname
的值。
文章來源:http://www.zghlxwxcb.cn/news/detail-631469.html
總結(jié)
如果對您有幫助,請點贊!文章來源地址http://www.zghlxwxcb.cn/news/detail-631469.html
到了這里,關(guān)于Kafka3.4 SASL/kerberos/ACL 證以及 SSL 加密連接的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!