Kafka 授权与 ACL 深入实践

一、授权框架概览:开启可插拔 Authorizer

Kafka 内置可插拔的授权框架,通过 authorizer.class.name 指定 Authorizer 实现。被配置实现需继承 org.apache.kafka.server.authorizer.Authorizer
KRaft 模式下,Kafka 提供默认实现,将 ACL 存储在 集群元数据(KRaft 元数据日志) 中。请在 所有节点(broker、controller 或二者合一)设置:

properties 复制代码
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer

🔎 延伸阅读:ACL 结构详见 KIP-11 ,资源模式详见 KIP-290 。日常增删查 ACL 使用 kafka-acls.sh

二、资源无 ACL 的默认行为与"允许所有人"的开关

1)默认:不匹配 ACL = 拒绝访问

当资源(R)未定义任何 ACL(即没有 ACL 命中该资源)时,Kafka 默认限制 访问,只有 super users 可访问。

2)切换为"无 ACL 即允许所有人"

如需改成 没有 ACL 时对所有用户可访问 ,在 server.properties 中加入:

properties 复制代码
allow.everyone.if.no.acl.found=true

说明:一旦资源存在一条或多条 ACL,则仍以 ACL 的匹配规则为准,与上述开关无关。

3)配置超级用户

分隔符为分号(SSL 用户名可能包含逗号);默认 PrincipalType 字符串 "User" 区分大小写

properties 复制代码
super.users=User:Bob;User:Alice

三、KRaft 中的 Principal 转发(Envelope)

KRaft 集群 里,客户端的管理类请求(如 CreateTopics/DeleteTopics)先发往 broker 的监听器,broker 再通过 controller.listener.names第一个监听器 将请求转发给 active controller
授权 在 controller 上完成,机制为 Envelope :将底层请求客户端 principal一并封装转发。

  • controller 首先用 已认证的 broker principal 授权 Envelope 请求;
  • 然后用 被转发的客户端 principal 授权底层请求。

因此,Kafka 必须会序列化/反序列化客户端 principal。若自定义 principal,需要:

  • 通过 principal.builder.class 覆盖构建器;
  • 该类实现 org.apache.kafka.common.security.auth.KafkaPrincipalSerde(用于序列化/反序列化 principal)。

默认构建器:org.apache.kafka.common.security.authenticator.DefaultKafkaPrincipalBuilder

使用 RPC 定义:clients/src/main/resources/common/message/DefaultPrincipalData.json

四、映射用户名:SSL 与 SASL(Kerberos)

1)SSL 用户名映射:ssl.principal.mapping.rules

默认 SSL 用户名形如:
"CN=writeuser,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown"

可用 ssl.principal.mapping.rulesX.500 DN 映射为短名。按序匹配 ,首次命中即用,后续忽略;支持 /L(小写)、/U(大写):

text 复制代码
RULE:pattern/replacement/
RULE:pattern/replacement/[LU]

示例(含大小写规范及通配):

properties 复制代码
ssl.principal.mapping.rules=\
  RULE:^CN=(.*?),OU=ServiceUsers.*$/$1/,\
  RULE:^CN=(.*?),OU=(.*?),O=(.*?),L=(.*?),ST=(.*?),C=(.*?)$/$1@$2/L,\
  RULE:^.*[Cc][Nn]=([a-zA-Z0-9.]*).*$/$1/L,\
  DEFAULT
  • "CN=serviceuser,OU=ServiceUsers,..." → "serviceuser"
  • "CN=adminUser,OU=Admin,..." → "adminuser@admin"

自定义 PrincipalBuilder:

properties 复制代码
principal.builder.class=CustomizedPrincipalBuilderClass

2)SASL(Kerberos)用户名映射:sasl.kerberos.principal.to.local.rules

默认 SASL 用户名为 Kerberos principal 的 primary 部分。可在 server.properties 中用与 krb5.confauth_to_local 同构的规则改写(同样支持 /L/U):

