安全体系:认证、授权与加密
上一篇分析了性能模型。这一篇进入生产环境的另一个关键维度:安全。
Kafka 早期版本没有内置安全机制——客户端连上 broker 就能读写任意 topic。自 0.9 版本起,Kafka 逐步引入了认证、授权和加密三层安全能力。这三层各自解决一个问题:认证确认身份,授权控制权限,加密保护传输通道。
本文只抓一个问题:Kafka 的安全体系如何分层工作,每一层的配置和机制是什么。
三层安全模型
1 | |
三层可以独立启用。只要加密不要认证(SSL),只要认证不要加密(SASL_PLAINTEXT),或者三层全开(SASL_SSL),都是合法的组合。Kafka 通过 listener 的 security.protocol 配置来指定每个端口使用哪种组合。
认证机制
Kafka 支持四种主要的认证方式,通过 SASL(Simple Authentication and Security Layer)框架统一接入。
SASL/PLAIN:用户名 + 明文密码。配置最简单,适合开发和测试环境。密码以明文传输,生产环境必须搭配 TLS 使用(即 SASL_SSL 协议)。
SASL/SCRAM(Salted Challenge Response Authentication Mechanism):密码不在网络上明文传输,使用挑战-应答机制。支持 SCRAM-SHA-256 和 SCRAM-SHA-512 两种强度。用户凭证存储在 ZooKeeper 或 KRaft 的元数据中,支持动态增删用户,不需要重启 broker。
SASL/GSSAPI(Kerberos):企业级认证协议,依赖外部 KDC(Key Distribution Center)。适合已有 Kerberos 基础设施的组织(如 Hadoop 集群、Active Directory 环境)。配置复杂度最高。
mTLS(双向 TLS):客户端和 broker 互相验证对方的 X.509 证书。不走 SASL 框架,而是通过 TLS 层直接完成认证。客户端的证书 DN(Distinguished Name)作为 principal 用于后续的授权判断。适合服务间通信,不适合面向终端用户的场景。
SASL/SCRAM 配置实战
SASL/SCRAM 是生产环境中最常用的认证方式之一,因为它安全性足够且不依赖外部 KDC。以下是配置步骤。
第一步,创建 SCRAM 用户凭证。在 ZooKeeper 模式下:
1 | |
在 KRaft 模式下,使用 --bootstrap-server 替代 --zookeeper:
1 | |
第二步,配置 broker。在 server.properties 中添加:
1 | |
同时需要在 broker 的 JAAS 配置文件中配置 inter-broker 通信使用的凭证:
1 | |
第三步,配置 producer 客户端。在 producer.properties 中:
1 | |
第四步,配置 consumer 客户端,方式相同,替换用户名和密码即可。
授权:ACL
Kafka 的授权基于 ACL(Access Control List)。每条 ACL 规则描述了一个 principal(用户)对一个 resource(资源)执行某个 operation(操作)的许可或拒绝。
资源类型包括:
| 资源类型 | 示例 | 说明 |
|---|---|---|
| Topic | my-topic | 某个具体 topic |
| Group | my-consumer-group | consumer group ID |
| Cluster | kafka-cluster | 集群级操作 |
| TransactionalId | my-tx-id | 事务 ID |
| DelegationToken | token-id | 委托令牌 |
操作类型包括 Read、Write、Create、Delete、Alter、Describe、ClusterAction、IdempotentWrite 等。
ACL 管理使用 kafka-acls.sh 工具:
1 | |
Kafka 的 ACL 默认行为是"没有显式允许就拒绝"。可以通过 allow.everyone.if.no.acl.found=true 改变这个默认值,但生产环境不推荐。
broker 端需要启用 authorizer:
1 | |
super.users 配置指定超级用户,超级用户绕过所有 ACL 检查:
1 | |
Per-Listener 安全配置
Kafka 支持在不同 listener 上配置不同的安全协议。一个 broker 可以同时暴露多个端口,每个端口使用不同的安全级别:
1 | |
典型的多端口配置场景:
1 | |
inter.broker.listener.name 指定 broker 之间通信使用哪个 listener:
1 | |
加密:TLS 配置
TLS 加密需要配置 keystore(存放 broker 自己的证书和私钥)和 truststore(存放信任的 CA 证书)。
生成证书的典型流程:
1 | |
broker 端 TLS 配置:
1 | |
Delegation Token
KIP-48 引入了 delegation token 机制,用于解决分布式计算框架(Spark、Flink)的认证问题。
这些框架的 driver 进程拥有 Kerberos 凭证,但 executor 进程运行在集群的各个节点上,让每个 executor 都持有 Kerberos keytab 不现实。Delegation token 的工作方式是:driver 用自己的凭证向 broker 申请一个短期 token,然后把这个 token 分发给所有 executor,executor 用 token 进行认证。
1 | |
token 有有效期,过期后需要续约或重新创建。
实验:SASL/SCRAM 认证验证
以下实验在一个启用了 SASL/SCRAM 的单 broker 环境中验证认证和授权。
第一步,启动配置了 SASL_PLAINTEXT 的 broker。
第二步,用已授权的 producer 发送消息:
1 | |
producer-scram.properties 内容:
1 | |
第三步,用未授权的用户尝试发送:
1 | |
预期结果:收到 TopicAuthorizationException,消息发送失败。
第四步,用已授权的 consumer 消费:
1 | |
如果 consumer-user 没有被授权 Read my-group,同样会收到 GroupAuthorizationException。
模式提炼
Kafka 的安全模型是分层安全(defense in depth)的典型实现。这个模式在各种系统中反复出现:
数据库安全:用户名/密码认证 → GRANT/REVOKE 权限控制 → SSL/TLS 传输加密。MySQL 的 mysql.user 表对应 Kafka 的 SCRAM 用户存储,GRANT 语句对应 kafka-acls.sh。
Kubernetes RBAC:ServiceAccount(认证) → Role/ClusterRole + RoleBinding(授权) → TLS(加密)。Kubernetes 的 Role 按 namespace 隔离资源,Kafka 的 ACL 按 topic/group 隔离资源。
AWS IAM:IAM User/Role(认证) → Policy(授权) → HTTPS(加密)。IAM Policy 的 Effect/Action/Resource 结构与 Kafka ACL 的 Allow-Deny/Operation/Resource 结构同构。
共同点是三个层次各自独立可配置,且层与层之间没有依赖——可以只开加密不开认证,也可以只开认证不开授权。
工程迁移表
| 概念 | Kafka | RocketMQ | 数据库 | Kubernetes |
|---|---|---|---|---|
| 认证方式 | SASL/SCRAM, mTLS, Kerberos | AK/SK, mTLS | 用户名/密码, LDAP | ServiceAccount, OIDC |
| 授权模型 | ACL (principal + resource + operation) | ACL (topic + group + IP) | GRANT/REVOKE | RBAC (Role + RoleBinding) |
| 资源粒度 | topic, group, cluster, txn-id | topic, group | database, table, column | namespace, pod, service |
| 加密 | TLS (client-broker, broker-broker) | TLS (client-broker) | TLS (client-server) | mTLS (pod-to-pod via Istio) |
| 短期凭证 | Delegation Token (KIP-48) | STS Token | 临时密码 | Projected Service Account Token |
| 超级用户 | super.users 配置 | 无内置概念 | root / DBA 角色 | cluster-admin ClusterRole |
常见误解
PLAINTEXT 在生产环境没问题:PLAINTEXT 协议意味着所有数据(包括消息内容和认证凭证)以明文在网络上传输。即使在内网环境中,网络嗅探、ARP 欺骗等攻击手段仍然可能暴露敏感数据。生产环境至少应该启用 TLS 加密。
SSL/TLS 会让吞吐量减半:TLS 确实增加了 CPU 开销(加解密运算)和网络延迟(握手),但在现代硬件上,启用 TLS 的吞吐量下降通常在 10-20% 范围内,而不是 50%。使用 TLS 1.3(减少握手往返)和硬件 AES 加速指令(AES-NI)可以进一步降低开销。
ACL 只能按 topic 控制:Kafka ACL 的资源类型包括 Topic、Group、Cluster、TransactionalId 和 DelegationToken 五种。可以精确控制到某个用户对某个 consumer group 的 Read 权限,或某个用户使用某个 transactional.id 发起事务的权限。
练习
-
在一个 KRaft 模式的单 broker 集群上配置 SASL/SCRAM-SHA-256 认证。创建两个用户 producer-user 和 consumer-user,验证未认证的客户端无法连接。
-
为 producer-user 配置 ACL,只允许向 topic orders 写入。尝试让 producer-user 向 topic payments 写入,观察错误信息。
-
在同一个 broker 上配置两个 listener:9092 端口使用 PLAINTEXT(仅限内网运维),9093 端口使用 SASL_SSL(面向应用客户端)。验证两个端口都能正常工作。
-
测量启用 TLS 前后 producer 的吞吐量差异。使用 kafka-producer-perf-test 发送 100 万条消息,对比 PLAINTEXT 和 SSL 协议下的 records/sec。
系列导航
参考资料
- Apache Kafka Documentation — Security: https://kafka.apache.org/documentation/#security
- KIP-48: Delegation token support for Kafka: https://cwiki.apache.org/confluence/display/KAFKA/KIP-48+Delegation+token+support+for+Kafka
- Confluent Security Tutorial: https://docs.confluent.io/platform/current/security/security-tutorial.html
- Apache Kafka Documentation — Authorization and ACLs: https://kafka.apache.org/documentation/#security_authz
