Kafka在KRaft模式下实现ACL授权策略
docker-compose.yml
version: "3.3"
services:
kafka:
image: 'bitnami/kafka:3.7.0-debian-12-r3'
ports:
- '9092:9092'
environment:
- KAFKA_CFG_NODE_ID=0
- KAFKA_CFG_PROCESS_ROLES=controller,broker
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093
- KAFKA_CFG_LISTENERS=SASL_PLAINTEXT://:9092,CONTROLLER://:9093
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT
- KAFKA_CFG_ADVERTISED_LISTENERS=SASL_PLAINTEXT://xxx:xxx:xxx:xxx:9092
- KAFKA_CLIENT_USERS=kafkaMaster;kafka1
- KAFKA_CLIENT_PASSWORDS=kafkaMaster@123;123456
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_SASL_MECHANISM_CONTROLLER_PROTOCOL=PLAIN
- KAFKA_CONTROLLER_USER=kafkaMaster
- KAFKA_CONTROLLER_PASSWORD=kafkaMaster@123
- KAFKA_CFG_INTER_BROKER_LISTENER_NAME=SASL_PLAINTEXT
- KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL=PLAIN
- KAFKA_INTER_BROKER_USER=kafkaMaster
- KAFKA_INTER_BROKER_PASSWORD=kafkaMaster@123
- KAFKA_CFG_ALLOW_EVERYONE_IF_NO_ACL_FOUND=false
- KAFKA_CFG_SUPER_USERS=User:kafkaMaster;User:ANONYMOUS
- KAFKA_CFG_AUTHORIZER_CLASS_NAME=org.apache.kafka.metadata.authorizer.StandardAuthorizer
volumes:
- ./client.properties:/tmp/client.properties # 认证配置
- ./client.properties:/opt/bitnami/kafka/config/sasl_config.properties # 认证配置
- ./kafka:/bitnami/kafka
# - ./config:/opt/bitnami/kafka/config
# 注释版本
version: "3.3" # 指定 docker-compose 文件的版本
services:
kafka:
image: 'bitnami/kafka:3.7.0-debian-12-r3' # 使用的 Kafka 镜像
ports:
- '9092:9092' # 端口映射,将宿主机的 9092 端口映射到容器的 9092 端口
environment:
- KAFKA_CFG_NODE_ID=0 # Kafka 节点 ID,在 KRaft 模式下,每个节点都需要一个唯一的 ID
- KAFKA_CFG_PROCESS_ROLES=controller,broker # 节点角色,这里配置为同时担任 controller 和 broker
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093 # 控制器法定投票节点,格式为 id@host:port,这里配置了自身作为唯一的 controller
- KAFKA_CFG_LISTENERS=SASL_PLAINTEXT://:9092,CONTROLLER://:9093 # Kafka 监听器,配置了两个监听器:SASL_PLAINTEXT 用于客户端连接,CONTROLLER 用于控制器之间的通信
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT # 监听器安全协议映射,将 CONTROLLER 监听器映射到 PLAINTEXT 协议,SASL_PLAINTEXT 监听器映射到 SASL_PLAINTEXT 协议
- KAFKA_CFG_ADVERTISED_LISTENERS=SASL_PLAINTEXT://xxx:xxx:xxx:xxx:9092 # Kafka 广播监听器,客户端将通过这个地址和端口连接到 Kafka。需要配置为客户端可以访问的地址和端口。
- KAFKA_CLIENT_USERS=kafkaMaster;kafka1 # 允许连接到 Kafka 的客户端用户列表,用分号分隔
- KAFKA_CLIENT_PASSWORDS=kafkaMaster@123;123456 # 客户端用户对应的密码,用分号分隔,顺序与 KAFKA_CLIENT_USERS 对应
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER # 控制器监听器的名称
- KAFKA_CFG_SASL_MECHANISM_CONTROLLER_PROTOCOL=PLAIN # 控制器监听器的 SASL 机制,这里设置为 PLAIN
- KAFKA_CONTROLLER_USER=kafkaMaster # 用于控制器间认证的用户名
- KAFKA_CONTROLLER_PASSWORD=kafkaMaster@123 # 用于控制器间认证的密码
- KAFKA_CFG_INTER_BROKER_LISTENER_NAME=SASL_PLAINTEXT # broker 间通信的监听器名称
- KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL=PLAIN # broker 间通信的 SASL 机制,这里设置为 PLAIN
- KAFKA_INTER_BROKER_USER=kafkaMaster # 用于 broker 间认证的用户名
- KAFKA_INTER_BROKER_PASSWORD=kafkaMaster@123 # 用于 broker 间认证的密码
- KAFKA_CFG_ALLOW_EVERYONE_IF_NO_ACL_FOUND=false # 如果没有找到 ACL,是否允许所有人访问,这里设置为 false,表示禁止访问
- KAFKA_CFG_SUPER_USERS=User:kafkaMaster;User:ANONYMOUS # 超级用户列表,用分号分隔,这里的 ANONYMOUS 用户比较特殊,一般不建议添加
- KAFKA_CFG_AUTHORIZER_CLASS_NAME=org.apache.kafka.metadata.authorizer.StandardAuthorizer # 授权器类名,这里使用了 Kafka 3.5 引入的新的标准授权器
volumes:
- ./client.properties:/tmp/client.properties # 将宿主机当前目录下的 client.properties 文件挂载到容器的 /tmp/client.properties,用于 kafka-acls.sh 等客户端工具的认证配置
- ./client.properties:/opt/bitnami/kafka/config/sasl_config.properties # 将宿主机当前目录下的 client.properties 文件挂载到容器的 /opt/bitnami/kafka/config/sasl_config.properties,用于配置 SASL 认证
- ./data:/bitnami/kafka/data # 将宿主机当前目录下的 data 目录挂载到容器的 /bitnami/kafka/data,用于持久化 Kafka 的数据
# - ./config:/opt/bitnami/kafka/config # 注释掉了将宿主机的 config 目录挂载到容器的配置目录
client.properties
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username="kafkaMaster" password="kafkaMaster@123";
常用命令
查询/生产/消费topic
# 查询topic
kafka-topics.sh --list --bootstrap-server localhost:9092 --command-config /tmp/client.properties
# 创建topic
kafka-topics.sh --create --topic test_kafka --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 --command-config /tmp/client.properties
# 生产
kafka-console-producer.sh --bootstrap-server localhost:9092 --topic test_topic --producer.config /opt/bitnami/kafka/config/producer.properties
# 消费
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test_kafka --consumer.config /opt/bitnami/kafka/config/consumer.properties
# 消费数据
kafka-console-consumer.sh \
--bootstrap-server localhost:9092 \
--topic test_kafka \
--from-beginning \
--formatter kafka.tools.DefaultMessageFormatter \
--consumer.config /tmp/client.properties \
--property print.key=true \
--property key.separator=":"
--property print.timestamp=true
#生产数据,例如1:1
kafka-console-producer.sh \
--bootstrap-server localhost:9092 \
--topic test_kafka \
--property parse.key=true \
--property key.separator=":" \
--producer.config /opt/bitnami/kafka/config/producer.properties
--property key.serializer=org.apache.kafka.common.serialization.StringSerializer \
--property value.serializer=org.apache.kafka.common.serialization.StringSerializer
查看 ACL 列表
# 查看所有 ACL
kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --list
# 查看特定主题的 ACL
kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --list --topic test_kafka
# 查看特定用户的所有 ACL
kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --list --principal User:kafka1
# 查看特定消费者组的 ACL
kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --list --group my-group
授权 (添加 ACL):
-
授予用户
kafka1对主题test_kafka的所有权限:kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --add --allow-principal User:kafka1 --operation all --topic test_kafka -
授予用户
kafka1对主题test_kafka的读取权限:kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --add --allow-principal User:kafka1 --operation Read --topic tests_kafka -
授予用户
kafka1对主题test_kafka的写入权限:kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --add --allow-principal User:kafka1 --operation Write --topic test_kafka -
授予用户
kafka1对主题test_kafka的生产 (Produce) 权限 (等同于 Create, Describe, Write):kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --add --allow-principal User:kafka1 --producer --topic test_kafka -
授予用户
kafka1对消费者组my-group的消费 (Consume) 权限 (等同于 Read, Describe):kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --add --allow-principal User:kafka1 --consumer --group my-group --topic test_kafka -
授予用户
kafka1对集群的创建主题权限:kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --add --allow-principal User:kafka1 --operation Create --cluster
3. 取消授权 (删除 ACL):
-
取消用户
kafka1对主题test_kafka的所有权限:kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --remove --allow-principal User:kafka1 --operation all --topic test_kafka -
取消用户
kafka1对主题test_kafka的读取权限:kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --remove --allow-principal User:kafka1 --operation Read --topic test_kafka -
取消用户
kafka1对主题test_kafka的写入权限:kafka-acls.sh --bootstrap-server 127.0.0.1:9092 --command-config /tmp/client.properties --remove --allow-principal User:kafka1 --operation Write --topic test_kafka
其他常用选项:
-deny-principal User:<用户名>: 拒绝某个用户的权限 (不常用,建议使用-remove取消授权)。-allow-host <主机名>: 允许来自特定主机的访问 (通常不需要指定,默认允许所有主机 ``)。-resource-pattern-type <模式类型>: 指定资源名称的模式类型,可以是LITERAL(精确匹配) 或PREFIXED(前缀匹配)。例如,-resource-pattern-type PREFIXED --topic "test_"可以匹配所有以test_开头的主题。
附录
ACL 可以应用于以下几种资源类型:
Topic: 主题Group: 消费者组Cluster: Kafka 集群TransactionalId: 事务 IDDelegationToken: 委托令牌 (用于安全委派)
权限 (Operations):
针对不同的资源类型,可以授予或拒绝以下权限:
| 权限 (Operation) | 描述 | 适用资源类型 |
|---|---|---|
All | 所有权限 | 所有资源类型 |
Read | 读取权限 | Topic, Group, TransactionalId, DelegationToken |
Write | 写入权限 | Topic, TransactionalId |
Create | 创建权限 | Topic, Group, Cluster (创建主题), TransactionalId (生成新的事务 ID) |
Delete | 删除权限 | Topic, Group |
Alter | 修改权限 | Topic, Group |
Describe | 查看描述信息的权限 | Topic, Group, Cluster, TransactionalId, DelegationToken |
ClusterAction | 集群操作权限,例如创建或删除代理,修改集群配置等 | Cluster |
DescribeConfigs | 查看配置信息的权限 | Topic, Group, Cluster |
AlterConfigs | 修改配置信息的权限 | Topic, Group, Cluster |
IdempotentWrite | 幂等写入权限 | Cluster |
权限说明:
-
Read:Topic: 允许从主题消费消息。Group: 允许读取消费者组的元数据 (例如偏移量)。TransactionalId: 允许使用指定的事务 ID。DelegationToken: 允许描述 (查看) 委托令牌。
-
Write:Topic: 允许向主题生产消息。TransactionalId: 允许使用指定的事务 ID 写入数据。
-
Create:Topic: 允许创建主题。Group: 允许创建消费者组。Cluster: 允许创建主题 (需要ClusterAction权限才能创建或删除代理)。TransactionalId: 允许生成新的事务 ID。
-
Delete:Topic: 允许删除主题。Group: 允许删除消费者组。
-
Alter:Topic: 允许修改主题的配置 (例如分区数、副本数)。Group: 允许修改消费者组的元数据 (例如重置偏移量)。
-
Describe:Topic: 允许查看主题的描述信息 (例如分区、副本)。Group: 允许查看消费者组的描述信息 (例如成员、偏移量)。Cluster: 允许查看集群的描述信息 (例如代理列表)。TransactionalId: 允许查看事务 ID 的描述信息。DelegationToken: 允许查看委托令牌的描述信息。
-
ClusterAction: 允许执行集群级别的操作,例如添加、删除或重新配置代理。 -
DescribeConfigs: 允许查看指定资源的配置信息。 -
AlterConfigs: 允许修改指定资源的配置信息。 -
IdempotentWrite: 允许进行幂等写入操作,这对于启用 Kafka 的 Exactly-Once 语义 (EOS) 是必需的。
常用权限组合:
- 生产者 (Producer): 通常需要
Create,Describe,Write权限。可以使用-producer简写。 - 消费者 (Consumer): 通常需要
Read,Describe权限。可以使用-consumer简写。
-operation 选项后面跟的就是具体的权限 (Operations) 名称,例如 Write, Read, Create, Delete, Alter 等。
kafka-acls.sh 命令使用 --operation 选项来指定你要添加或删除的 ACL 规则中的操作权限。
例如:
-operation Write表示写入权限,允许用户向主题生产消息。-operation Read表示读取权限,允许用户从主题消费消息或读取消费者组的元数据。-operation Create表示创建权限,允许用户创建主题、消费者组或事务 ID。-operation Delete表示删除权限,允许用户删除主题或消费者组。-operation All表示所有权限,这是最高级别的权限,拥有该权限的用户可以执行任何操作。
借鉴:
KafkaTool连接
org.apache.kafka.common.security.plain.PlainLoginModule required username="kafkaMaster" password="kafkaMaster@123";