text 复制代码
RULE:[n:string](regexp)s/pattern/replacement/
RULE:[n:string](regexp)s/pattern/replacement/g
RULE:[n:string](regexp)s/pattern/replacement//L
RULE:[n:string](regexp)s/pattern/replacement/g/L
RULE:[n:string](regexp)s/pattern/replacement//U
RULE:[n:string](regexp)s/pattern/replacement/g/U

示例 :将 user@MYDOMAIN.COMuser,同时保留默认规则:

properties 复制代码
sasl.kerberos.principal.to.local.rules=\
  RULE:[1:$1@$0](.*@MYDOMAIN.COM)s/@.*//,DEFAULT

五、kafka-acls.sh:CLI 全参与高频用法

CLI 位于 bin/ 目录,脚本名 kafka-acls.sh参数全集(与官方一致):

  • 动作类--add--remove--list

  • 连接配置
    --bootstrap-server(连 broker)、--bootstrap-controller(连 controller)二选一
    --command-config(Admin Client 用属性文件,仅配合 --bootstrap-server

  • 资源模式
    --cluster--topic [topic-name]--group [group-name]
    --transactional-id [transactional-id]*=全部)、
    --delegation-token [delegation-token]*=全部)、
    --user-principal [user-principal](现用于 delegation tokens;*=全部)、
    --resource-pattern-type [pattern-type]:添加时 literal|prefixed;列出/移除时可 any|match

    ⚠️ --remove + match 慎用(会批量移除所有匹配模式的 ACL)

  • 主体与来源
    --allow-principal--deny-principal--principal(列出时过滤)
    --allow-host--deny-host(仅 IP ,不支持主机名;未显式指定时默认 *

  • 操作名
    Read|Write|Create|Delete|Alter|Describe|ClusterAction|DescribeConfigs|AlterConfigs|IdempotentWrite|CreateTokens|DescribeTokens|All

  • 便捷选项
    --producer(生成 WRITE/DESCRIBE/CREATE@topic)
    --consumer(生成 READ/DESCRIBE@topic + READ@group)
    --idempotent(与 --producer 同用;或由 transactional-id 授权自动启用)
    --force(无交互确认)

典型操作示例

1)添加 :允许 User:BobUser:Alice 从指定 IP 对 Test-topic 执行 Read/Write

bash 复制代码
bin/kafka-acls.sh --bootstrap-server localhost:9092 --add \
  --allow-principal User:Bob \
  --allow-principal User:Alice \
  --allow-host 198.51.100.0 \
  --allow-host 198.51.100.1 \
  --operation Read --operation Write \
  --topic Test-topic

2)"允许所有 + 拒绝个别" :允许所有用户从任意主机读 Test-topic,但拒绝 User:BadBob198.51.100.3 读取:

bash 复制代码
bin/kafka-acls.sh --bootstrap-server localhost:9092 --add \
  --allow-principal User:'*' --allow-host '*' \
  --deny-principal User:BadBob --deny-host 198.51.100.3 \
  --operation Read --topic Test-topic

3)对所有 Topic(通配 *)授 Producer 权限

bash 复制代码
bin/kafka-acls.sh --bootstrap-server localhost:9092 --add \
  --allow-principal User:Peter \
  --allow-host 198.51.200.1 \
  --producer --topic '*'

4)前缀模式 :允许 User:Jane 向以 Test- 开头的主题生产:

bash 复制代码
bin/kafka-acls.sh --bootstrap-server localhost:9092 --add \
  --allow-principal User:Jane \
  --producer --topic Test- \
  --resource-pattern-type prefixed

5)移除 ACL (与添加相同参数,改 --remove 即可):

bash 复制代码
bin/kafka-acls.sh --bootstrap-server localhost:9092 --remove \
  --allow-principal User:Bob --allow-principal User:Alice \
  --allow-host 198.51.100.0 --allow-host 198.51.100.1 \
  --operation Read --operation Write \
  --topic Test-topic

