Step by Step 实现基于 Cloudera 5.8.2 的企业级安全大数据平台 - Kafka 整合 SASL/Kerberos 认证及 ACL

自 0.9.0 (scala 2.0) 版本开始,Kafka 可以同时集成 SSL 和 Kerberos,前者用于传输加密,后者用于身份认证。并且,Kerberos 用户可以选择映射到本地 UnixShellUserGroup,该场景下需要 Unix 和 KDC 中都存在用户信息才可以通过认证。在认证后,超级用户可以对 ACL 进行修改,实现对普通用户的操作授权。总得来看,是这样的:

Apache_Kafka_Security

关于协议的整合分为如下几种组合:

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 AuthenticationAuthenticate 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/kafka_krb_user@LWSITE.NET # 新建用户需要键入密码
> exit

使用 ticket cache 方式进行认证:

kinit test/kafka_krb_user@LWSITE.NET

创建 /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/kafka_krb_user@LWSITE.NET中的 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/kafka_admin@LWSITE.NET"
  keyTab="/tmp/kafka_kafka_admin.keytab";
};
Client {
  com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=true
  storeKey=true
  principal="kafka/kafka_admin@LWSITE.NET"
  keyTab="/tmp/kafka_kafka_admin.keytab";
};

生成对应的 keytab,并保证运行命令的用户有读权限(生产环境推荐 keytab 文件权限 400) :

kinit ${krb_admin_principal}
kadmin # 此处键入超级管理员密码
> addprinc -randkey kafka/kafka_krb_admin@LWSITE.NET
> ktadd -k /tmp/kafka_kafka_admin.keytab kafka/kafka_krb_admin@LWSITE.NET
> 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/kafka_krb_user@LWSITE.NET"
  keyTab="/tmp/test_kafka_krb_user.keytab";
};

生成对应的 keytab,并保证运行命令的用户有读权限(生产环境推荐 keytab 文件权限 400) :

kinit ${krb_admin_principal}
kadmin # 此处键入超级管理员密码
> addprinc -randkey test/kafka_krb_user@LWSITE.NET
> ktadd -k /tmp/test_kafka_krb_user.keytab test/kafka_krb_user@LWSITE.NET
> 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/

推荐阅读更多精彩内容