4. 授权模型ACL

在 Kafka 的安全体系中,认证解决的是“你是谁”,而授权解决的是“你能做什么”。Kafka 的授权模型以 ACL(Access Control List,访问控制列表)为核心,通过一条条显式规则,把主体(Principal)、资源(Resource)、操作(Operation)和允许/拒绝(Allow/Deny)绑定在一起。理解 ACL 的语法结构,是后续用 CLI 精确管理权限的基础。

ACL 的语法结构

一条 Kafka ACL 由五个核心要素构成,可以概括为“谁,对什么资源,在什么条件下,能做什么,是允许还是拒绝”。在 CLI 中,这些要素通过参数表达:

  • --allow-principal / --deny-principal:主体,格式为 User:用户名 或 Group:组名,例如 User:alice。
  • --operation:操作权限,如 Read、Write、Create、Delete、Alter、Describe、DescribeConfigs、AlterConfigs、IdempotentWrite、ClusterAction 等。
  • --topic / --group / --cluster / --transactional-id / --delegation-token:资源类型与资源名。
  • --resource-pattern-type:资源匹配模式,取值为 literal(精确匹配)或 prefixed(前缀匹配)。
  • --allow-host / --deny-host:来源主机,默认 * 表示任意主机。

这五个要素共同决定了一条规则是否命中。Kafka 的授权判定遵循“显式拒绝优先、无匹配则拒绝”的原则:只要存在一条匹配的 Deny 规则,请求就被拒绝;如果没有 Allow 规则命中,同样被拒绝。因此 ACL 是白名单式的,默认关闭。

资源类型与操作权限的对应关系

不同资源类型支持的操作并不相同,混淆会导致 ACL 无效。Topic 资源常用 Read、Write、Create、Delete、Describe、DescribeConfigs、AlterConfigs;Group 资源常用 Read、Describe;Cluster 资源常用 Create、ClusterAction、Alter、Describe、DescribeConfigs、IdempotentWrite;TransactionalId 资源常用 Write、Describe。例如生产者向主题写入需要 Topic 的 Write,消费者读取需要 Topic 的 Read 以及对应 Group 的 Read。

Describe 操作常被忽略:消费者订阅主题时,除了 Read,还需要对 Topic 的 Describe 权限,否则元数据请求会被拒绝。

通配符的使用

Kafka ACL 支持两种通配方式。第一种是资源名使用 *,表示匹配所有资源,例如 --topic "*" 表示所有主题。第二种是 --resource-pattern-type prefixed,配合资源名前缀,例如 --topic "app-" --resource-pattern-type prefixed 匹配所有以 app- 开头的主题。需要注意,* 与 prefixed 是两种不同机制:* 是字面量通配,prefixed 是前缀匹配。此外,--allow-host "*" 表示任意来源主机。

通配符虽然方便,但会放大权限范围。生产环境应优先使用精确资源名或受控前缀,避免对 * 授予 Write 或 Delete 这类高危操作。

Kafka ACL 授权判定链 客户端请求 Principal + 资源 + 操作 ACL 匹配 Principal / 资源 / 操作 Host / PatternType 命中 Deny 立即拒绝 命中 Allow 允许通过 无匹配规则 默认拒绝 资源类型与常用操作权限 Topic Read / Write Create / Delete Describe / Alter DescribeConfigs Group Read Describe Cluster Create / Alter Describe / ClusterAction IdempotentWrite TransactionalId Write Describe

通过 CLI 管理 ACL

Kafka 提供 kafka-acls.sh 脚本用于 ACL 的增删查。所有操作都需要指定 --bootstrap-server 和 --command-config(包含管理员认证信息)。下面以几个典型场景说明。

场景一:为生产者授予写入权限。允许用户 alice 向主题 orders 写入:

kafka-acls.sh --bootstrap-server broker1:9092 \
  --command-config admin.properties \
  --add --allow-principal User:alice \
  --operation Write --topic orders

场景二:为消费者授予读取权限。消费者需要同时获得 Topic 的 Read 和 Group 的 Read:

kafka-acls.sh --bootstrap-server broker1:9092 \
  --command-config admin.properties \
  --add --allow-principal User:bob \
  --operation Read --topic orders \
  --operation Read --group order-consumer-group

场景三:使用前缀通配符。允许用户 carol 读取所有以 log- 开头的主题:

kafka-acls.sh --bootstrap-server broker1:9092 \
  --command-config admin.properties \
  --add --allow-principal User:carol \
  --operation Read --topic "log-" \
  --resource-pattern-type prefixed

场景四:查看与删除。列出某主题上的所有 ACL,然后删除其中一条:

kafka-acls.sh --bootstrap-server broker1:9092 \
  --command-config admin.properties \
  --list --topic orders

kafka-acls.sh --bootstrap-server broker1:9092 \
  --command-config admin.properties \
  --remove --allow-principal User:alice \
  --operation Write --topic orders
删除 ACL 时必须与添加时的参数完全一致,包括 principal、operation、resource、pattern-type 和 host,否则会提示找不到匹配的 ACL。

实践中的判断依据

配置完成后,如何确认 ACL 生效?最直接的方式是用被授权主体发起一次真实操作,例如生产者发送一条消息、消费者拉取一条消息,观察是否抛出 TopicAuthorizationException 或 GroupAuthorizationException。如果被拒绝,先用 --list 检查 ACL 是否存在、资源名和 pattern-type 是否匹配、operation 是否覆盖了实际请求。常见错误包括:只给了 Topic Read 却忘了 Group Read;使用 prefixed 时资源名写成了完整主题名;以及 host 限制过严导致来源 IP 不匹配。

ACL 的管理本质上是“最小权限”与“可维护性”之间的平衡。通配符能减少规则数量,但会扩大攻击面;精确规则更安全,但数量增长后需要借助命名规范和定期审计来维护。建议为每类应用定义清晰的主体命名和资源前缀,把 ACL 变更纳入版本化配置,避免手工操作带来的遗漏。