6)列出 ACL

  • 精确资源(literal):

    bash 复制代码
    bin/kafka-acls.sh --bootstrap-server localhost:9092 --list --topic Test-topic
  • 通配 *

    bash 复制代码
    bin/kafka-acls.sh --bootstrap-server localhost:9092 --list --topic '*'
  • 列出影响 Test-topic 的全部(含 literal、wildcard、prefixed):

    bash 复制代码
    bin/kafka-acls.sh --bootstrap-server localhost:9092 --list \
      --topic Test-topic --resource-pattern-type match

7)按"角色"快速授权

  • User:BobTest-topic 生产者

    bash 复制代码
    bin/kafka-acls.sh --bootstrap-server localhost:9092 --add \
      --allow-principal User:Bob --producer --topic Test-topic
  • User:BobTest-topic 消费者 ,消费组 Group-1必须 指定 --group):

    bash 复制代码
    bin/kafka-acls.sh --bootstrap-server localhost:9092 --add \
      --allow-principal User:Bob --consumer --topic Test-topic --group Group-1

六、授权原语:操作(Operations)与资源(Resources)

1)操作集合

Read | Write | Create | Delete | Alter | Describe | ClusterAction | DescribeConfigs | AlterConfigs | IdempotentWrite | CreateTokens | DescribeTokens | All

2)资源集合与错误码

  • Topic :主题。失败 → TOPIC_AUTHORIZATION_FAILED (29)
  • Group :消费组。失败 → GROUP_AUTHORIZATION_FAILED (30)
  • Cluster :集群。失败 → CLUSTER_AUTHORIZATION_FAILED (31)
  • TransactionalId :事务标识。失败 → TRANSACTIONAL_ID_AUTHORIZATION_FAILED (53)
  • DelegationToken:委派令牌(详见 KIP-48)
  • User :用户(CreateToken/DescribeToken 可授予到 User,详见 KIP-373)

七、权责矩阵:Kafka 协议 × 操作 × 资源(完整版)

下表直接复刻官方映射(按原文顺序),用于设计"最小权限 "与审计

注:若同一 API 同时列出多条,表示该请求可能触达多种授权路径或需要叠加校验。

