KafkaNotes

第 21 章:安全实战:认证、加密与授权

zjc 于 2026-01-21 发布

这是《Kafka 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 默认的 PLAINTEXT 监听等于“裸奔”:任何能连通端口的人都能读写所有 topic。本章讲清楚三层安全模型,并给出可落地的配置。

21.1 安全的三个层次

加密(Encryption)   数据在网络上不可被窃听      SSL/TLS
认证(Authentication) 你是谁                     SASL / mTLS
授权(Authorization)  你能做什么                 ACL

三者独立且都要做:只加密不认证,等于只防窃听不防冒充;只认证不加密,凭据和数据仍可能被嗅探。

21.2 监听器与协议

Broker 通过监听器组合不同协议:

listeners=SSL://:9093,SASL_SSL://:9094
advertised.listeners=SSL://broker1:9093,SASL_SSL://broker1:9094
listener.security.protocol.map=SSL:SSL,SASL_SSL:SASL_SSL
协议 含义
PLAINTEXT 无加密无认证(仅内网可信环境)
SSL TLS 加密,可选 mTLS 双向认证
SASL_PLAINTEXT 认证但不加密
SASL_SSL 认证 + 加密(推荐)

实践建议:内部服务用 SASL_SSLSSL;管理端口可用单独监听器加 ACL 收敛权限。

21.3 SASL/SCRAM:最常用的认证

SCRAM 的用户与凭据存在 ZooKeeper/KRaft 元数据中(而非静态 JAAS 文件),支持动态增删,运维友好。以 SCRAM-SHA-256 为例。

1. 创建用户(在任意 Broker 机器执行)

bin/kafka-configs.sh --bootstrap-server localhost:9092 \
  --alter --add-config 'SCRAM-SHA-256=[iterations=8192,password=app-secret]' \
  --entity-type users --entity-name app-producer

查看:

bin/kafka-configs.sh --bootstrap-server localhost:9092 \
  --describe --entity-type users --entity-name app-producer

2. Broker 端配置

listeners=SASL_SSL://:9094
advertised.listeners=SASL_SSL://broker1:9094
listener.security.protocol.map=SASL_SSL:SASL_SSL
sasl.enabled.mechanisms=SCRAM-SHA-256
sasl.mechanism.inter.broker.protocol=SCRAM-SHA-256

# Broker 之间互联也需要账号(这里用 admin)
listener.name.sasl_ssl.scram-sha-256.sasl.jaas.config=\
org.apache.kafka.common.security.scram.ScramLoginModule required \
  username="admin" \
  password="admin-secret";

3. 客户端配置

security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-256
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
  username="app-producer" \
  password="app-secret";

SCRAM-SHA-512 更强,PLAIN 只建议配合 SSL 在测试环境使用。

21.4 SSL/TLS:加密与双向认证

证书准备(生产用公司 CA,测试可用自签)

# 1. 生成 CA
openssl req -new -x509 -keyout ca-key -out ca-cert -days 3650 \
  -subj "/CN=TestCA"

# 2. 每台 Broker 生成密钥与 CSR,并用 CA 签发
keytool -keystore broker1.keystore.p12 -storetype PKCS12 \
  -alias broker1 -genkey -keyalg RSA -validity 3650 \
  -dname "CN=broker1.example.com"
keytool -keystore broker1.keystore.p12 -alias broker1 \
  -certreq -file broker1.csr
openssl x509 -req -CA ca-cert -CAkey ca-key \
  -in broker1.csr -out broker1-signed.pem -days 3650 -CAcreateserial

# 3. 导入 CA 与签发证书到 keystore,导入 CA 到 truststore
keytool -keystore broker1.keystore.p12 -alias CARoot \
  -import -file ca-cert
keytool -keystore broker1.keystore.p12 -alias broker1 \
  -import -file broker1-signed.pem
keytool -keystore truststore.p12 -alias CARoot \
  -importcert -file ca-cert -noprompt

Broker 配置

listeners=SSL://:9093
ssl.keystore.location=/etc/kafka/ssl/broker1.keystore.p12
ssl.keystore.password=changeit
ssl.key.password=changeit
ssl.truststore.location=/etc/kafka/ssl/truststore.p12
ssl.truststore.password=changeit
ssl.client.auth=required        # mTLS 双向认证;none 表示仅加密

客户端配置

security.protocol=SSL
ssl.truststore.location=/path/truststore.p12
ssl.truststore.password=changeit
# mTLS 时客户端也需要证书
ssl.keystore.location=/path/client.keystore.p12
ssl.keystore.password=changeit

TLS 会增加 CPU 与延迟,大流量集群建议评估硬件加速,并保持长连接复用。

21.5 ACL 授权

认证解决“你是谁”,ACL 决定“你能干什么”。前提:

authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer   # KRaft
# ZK 模式: kafka.security.authorizer.AclAuthorizer
allow.everyone.if.no.acl.found=false    # 默认拒绝
super.users=User:admin;User:broker1     # 管理与 Broker 互联账号

常用 ACL 操作

BOOTSTRAP=localhost:9094
CMD=(bin/kafka-acls.sh --bootstrap-server $BOOTSTRAP \
     --command-config admin.properties)   # admin.properties 含管理员认证

# 生产者:写 order-events
"${CMD[@]}" --add --allow-principal User:app-producer \
  --producer --topic order-events

# 消费者:读 order-events + 读消费组
"${CMD[@]}" --add --allow-principal User:order-consumer \
  --consumer --topic order-events --group order-service

# 只读某前缀的所有 topic
"${CMD[@]}" --add --allow-principal User:report \
  --operation READ --resource-pattern-type prefixed --topic report-

# 列出 ACL
"${CMD[@]}" --list

# 删除
"${CMD[@]}" --remove --allow-principal User:app-producer \
  --producer --topic order-events

最小权限示例矩阵:

主体 topic 权限 组权限 集群权限
producer-app WRITE 特定 topic
consumer-app READ 特定 topic READ 特定组
connect-worker 读写内部 topic 组权限 Describe
admin 全部 全部 全部

21.6 Spring Boot 客户端配置

spring:
  kafka:
    bootstrap-servers: broker1:9094
    security:
      protocol: SASL_SSL
    properties:
      sasl.mechanism: SCRAM-SHA-256
      sasl.jaas.config: >
        org.apache.kafka.common.security.scram.ScramLoginModule required
        username="app-producer"
        password="app-secret";
      ssl.truststore.location: /etc/app/truststore.p12
      ssl.truststore.password: changeit

凭据不要进 Git:用环境变量、Vault、K8s Secret 注入。

21.7 安全最佳实践清单

网络:
  [ ] Kafka 只在内网/私网监听,必要时才经网关暴露
  [ ] Broker 间与 Controller 通道启用 TLS/SASL

认证:
  [ ] 禁用 PLAINTEXT 或仅限运维白名单
  [ ] 不同应用使用不同主体(不要一个账号走天下)
  [ ] 凭据集中管理,定期轮换

授权:
  [ ] allow.everyone.if.no.acl.found=false
  [ ] 最小权限:读写分离、按 topic/组授权
  [ ] ACL 变更走审批与审计

审计与加密:
  [ ] 开启审计日志(谁读写了什么)
  [ ] 敏感数据在业务层额外加密(Kafka 不理解内容)

本章小结

思考题

  1. 只启用 ACL 不启用认证,安全模型还成立吗?为什么?
  2. Broker 之间也需要账号吗?如果配置错误会出现什么现象?
  3. 设计多租户 Kafka 的权限模型:租户 A 的服务如何绝对无法读租户 B 的 topic?