基于KRaft的Kafka配置SASL/SCRAM实现用户主题权限控制报错求助
解决方案:KRaft Kafka 配置 SASL/SCRAM + SSL + 细粒度ACL权限控制
一、先解决当前SCRAM认证失败错误
你的报错核心是controller与broker间SCRAM认证凭证不匹配,结合Bitnami Kafka特性,问题出在以下几点:
- 混用Bitnami专属环境变量与原生Kafka JAAS配置
- Controller listener的认证机制与JAAS配置冲突
- 用户凭证未通过Bitnami专属变量生成正确的SCRAM哈希
修复步骤:
- 移除手动JAAS配置:Bitnami Kafka会自动生成JAAS配置,自定义的
KAFKA_LISTENER_NAME_*_SASL_JAAS_CONFIG会覆盖自动生成内容,导致凭证不匹配,直接删除这些变量。 - 统一Controller与Broker认证机制:将controller的SASL机制改为
SCRAM-SHA-256,和inter-broker保持一致,避免PLAIN与SCRAM混合冲突。 - 替换用户凭证变量:用Bitnami专属的
KAFKA_SCRAM_USERS和KAFKA_SCRAM_PASSWORDS替代KAFKA_CLIENT_USERS/PASSWORDS,这两个变量会自动生成SCRAM所需的哈希凭证。
修改后的关键环境变量片段:
# Authentification - KAFKA_CFG_SASL_ENABLED_MECHANISMS=SCRAM-SHA-256 - KAFKA_CFG_SASL_MECHANISM_CONTROLLER_PROTOCOL=SCRAM-SHA-256 - KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL=SCRAM-SHA-256 # 移除所有KAFKA_LISTENER_NAME_*_SASL_JAAS_CONFIG变量 - KAFKA_SCRAM_USERS=admin,user1,user2 - KAFKA_SCRAM_PASSWORDS=admin-secret,user1-secret,user2-secret
二、完整配置:SASL/SCRAM + SSL + ACL权限控制
要实现用户仅访问专属主题,需在SASL认证基础上结合Kafka ACL实现细粒度权限控制,同时配置SSL加密外部连接。
1. 三节点KRaft Docker Compose完整配置
version: '3.8' services: kafka-0: image: docker.io/bitnami/kafka:${KAFKA_VERSION} hostname: kafka-0 container_name: kafka-0 ports: - "9094:9094" volumes: - ./kafka-ssl:/opt/bitnami/kafka/ssl - kafka-0-data:/bitnami/kafka environment: # KRaft基础配置 - KAFKA_CFG_NODE_ID=0 - KAFKA_CFG_PROCESS_ROLES=controller,broker - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka-0:9093,1@kafka-1:9093,2@kafka-2:9093 - KAFKA_KRAFT_CLUSTER_ID=abcdefghijklmnopqrstuv # 监听器配置 - KAFKA_CFG_MESSAGE_MAX_BYTES=20000000 - KAFKA_CFG_LISTENERS=BROKER://:9092,CONTROLLER://:9093,EXTERNAL://:9094 - KAFKA_CFG_ADVERTISED_LISTENERS=BROKER://kafka-0:9092,EXTERNAL://${HOST_IP}:9094 - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=BROKER:SASL_PLAINTEXT,CONTROLLER:SASL_PLAINTEXT,EXTERNAL:SASL_SSL - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=BROKER - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER # 集群副本配置 - KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3 - KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3 - KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR=2 # SASL/SCRAM配置 - KAFKA_CFG_SASL_ENABLED_MECHANISMS=SCRAM-SHA-256 - KAFKA_CFG_SASL_MECHANISM_CONTROLLER_PROTOCOL=SCRAM-SHA-256 - KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL=SCRAM-SHA-256 - KAFKA_SCRAM_USERS=admin,user1,user2 - KAFKA_SCRAM_PASSWORDS=admin-secret,user1-secret,user2-secret # SSL配置 - KAFKA_CFG_SSL_KEYSTORE_LOCATION=/opt/bitnami/kafka/ssl/kafka.keystore.jks - KAFKA_CFG_SSL_KEYSTORE_PASSWORD=keystore-secret - KAFKA_CFG_SSL_KEY_PASSWORD=key-secret - KAFKA_CFG_SSL_TRUSTSTORE_LOCATION=/opt/bitnami/kafka/ssl/kafka.truststore.jks - KAFKA_CFG_SSL_TRUSTSTORE_PASSWORD=truststore-secret # ACL权限控制 - KAFKA_CFG_AUTHORIZER_CLASS_NAME=org.apache.kafka.metadata.authorizer.StandardAuthorizer - KAFKA_CFG_ALLOW_EVERYONE_IF_NO_ACL_FOUND=false - KAFKA_CFG_SUPER_USERS=User:admin kafka-1: image: docker.io/bitnami/kafka:${KAFKA_VERSION} hostname: kafka-1 container_name: kafka-1 volumes: - ./kafka-ssl:/opt/bitnami/kafka/ssl - kafka-1-data:/bitnami/kafka environment: - KAFKA_CFG_NODE_ID=1 - KAFKA_CFG_PROCESS_ROLES=controller,broker - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka-0:9093,1@kafka-1:9093,2@kafka-2:9093 - KAFKA_KRAFT_CLUSTER_ID=abcdefghijklmnopqrstuv - KAFKA_CFG_LISTENERS=BROKER://:9092,CONTROLLER://:9093,EXTERNAL://:9094 - KAFKA_CFG_ADVERTISED_LISTENERS=BROKER://kafka-1:9092,EXTERNAL://${HOST_IP}:9095 - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=BROKER:SASL_PLAINTEXT,CONTROLLER:SASL_PLAINTEXT,EXTERNAL:SASL_SSL - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=BROKER - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER - KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3 - KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3 - KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR=2 - KAFKA_CFG_SASL_ENABLED_MECHANISMS=SCRAM-SHA-256 - KAFKA_CFG_SASL_MECHANISM_CONTROLLER_PROTOCOL=SCRAM-SHA-256 - KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL=SCRAM-SHA-256 - KAFKA_SCRAM_USERS=admin,user1,user2 - KAFKA_SCRAM_PASSWORDS=admin-secret,user1-secret,user2-secret - KAFKA_CFG_SSL_KEYSTORE_LOCATION=/opt/bitnami/kafka/ssl/kafka.keystore.jks - KAFKA_CFG_SSL_KEYSTORE_PASSWORD=keystore-secret - KAFKA_CFG_SSL_KEY_PASSWORD=key-secret - KAFKA_CFG_SSL_TRUSTSTORE_LOCATION=/opt/bitnami/kafka/ssl/kafka.truststore.jks - KAFKA_CFG_SSL_TRUSTSTORE_PASSWORD=truststore-secret - KAFKA_CFG_AUTHORIZER_CLASS_NAME=org.apache.kafka.metadata.authorizer.StandardAuthorizer - KAFKA_CFG_ALLOW_EVERYONE_IF_NO_ACL_FOUND=false - KAFKA_CFG_SUPER_USERS=User:admin kafka-2: image: docker.io/bitnami/kafka:${KAFKA_VERSION} hostname: kafka-2 container_name: kafka-2 volumes: - ./kafka-ssl:/opt/bitnami/kafka/ssl - kafka-2-data:/bitnami/kafka environment: - KAFKA_CFG_NODE_ID=2 - KAFKA_CFG_PROCESS_ROLES=controller,broker - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka-0:9093,1@kafka-1:9093,2@kafka-2:9093 - KAFKA_KRAFT_CLUSTER_ID=abcdefghijklmnopqrstuv - KAFKA_CFG_LISTENERS=BROKER://:9092,CONTROLLER://:9093,EXTERNAL://:9094 - KAFKA_CFG_ADVERTISED_LISTENERS=BROKER://kafka-2:9092,EXTERNAL://${HOST_IP}:9096 - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=BROKER:SASL_PLAINTEXT,CONTROLLER:SASL_PLAINTEXT,EXTERNAL:SASL_SSL - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=BROKER - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER - KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3 - KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3 - KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR=2 - KAFKA_CFG_SASL_ENABLED_MECHANISMS=SCRAM-SHA-256 - KAFKA_CFG_SASL_MECHANISM_CONTROLLER_PROTOCOL=SCRAM-SHA-256 - KAFKA_CFG_SASL_MECHANISM_INTER_BROKER_PROTOCOL=SCRAM-SHA-256 - KAFKA_SCRAM_USERS=admin,user1,user2 - KAFKA_SCRAM_PASSWORDS=admin-secret,user1-secret,user2-secret - KAFKA_CFG_SSL_KEYSTORE_LOCATION=/opt/bitnami/kafka/ssl/kafka.keystore.jks - KAFKA_CFG_SSL_KEYSTORE_PASSWORD=keystore-secret - KAFKA_CFG_SSL_KEY_PASSWORD=key-secret - KAFKA_CFG_SSL_TRUSTSTORE_LOCATION=/opt/bitnami/kafka/ssl/kafka.truststore.jks - KAFKA_CFG_SSL_TRUSTSTORE_PASSWORD=truststore-secret - KAFKA_CFG_AUTHORIZER_CLASS_NAME=org.apache.kafka.metadata.authorizer.StandardAuthorizer - KAFKA_CFG_ALLOW_EVERYONE_IF_NO_ACL_FOUND=false - KAFKA_CFG_SUPER_USERS=User:admin volumes: kafka-0-data: kafka-1-data: kafka-2-data:
2. SSL证书生成(本地自签示例)
在./kafka-ssl目录下执行以下命令生成JKS证书:
# 生成keystore keytool -genkey -alias kafka -keyalg RSA -keystore kafka.keystore.jks -storepass keystore-secret -keypass key-secret -validity 3650 -dname "CN=kafka,OU=dev,O=company,L=city,S=state,C=CN" # 导出证书并生成truststore keytool -export -alias kafka -file kafka.crt -keystore kafka.keystore.jks -storepass keystore-secret keytool -import -alias kafka -file kafka.crt -keystore kafka.truststore.jks -storepass truststore-secret -noprompt
三、动态添加SCRAM用户与ACL权限配置
1. 动态添加SCRAM用户
进入任意Kafka容器,使用kafka-configs.sh添加用户:
docker exec -it kafka-0 bash # 先创建admin的客户端配置文件 cat > /opt/bitnami/kafka/config/admin-client.properties << EOF security.protocol=SASL_PLAINTEXT sasl.mechanism=SCRAM-SHA-256 sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required username="admin" password="admin-secret"; EOF # 添加新用户user3 kafka-configs.sh --bootstrap-server kafka-0:9092 --command-config /opt/bitnami/kafka/config/admin-client.properties --alter --add-config 'SCRAM-SHA-256=[password=user3-secret]' --entity-type users --entity-name user3
2. 配置ACL权限(用户仅访问专属主题)
以user1仅能访问user1-topic为例:
# 授予user1对user1-topic的读写权限 kafka-acls.sh --bootstrap-server kafka-0:9092 --command-config /opt/bitnami/kafka/config/admin-client.properties --add --allow-principal User:user1 --operation Read --operation Write --topic user1-topic # 授予user1对自身消费组的权限 kafka-acls.sh --bootstrap-server kafka-0:9092 --command-config /opt/bitnami/kafka/config/admin-client.properties --add --allow-principal User:user1 --operation Read --operation Write --group user1-group
四、Python客户端配置示例(confluent-kafka)
from confluent_kafka import Producer, Consumer # 生产者配置 producer_conf = { 'bootstrap.servers': 'your-host-ip:9094', 'security.protocol': 'SASL_SSL', 'sasl.mechanism': 'SCRAM-SHA-256', 'sasl.username': 'user1', 'sasl.password': 'user1-secret', 'ssl.ca.location': './kafka-ssl/kafka.crt', 'client.id': 'user1-producer' } # 消费者配置 consumer_conf = { 'bootstrap.servers': 'your-host-ip:9094', 'security.protocol': 'SASL_SSL', 'sasl.mechanism': 'SCRAM-SHA-256', 'sasl.username': 'user1', 'sasl.password': 'user1-secret', 'ssl.ca.location': './kafka-ssl/kafka.crt', 'group.id': 'user1-group', 'auto.offset.reset': 'earliest' }
内容的提问来源于stack exchange,提问作者Vladimir Shebuniayeu
相关产品推荐
相关产品推荐