Protocol (API key) Operation Resource Note
PRODUCE (0) Write TransactionalId 事务生产者设置了 transactional.id 时需要。
PRODUCE (0) IdempotentWrite Cluster 幂等写。
PRODUCE (0) Write Topic 普通生产。
FETCH (1) ClusterAction Cluster follower 拉取分区数据。
FETCH (1) Read Topic 普通消费者读取分区。
LIST_OFFSETS (2) Describe Topic ---
METADATA (3) Describe Topic ---
METADATA (3) Create Cluster 自动建主题先查集群级;无则查 Topic 级。
METADATA (3) Create Topic 自动建主题(当集群级无权限)。
LEADER_AND_ISR (4) ClusterAction Cluster ---
STOP_REPLICA (5) ClusterAction Cluster ---
UPDATE_METADATA (6) ClusterAction Cluster ---
CONTROLLED_SHUTDOWN (7) ClusterAction Cluster ---
OFFSET_COMMIT (8) Read Group 先组后题。
OFFSET_COMMIT (8) Read Topic ---
OFFSET_FETCH (9) Describe Group 先组后题。
OFFSET_FETCH (9) Describe Topic ---
FIND_COORDINATOR (10) Describe Group 请求类型为 Group 时。
FIND_COORDINATOR (10) Describe TransactionalId 事务生产者找事务协调者。
JOIN_GROUP (11) Read Group ---
HEARTBEAT (12) Read Group ---
LEAVE_GROUP (13) Read Group ---
SYNC_GROUP (14) Read Group ---
DESCRIBE_GROUPS (15) Describe Group ---
LIST_GROUPS (16) Describe Cluster 无权限不报错,回退逐组检查。
LIST_GROUPS (16) Describe Group 全未授权时返回空(自 2.1 起)。
SASL_HANDSHAKE (17) --- --- 认证流程,无法授权。
API_VERSIONS (18) --- --- 握手流程,无法授权。
CREATE_TOPICS (19) Create Cluster 无集群级时回退 Topic 级并据此报错。
CREATE_TOPICS (19) Create Topic 自 2.0 起。
DELETE_TOPICS (20) Delete Topic ---
DELETE_RECORDS (21) Delete Topic ---
INIT_PRODUCER_ID (22) Write TransactionalId ---
INIT_PRODUCER_ID (22) IdempotentWrite Cluster ---
OFFSET_FOR_LEADER_EPOCH (23) ClusterAction Cluster 无集群级则查 Topic 级。
OFFSET_FOR_LEADER_EPOCH (23) Describe Topic 自 2.1 起。
ADD_PARTITIONS_TO_TXN (24) Write TransactionalId 仅事务请求;先 TxnId 后 Topic。
ADD_PARTITIONS_TO_TXN (24) Write Topic ---
ADD_OFFSETS_TO_TXN (25) Write TransactionalId 仅事务请求;先 TxnId 后 Group。
ADD_OFFSETS_TO_TXN (25) Read Group ---
END_TXN (26) Write TransactionalId ---
WRITE_TXN_MARKERS (27) Alter Cluster ---
WRITE_TXN_MARKERS (27) ClusterAction Cluster ---
TXN_OFFSET_COMMIT (28) Write TransactionalId ---
TXN_OFFSET_COMMIT (28) Read Group ---
TXN_OFFSET_COMMIT (28) Read Topic ---
DESCRIBE_ACLS (29) Describe Cluster ---
CREATE_ACLS (30) Alter Cluster ---
DELETE_ACLS (31) Alter Cluster ---
DESCRIBE_CONFIGS (32) DescribeConfigs Cluster 查 broker 配置时。
DESCRIBE_CONFIGS (32) DescribeConfigs Topic 查 topic 配置时。
ALTER_CONFIGS (33) AlterConfigs Cluster 改 broker 配置时。
ALTER_CONFIGS (33) AlterConfigs Topic 改 topic 配置时。
ALTER_REPLICA_LOG_DIRS (34) Alter Cluster ---
DESCRIBE_LOG_DIRS (35) Describe Cluster 未授权返回空。
SASL_AUTHENTICATE (36) --- --- 认证流程,无法授权。
CREATE_PARTITIONS (37) Alter Topic ---
CREATE_DELEGATION_TOKEN (38) --- --- 特殊规则,见 Delegation Tokens。
CREATE_DELEGATION_TOKEN (38) CreateTokens User 允许为 User 创建委派令牌。
RENEW_DELEGATION_TOKEN (39) --- --- 特殊规则。
EXPIRE_DELEGATION_TOKEN (40) --- --- 特殊规则。
DESCRIBE_DELEGATION_TOKEN (41) Describe DelegationToken 特殊规则。
DESCRIBE_DELEGATION_TOKEN (41) DescribeTokens User 允许描述 User 的委派令牌。
DELETE_GROUPS (42) Delete Group ---
ELECT_PREFERRED_LEADERS (43) ClusterAction Cluster ---
INCREMENTAL_ALTER_CONFIGS (44) AlterConfigs Cluster 改 broker 配置。
INCREMENTAL_ALTER_CONFIGS (44) AlterConfigs Topic 改 topic 配置。
ALTER_PARTITION_REASSIGNMENTS (45) Alter Cluster ---
LIST_PARTITION_REASSIGNMENTS (46) Describe Cluster ---
OFFSET_DELETE (47) Delete Group ---
OFFSET_DELETE (47) Read Topic ---
DESCRIBE_CLIENT_QUOTAS (48) DescribeConfigs Cluster ---
ALTER_CLIENT_QUOTAS (49) AlterConfigs Cluster ---
DESCRIBE_USER_SCRAM_CREDENTIALS (50) Describe Cluster ---
ALTER_USER_SCRAM_CREDENTIALS (51) Alter Cluster ---
VOTE (52) ClusterAction Cluster ---
BEGIN_QUORUM_EPOCH (53) ClusterAction Cluster ---
END_QUORUM_EPOCH (54) ClusterAction Cluster ---
DESCRIBE_QUORUM (55) Describe Cluster ---
ALTER_PARTITION (56) ClusterAction Cluster ---
UPDATE_FEATURES (57) Alter Cluster ---
ENVELOPE (58) ClusterAction Cluster ---
FETCH_SNAPSHOT (59) ClusterAction Cluster ---
DESCRIBE_CLUSTER (60) Describe Cluster ---
DESCRIBE_PRODUCERS (61) Read Topic ---
BROKER_REGISTRATION (62) ClusterAction Cluster ---
BROKER_HEARTBEAT (63) ClusterAction Cluster ---
UNREGISTER_BROKER (64) Alter Cluster ---
DESCRIBE_TRANSACTIONS (65) Describe TransactionalId ---
LIST_TRANSACTIONS (66) Describe TransactionalId ---
ALLOCATE_PRODUCER_IDS (67) ClusterAction Cluster ---
CONSUMER_GROUP_HEARTBEAT (68) Read Group ---
CONSUMER_GROUP_DESCRIBE (69) Read Group ---
CONTROLLER_REGISTRATION (70) ClusterAction Cluster ---
GET_TELEMETRY_SUBSCRIPTIONS (71) --- --- 无授权检查。
PUSH_TELEMETRY (72) --- --- 无授权检查。
ASSIGN_REPLICAS_TO_DIRS (73) ClusterAction Cluster ---
LIST_CONFIG_RESOURCES (74) DescribeConfigs Cluster ---
DESCRIBE_TOPIC_PARTITIONS (75) Describe Topic ---
SHARE_GROUP_HEARTBEAT (76) Read Group ---
SHARE_GROUP_DESCRIBE (77) Describe Group ---
SHARE_FETCH (78) Read Group ---
SHARE_FETCH (78) Read Topic ---
SHARE_ACKNOWLEDGE (79) Read Group ---
SHARE_ACKNOWLEDGE (79) Read Topic ---
INITIALIZE_SHARE_GROUP_STATE (83) ClusterAction Cluster ---
READ_SHARE_GROUP_STATE (84) ClusterAction Cluster ---
WRITE_SHARE_GROUP_STATE (85) ClusterAction Cluster ---
DELETE_SHARE_GROUP_STATE (86) ClusterAction Cluster ---
READ_SHARE_GROUP_STATE_SUMMARY (87) ClusterAction Cluster ---
STREAMS_GROUP_HEARTBEAT (88) Read Group ---
STREAMS_GROUP_HEARTBEAT (88) Describe Topic 需要对所有源主题内部主题授权。
STREAMS_GROUP_HEARTBEAT (88) Create Topic 允许 broker 自动创建内部主题(若不存在)。
STREAMS_GROUP_DESCRIBE (89) Describe Group ---
STREAMS_GROUP_DESCRIBE (89) Describe Topic 需要对所有源/内部主题授权。
DESCRIBE_SHARE_GROUP_OFFSETS (90) Describe Group 先组后题。
DESCRIBE_SHARE_GROUP_OFFSETS (90) Describe Topic ---
ALTER_SHARE_GROUP_OFFSETS (91) Read Group 先组后题。
ALTER_SHARE_GROUP_OFFSETS (91) Read Topic ---
DELETE_SHARE_GROUP_OFFSETS (92) Delete Group 先组后题。
DELETE_SHARE_GROUP_OFFSETS (92) Read Topic ---

