自 0.9.0 (scala 2.0) 版本开始,Kafka 可以同时集成 SSL 和 Kerberos,前者用于传输加密,后者用于身份认证。并且,Kerberos 用户可以选择映射到本地 UnixShellUserGroup,该场景下需要 Unix 和 KDC 中都存在用户信息才可以通过认证。在认证后,超级用户可以对 ACL 进行修改,实现对普通用户的操作授权。总得来看,是这样的:
关于协议的整合分为如下几种组合:
SSL | Kerberos | |
---|---|---|
PLAINTEXT | No | No |
SSL | Yes | No |
SASL_PLAINTEXT | No | Yes |
SASL_SSL | Yes | Yes |
本文描述的是基于第三种方式——不进行传输加密的 Kerberos 认证的 ACL(ZK本身没有开启 Kerberos 认证),即如何在 CDH 5.8.2 集群中(Kafka 版本为 2.1.0-1.2.1.0.p0.115):
- 整合 SASL/Kerberos;
- 开启 ACL,并进行生产/消费授权测试;
不包括 TLS 传输加密的配置实施,以及 DDL 相关授权测试。
本文需要您有 Kerberos 相关知识,假设 CDH 本身还没有集成 Kerberos,请参看:Step by Step 实现基于 Cloudera 5.8.2 的企业级安全大数据平台 - Kerberos的整合。
环境简述
OS: CentOS 7.2
CDH: 5.8.2
Kafka: 2.1.0-1.2.1.0.p0.115(对应社区 0.10.0.0)
Kerberos: 5
操作用户: admin
操作路径(pwd):/home/admin
主机角色分布:
- KDC: 172.16.134.8
- Zookeeper Server / Kafka Broker: 172.16.134.2
- Kafka Client: 172.16.129.161
整合 SASL/Kerberos
在开始本部分之前需要确认 Kerberos 已经完成安装。开启 Kafka SASL/Kerberos 的方式很简单,在 CM 管控页面(通常由7180 https 或者7183 https 端口进入,比如本文是 https://172.16.134.2:7183 )可以方便完成。
Step1. 进入 Kafka Service 页面;
Step2. 选择 Configuration
选项卡,进入配置页面;
Step3. 按照 Kerberos
关键字进行配置项搜索,对 Enable Kerberos Authentication
和 Authenticate Zookeeper Connection
选项进行勾选;
Step4. 重启 Kafka;
和社区版本不同的是,不需要设置 Inter Broker Protocol = SASL_PLAINTEXT
,因为默认就是和外部认证采取一样的配置。
测试认证
以下操作在 Kafka Client 上操作(172.16.129.161)。
安装 Kerberos 客户端:
sudo yum install -y krb5-devel krb5-workstation
修改 /etc/krb5.conf
配置文件,使得可以访问 KDC:
[logging]
default = FILE:/var/log/krb5libs.log
kdc = FILE:/var/log/krb5kdc.log
admin_server = FILE:/var/log/kadmind.log
[libdefaults]
default_realm = LWSITE.NET
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
[realms]
LWSITE.NET = {
kdc = 172.16.134.8
admin_server = 172.16.134.8
}
[domain_realm]
.lwsite.net = LWSITE.NET
lwsite.net = LWSITE.NET
在 Kerberos 中创建测试用的 principal:
kinit ${krb_admin_principal}
kadmin # 此处键入超级管理员密码
> addprinc test/[email protected] # 新建用户需要键入密码
> exit
使用 ticket cache 方式进行认证:
kinit test/[email protected]
创建 /home/admin/jass.conf.client.ticket
文件用于认证方式申明,我们在这里使用的是 krb5LoginModule
:
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useTicketCache=true;
};
申明 KAFKA_OPTS
环境变量,告诉客户端我们的相关配置:
export KAFKA_OPTS="-Djava.security.auth.login.config=/home/admin/jaas.conf.client.ticket -Djava.security.krb5.conf=/etc/krb5.conf -Dsun.security.krb5.debug=true"
# 开启debug是为了方便调试
创建测试用 topic:
kafka-topics --create --topic topic-test --replication-factor 1 --partitions 1 --zookeeper 172.16.134.2:2181
申明 /home/admin/client.properties
文件,用于协议相关配置,在生产和消费的时候都需要用到:
security.protocol=SASL_PLAINTEXT
sasl.kerberos.service.name=kafka
sasl.mechanism=GSSAPI
生产者测试:
kafka-console-producer --broker-list 172.16.134.2:9092 --topic topic-test --producer.config client.properties
消费者测试:
kafka-console-consumer --new-consumer --topic topic-test --from-beginning --bootstrap-server 172.16.134.2:9092 --consumer.config client.properties
开启 ACL
在 5.8.2 版本中,没有直接的配置可以进行开启,我们需要对 kafka.properties
文件进行修改,对应社区版本的 server.properties
文件。
Step1. 进入 Kafka Service 页面;
Step2. 选择 Configuration
选项卡,进入配置页面;
Step3. 按照 Kafka Broker Advanced Configuration Snippet (Safety Valve) for kafka.properties
关键字进行配置项搜索,添加如下配置:
authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer
super.users=User:kafka
配置申明了认证实现类和超级用户。
Step4. 重启 Kafka;
需要表明,我们不对 Kerberos 进行本地 Unix 用户映射。并且后续我们构造 producer/consumer 实例时候使用的用于认证的用户名等价于 Kerberos principal 中的 primary name,也就是 test/[email protected]
中的 test
。
测试 ACL
生产者测试
以下操作在 Kafka Broker 上操作(172.16.134.2)。
首先我们必须使用之前申明的超级用户 kafka
来进行 ACL 申明,创建 /home/admin/jass.conf.admin
文件用于认证方式申明,我们在这里使用的是 Krb5LoginModule
,ACL 相关接口必须走 keytab 方式认证,否则会报错:
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
principal="kafka/[email protected]"
keyTab="/tmp/kafka_kafka_admin.keytab";
};
Client {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
principal="kafka/[email protected]"
keyTab="/tmp/kafka_kafka_admin.keytab";
};
生成对应的 keytab,并保证运行命令的用户有读权限(生产环境推荐 keytab 文件权限 400) :
kinit ${krb_admin_principal}
kadmin # 此处键入超级管理员密码
> addprinc -randkey kafka/[email protected]
> ktadd -k /tmp/kafka_kafka_admin.keytab kafka/[email protected]
> exit
清除上一节中生成的 ticket cache:
kdestroy
对 test 用户进行写赋权:
export KAFKA_OPTS="-Djava.security.auth.login.config=/home/admin/jaas.conf.admin -Djava.security.krb5.conf=/etc/krb5.conf -Dsun.security.krb5.debug=true"
kafka-acls --topic topic-test --add --operation Write --allow-host 172.16.129.161 --allow-principal User:test --authorizer-properties zookeeper.connect=172.16.134.2:2181
以下操作在 Kafka Client 上操作(172.16.129.161)。
创建 /home/admin/jass.conf.client.keytab
文件用于认证方式申明,我们在这里使用的是 krb5LoginModule
:
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
principal="test/[email protected]"
keyTab="/tmp/test_kafka_krb_user.keytab";
};
生成对应的 keytab,并保证运行命令的用户有读权限(生产环境推荐 keytab 文件权限 400) :
kinit ${krb_admin_principal}
kadmin # 此处键入超级管理员密码
> addprinc -randkey test/[email protected]
> ktadd -k /tmp/test_kafka_krb_user.keytab test/[email protected]
> exit
申明 KAFKA_OPTS
环境变量,告诉客户端我们的相关配置:
export KAFKA_OPTS="-Djava.security.auth.login.config=/home/admin/jaas.conf.client.keytab -Djava.security.krb5.conf=/etc/krb5.conf -Dsun.security.krb5.debug=true"
# 开启debug是为了方便调试
复用上一节中的 client.properties
文件,使用 test 用户进行写测试:
kafka-console-producer --broker-list 172.16.134.2:9092 --topic topic-test --producer.config client.properties
没有异常则表示写入成功。
消费者测试
以下操作在 Kafka Broker 上操作(172.16.134.2),对 test 用户进行读赋权:
export KAFKA_OPTS="-Djava.security.auth.login.config=/home/admin/jaas.conf.admin -Djava.security.krb5.conf=/etc/krb5.conf -Dsun.security.krb5.debug=true"
kafka-acls --consumer --group group-test --topic topic-test --add --allow-host 172.16.129.161 --allow-principal User:test --authorizer-properties zookeeper.connect=172.16.134.2:2181
以下操作在 Kafka Client 上操作(172.16.129.161)。
修改 client.properties
在最后添加一行:
group.id=group-test
测试读:
kafka-console-consumer --new-consumer --topic topic-test --from-beginning --bootstrap-server 172.16.134.2:9092 --consumer.config client.properties
参考文献
[1] Configuring Kafka Security https://www.cloudera.com/documentation/kafka/latest/topics/kafka_security.html
[2] Apache Kafka Security 101 https://www.confluent.io/blog/apache-kafka-security-authorization-authentication-encryption/