八、工程落地:最小权限、命名规范与排错清单

1)最小权限策略(示例)

  • 生产者(普通)Write@Topic:<t> + (如需)IdempotentWrite@Cluster
  • 消费者(普通)Read@Topic:<t> + Read@Group:<g>
  • 事务生产者Write@TransactionalId:<txid> + Write@Topic:<t>(以及必要时的 IdempotentWrite@Cluster)
  • Streams :为所有源主题与内部主题Describe@Topic;若允许自动创建内部主题 ,再赋 Create@Topic(或事先创建并仅给 Describe)

2)主体与主机规则

  • 优先用 短名(SSL/SASL 映射)避免 DN/Realm/大小写问题。
  • --allow-host / --deny-host 仅支持 IP;如需按网段限制,建议运维层控制或生成工具扩展。

3)资源模式

  • **精确(literal)**用于"按名授权",**通配('*')**慎用。
  • **前缀(prefixed)**适合多租户/批量主题,但需严格命名规范与审计。
  • 清理 ACL 时避免盲用 --remove --resource-pattern-type match

4)"无 ACL"策略开关

  • 默认拒绝 安全性更高;若开启 allow.everyone.if.no.acl.found=true,务必配合 CI/CD 审计防止"漏配即放开"。

5)KRaft Principal 转发

  • 定制 principal 时记得实现 KafkaPrincipalSerde;否则 Envelope 上下游序列化失败。

6)故障排查

  • 错误码定位:TOPIC_AUTHORIZATION_FAILED(29)GROUP_AUTHORIZATION_FAILED(30)CLUSTER_AUTHORIZATION_FAILED(31)TRANSACTIONAL_ID_AUTHORIZATION_FAILED(53)
  • LIST_GROUPS 返回空但不报错,考虑是权限不足导致的空集合(2.1+ 行为)。

九、运维脚本模板(占位符示例)

<BS><TOPIC><GROUP><USER> 替换为实际值。

bash 复制代码
# Producer (literal)
bin/kafka-acls.sh --bootstrap-server <BS> --add \
  --allow-principal User:<USER> --producer --topic <TOPIC>

# Consumer (literal)
bin/kafka-acls.sh --bootstrap-server <BS> --add \
  --allow-principal User:<USER> --consumer --topic <TOPIC> --group <GROUP>

# Idempotent Producer (cluster-level)
bin/kafka-acls.sh --bootstrap-server <BS> --add \
  --allow-principal User:<USER> --operation IdempotentWrite --cluster

# Streams 内部主题自动创建(前缀)
bin/kafka-acls.sh --bootstrap-server <BS> --add \
  --allow-principal User:<USER> --operation Create \
  --topic <INTERNAL_PREFIX> --resource-pattern-type prefixed

十、结语

本文按 KRaft 语义与官方结构,提供了 Kafka 授权体系的 全量知识面 :从 Authorizer 启用、无 ACL 策略、super users,到 Envelope 转发与 principal 序列化契约;从 SSL/SASL 用户名映射的正则规则到 CLI 全参;再到覆盖 Streams/事务/共享组在内的 协议×操作×资源矩阵

相关推荐
席万里4 小时前
使用Go做一个分布式短链系统
开发语言·分布式·golang
Terio_my13 小时前
RabbitMQ 安装与配置
分布式·rabbitmq
程序员小凯15 小时前
RabbitMq入门之概括
分布式·消息队列·rabbitmq
!chen17 小时前
RabbitMQ的安装集群、镜像队列配置
分布式·rabbitmq·ruby
一只学java的小汉堡17 小时前
RabbitMQ 在 Windows 环境下启动失败的完整解决方案
windows·分布式·rabbitmq
李九三19 小时前
分布式限流
分布式
nlog3n21 小时前
分布式排行榜系统设计方案
java·分布式
拾忆,想起1 天前
RabbitMQ事务机制深度剖析:消息零丢失的终极武器
java·开发语言·分布式·后端·rabbitmq·ruby
z晨晨1 天前
互联网大厂Java求职面试实战:Spring Boot与微服务场景深度解析
java·spring boot·redis·微服务·kafka·spring security·电商