资讯动态

Kafka安全认证机制与生产实践:SSL、SASL/SCRAM、ACL

发布时间:2026/10/14 22:33:33 来源:尧图企业网站定制
我们先把话说在前面Kafka 跑起来很容易但生产环境的 Kafka 集群从来不是“能收发消息”就完事了。搞大数据平台的人迟早都会遇到这么一个问题集群内网明明做了隔离但某天安全审计说你所有 Broker 端口裸奔没有鉴权随便来个人只要网络通就能消费生产数据。我之前陪着某团队做平台整改三个集群、几十个业务方全部对接安全认证前前后后踩了小一个月的坑今天把这些经验整理出来希望能让后来的人少走弯路。先说清楚这篇内容围绕 Kafka 的安全认证机制展开核心包括三块链路加密SSL/TLS、身份认证SASL、权限管控ACL。适合正在做大数据平台运维、消息中间件统一管控、或者被安全合规压着必须给 Kafka 上锁的工程师阅读。本文不会停留在罗列概念的层面而是直接给出可落地的配置、参数、坑点和排障思路。1. 先理清楚 Kafka 安全认证到底护住了什么1.1 从三个维度看待 Kafka 安全传输、身份、权限安全审计来的时候不会只问“你有没有密码”他们会拆成三件事来问。第一件事网络上传输的数据有没有可能被别人抓包看到这个靠SSL/TLS 链路加密解决也就是配置SSL://协议。Kafka 客户端与 Broker 之间传输的内容如果走明文那就是裸奔内网抓包直接能看到消息体。第二件事连接 Kafka 的一方到底是什么身份这个靠SASL 认证解决。Kafka 支持多种认证机制最常用的是 PLAIN、SCRAM、GSSAPIKerberos、OAUTHBEARER。认证是“你和 Broker 之间确认彼此身份”的过程必须发生在客户端发消息之前。第三件事即使知道你是谁你到底能动哪些数据这个靠ACL 授权解决。Kafka 的 ACL 定义了“谁Principal可以对哪个资源Topic/Consumer Group做什么操作Read/Write/Describe”。很多人以为配好账号密码就安全了实际上不配 ACL光认证通过的用户默认有集群超级权限这比不认证更可怕——等于门卫问你要了工牌但不管进去之后能拿什么。这三层需要放在一起理解SSL 解决“通信过程怕被偷听”SASL 解决“你是谁”ACL 解决“你能干什么”。如果时间紧认证和授权必须一块上传输加密可以后补但千万不能只做用户密码不设 ACL。1.2 四种监听器协议组合该怎么选Kafka 的listeners是个多协议配置常见组合包括PLAINTEXT、SSL、SASL_PLAINTEXT、SASL_SSL四种。刚接触的人容易被这些枚举名绕晕其实拆开来看就明白了下划线前面是“认证方式”下划线后面是“传输方式”。监听器协议认证方式传输方式适用场景PLAINTEXT无认证明文传输仅本机调试单机演示SSL无认证互相认证除外TLS加密只要求传输加密不需要登录身份SASL_PLAINTEXTSASL认证明文传输内网可信环境主要做身份管控SASL_SSLSASL认证TLS加密生产最推荐跨安全域、跨机房必选我自己的倾向是任何有多业务方接入的测试环境以上规模直接用SASL_PLAINTEXT先把账号体系建起来后续有条件再升级到SASL_SSL。如果一上来就SASL_SSL证书签发和管理工作会和业务适配纠缠在一起排障成本瞬间翻倍。这里有一点容易忽略advertised.listeners必须和实际内网访问地址保持同协议。曾经有团队把listeners配成 SASL_SSL但advertised.listeners忘了同步改客户端连上后拿到的是“内网普通 PLAINTEXT 地址”导致一堆诡异的握手错乱。1.3 为什么生产环境优先选 SCRAM 而不是 PLAIN 或 KerberosPLAIN 是很多离线教程里用过的机制只把用户名密码通过 SASL 握手发给 Broker实现简单但它的缺点非常致命PLAIN 的密码必须明文存储在 Kafka 的 JAAS 文件里Broker 重启、多节点同步、密码轮换都非常痛苦。而且 PLAIN 的接口不能动态创建用户只能改配置重启这在多业务方动态接入的场景下不可接受。Kerberos 在传统大数据集群Hadoop/Hive 体系里地位很高但它依赖额外的 KDC票据过期策略、跨域名 realm 映射、客户端 keytab 分发每一件都够折腾一阵子。如果公司没有已经运维良好的 KDC 基础设施不要强行上 Kerberos维护成本会吃掉所有安全收益。SCRAMSalted Challenge Response Authentication Mechanism是目前平衡安全和运维的最佳实践。它基于挑战-响应机制密码以摘要形式存在服务端不会在网络中明文传输同时支持通过kafka-configs.sh动态创建用户和修改密码。也就是说加一个业务方接入不需要重启 Broker只要发给他账号和密码即可。对生产环境来说这个“免重启新增用户”是刚需。2. 动手之前要捋清的版本和部署前缀2.1 版本差异直接决定配置文件长什么样Kafka 版本演进中配置项的变化很大。如果是 0.11 以前的老版本安全配置是另一套写法。目前主流是 2.x 以及 3.x。2.x 阶段authorizer.class.name是常规配置3.x 之后 KRaft 逐步替代 ZooKeeperServer 端配置结构有所调整。在开始之前我强烈建议先用kafka-broker-api-versions.sh确认集群的精确版本再查官方文档里对应版本的“Security”章节。网上搜到的配置如果不问版本直接抄大概率会踩到listener.name.{listenerName}.{mechanism}.sasl.jaas.config新旧格式不兼容的问题。举个例子2.6 之前SASL/SCRAM 的 JAAS 可以写在config/server_jaas.conf里再用KAFKA_OPTS-Djava.security.auth.login.config/path/server_jaas.conf引入。2.7 之后官方更推荐在server.properties里直接写listener.name.sasl_ssl.scram-sha-256.sasl.jaas.configorg.apache.kafka.common.security.scram.ScramLoginModule required;这种独立配置块。你只有搞清楚版本才能判断该采用哪种方式。2.2 KRaft 模式下的安全认证部署方式不同Kafka 3.3 以后KRaft 模式不再依赖 ZooKeeper已经可以用于生产。KRaft 模式下Controller 和 Broker 本身就是两个独立监听器如果不把安全机制覆盖到 Controller 的监听器上就等于你给数据面加了一把锁但控制面大门敞开。控制面被入侵集群元数据、分区副本分配、Leader 选举全部能被操纵。我的建议是在 KRaft 模式下要么全部监听器统一切到SASL_SSL SCRAM要么至少给CONTROLLER监听器配上单独的存储认证机制。Controller 的认证和 Data Plane 的认证要分清否则你改了 Broker 的认证controller 互相通信还是老配置日志里会反复出现 cluster authorization failed。另外KRaft 模式创建账号的方式也有变化。ZooKeeper 模式可以走kafka-configs.sh --zookeeper ...来写用户KRaft 模式必须用--bootstrap-server指定 controller 或 broker而且需要先配置一个超级用户才能初始化。这个顺序是先在 server.properties 里设置一个超级用户super.users启动 controller再用超级用户创建后续的普通 SCRAM 用户。2.3 证书规划千万别一把梭如果决定上 SSL 传输加密“证书”这一块要提前规划否则后面给几十个客户端分发证书会非常痛苦。第一种方案是自己建根 CA自签 CA为每个 Broker、每个客户端签发独立证书并把根 CA 证书放到各端的 truststore。完整程度高但签名和分发工作量也大。第二种做法是用统一证书。团队内部网络环境所有 Broker 共用一份证书域名/IP 通过SAN扩展写进去。客户端只需要配一个 truststore 加上客户端自己的 keystore复杂度大大降低。代价是一旦证书泄漏整个集群的所有节点都受影响。我的经验是中小规模集群先统一证书配合内网 IAM 体系用短期证书半年轮换一次。如果被审计要求严格再上独立证书并配合自动化签发工具。等价的说法是如果你还不打算做自动化证书轮换就不要一步到位玩“每个节点不同证书、不同 hostname”的形态。布鲁诺前车之鉴是某团队第一周就把几十个证书签好了第二周因为机房 IP 段调整全部作废重签浪费的时间足够再搭一整套认证。3. 从零把 Kafka 上线 SASL/SCRAM ACL 的完整实操3.1 第一步Broker 端配置认证我们以 3.4 版本、部署在/data/kafka目录下为例。先编辑config/server.properties以下给出核心配置块。# 监听器与安全协议配置 listenersSASL_PLAINTEXT://0.0.0.0:9092 advertised.listenersSASL_PLAINTEXT://kafka-001.example.internal:9092 # 这里按业务网段自行替换 # 允许所有机器都经过 SASL 认证 listener.security.protocol.mapSASL_PLAINTEXT:SASL_PLAINTEXT # 指定认证机制 sasl.enabled.mechanismsSCRAM-SHA-256 listener.name.sasl_plaintext.scram-sha-256.sasl.jaas.configorg.apache.kafka.common.security.scram.ScramLoginModule required; # 授权相关 authorizer.class.namekafka.security.authorizer.AclAuthorizer super.usersUser:admin有几个点我需要刻意提醒第一listener.name.sasl_plaintext.scram-sha-256.sasl.jaas.config中listener.name后面的值要与你实际配置的监听器名严格对应。很多同志把sasl_PLAINTEXT大写小写混淆或者没注意到监听器名全部要转换成小写再点分割结果 Broker 启动后外部客户端始终报“Unsupported SASL mechanism”。第二如果同时启用多套认证机制比如 SCRAM 与 PLAIN 共存要在sasl.enabled.mechanisms里同时列出来但建议业务初期不要混用多机制会成倍增加排障难度。重启完 Broker正常情况下日志里应该看到类似Registered broker 0 at path ... with epoch ...的输出并出现与sasl相关的一堆初始化日志。此时用kafka-configs.sh --bootstrap-server还不能直接创建用户因为 admin 账号还没建需要管理员权限。所以提前在server.properties里配置super.usersUser:admin是有意为之——先给集群做一个“人肉超级管理账号”等启动完成后用这个账号去创建运维或者业务账号。后面 SLF4J 日志会出现“User admin has been successfully logged in”这类握手日志看到这类信息就说明认证已经被启用。3.2 第二步创建 SCRAM 用户与凭据通过kafka-configs.sh动态创建用户。在 3.x 版本中推荐使用--bootstrap-server操作不要再用旧版--zookeeper方式。# 先配置管理用户环境变量 export KAFKA_OPTS-Djava.security.auth.login.config/data/kafka/config/kafka_client_jaas.conf # 创建业务账号 kafka-configs.sh \ --bootstrap-server kafka-001.example.internal:9092 \ --alter \ --add-config SCRAM-SHA-256[passwordmy-secure-pass] \ --entity-type users \ --entity-name app_ data_consumer注意看上面这段entity-name就是登录 Kafka 时使用的用户名最终在 ACL 授权里看到的 Principal 为User:app_data_consumer。创建完可以验证kafka-configs.sh \ --bootstrap-server kafka-001.example.internal:9092 \ --describe \ --entity-type users \ --entity-name app_data_consumer输出中应该显示SCRAM-SHA-256的摘要信息。SCRAM 机制的本质是“服务端只存盐值和迭代替换后的摘要”客户端每次握手时带着用户名发起挑战因此即使配置文件泄漏密码原文也不会直接暴露。这里注意一点SCRAM 用户列表存在 ZooKeeper 或 KRaft 元数据中不是存在本地文件。如果集群有多个节点创建的用户会被所有节点识别不需要逐台添加。3.3 第三步给业务账号配上足够但不越权的 ACL这一步是安全策略的临门一脚。不做 ACL相当于能登录就拥有一切权限。做了 ACL 之后即便密码泄漏攻击者也只能在有限的授权范围内操作这是纵深防御的关键。Kafka 的 ACL 是基于“资源 操作 用户”三元组授权的常用到的是 Topic 的读写Consumer Group 的读和 Group 描述等。以授权app_data_consumer用户消费order_event主题为例kafka-acls.sh \ --bootstrap-server kafka-001.example.internal:9092 \ --add \ --allow-principal User:app_data_consumer \ --operation Read \ --operation Describe \ --topic order_event \ --group order_event_group这意味着这个用户能够消费order_event的数据同时能查看这个消费组的 Offset、Lag 状态。注意如果这里没有授权 Describe 操作客户端在启动消费时即使能连接 Broker也会在获取 group 元数据或提交 offset 时收到 TOPIC_AUTHORIZATION_FAILED 或 GROUP_AUTHORIZATION_FAILED。生产端授权类似kafka-acls.sh \ --bootstrap-server kafka-001.example.internal:9092 \ --add \ --allow-principal User:app_data_producer \ --operation Write \ --operation Describe \ --topic order_event如果业务方需要同时生产多个主题可以一次性传多个--topic参数避免重复执行脚本。这里有个细节Describe操作对于生产客户端也不是废话没有它客户端连“这个主题是否存在、分区 leader 是谁”都无法感知直接连不上。还有一类内网平台常见的权限查主题列表、查看消费组列表。很多平台型业务经常要向运维要这权限建议默认不给统一收口到运维账号否则 ACL 形同虚设。提示不要一上来就敲一堆授权脚本先给业务方最小权限配合业务上线过程逐步放开。前期半步不放后期全量放开都会让你被业务方反复拉群“下一步还报错”效率极低。3.4 第四步客户端侧配置与接入适配服务端改了协议所有现存客户端基本无法直接使用这是必然的没人能绕过这一步。以 Java 客户端为例生产者和消费者都要在Properties里补上认证相关配置properties.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, SASL_PLAINTEXT); properties.put(SaslConfigs.SASL_MECHANISM, SCRAM-SHA-256); properties.put(SaslConfigs.SASL_JAAS_CONFIG, org.apache.kafka.common.security.scram.ScramLoginModule required username\app_data_producer\ password\my-secure-pass\;);如果用的是 Spring Kafka则对应地配置spring: kafka: bootstrap-servers: kafka-001.example.internal:9092 properties: security.protocol: SASL_PLAINTEXT sasl.mechanism: SCRAM-SHA-256 sasl.jaas.config: org.apache.kafka.common.security.scram.ScramLoginModule required usernameapp_data_producer passwordmy-secure-pass;常见的新人疑问是JAAS 配置中的SaslConfigs.SASL_JAAS_CONFIG是不是所有客户端版本都支持其实这是 2.x 版本加入的如果客户端版本太老必须退回到-Djava.security.auth.login.config指向的 JAAS 文件。生产上强制客户端依赖版本在 2.3 以上可以省掉一堆兼容性排障。Python 客户端基于 confluent-kafka的配置示例也一并给了方便多语言团队参考conf { bootstrap.servers: kafka-001.example.internal:9092, security.protocol: SASL_PLAINTEXT, sasl.mechanism: SCRAM-SHA-256, sasl.username: app_data_producer, sasl.password: my-secure-pass }3.5 第五步验证配置是否真正生效不要只看“客户端能连上、能收发消息”就认为认证没问题。我见过太多例子客户端自己配置了错误的security.protocol但因为 Kafka 服务端仍然同时监听了明文端口结果客户端以明文方式连上去了像裸奔一样运行了数月。用 CLI 工具做一次针对性验证kafka-console-producer.sh \ --bootstrap-server kafka-001.example.internal:9092 \ --topic order_event \ --producer.config /path/client_sasl.properties其中client_sasl.properties必须包含与生产环境一致的认证配置。执行成功再查看 Broker 的服务端日志名称匹配的监听器下会出现用户登录记录和 ACL 校验日志。我还习惯在服务端开启审计日志来观察 ACL 行为可以灵活设置log4j.properties中与kafka.authorizer.logger相关的日志级别为DEBUG只在排障时开启用完再关掉避免长期刷大量日志影响磁盘。4. 现场踩坑实录明明认证通过了授权又卡住4.1 坑一所有客户端都报 Principal 无法解析现象客户端输入了正确的用户名密码但连接时提示Server failed to authenticate: User:xxx not found或者Authentication failed。排查时先查 Broker 端server.log确认该用户是否在USER中存在确认是不是走了--bootstrap-server对Kraft模式创建到了错误的存储分区。还有一个容易被忽视的点用户名不要带空格、不要包含中划线等特殊字符Kafka 对 Principal 的解析会处理异常字符。4.2 坑二明明能生产消费组一直在 REBALANCE现象生产端已经能正常发消息但消费端每隔几十秒就重新平衡。通常原因有两种。第一种是消费组相关的 ACL 没有配全尤其遗漏了Describe权限导致的 group 元数据读权限第二种是网络抖动但如果你引入了认证首先要怀疑是否在 ACL 中遗漏了--group授权。用kafka-consumer-groups.sh --describe手动查一下如果报错GROUP_AUTHORIZATION_FAILED基本就实锤了。4.3 坑三Broker 节点间互相认证不过现象KRaft 模式下Controller 与 Broker 节点之间出现周期性的Connection to node -1 (host/kafka-002...) terminated authentication failed。这个坑很经典——你给数据面配了SASL_PLAINTEXT认证然后忘了给CONTROLLER监听器加独立认证配置。不同节点上的 controller 和 broker 使用不同 JAAS 配置导致互相不认。如果你不打算为 controller 维护额外账号体系有一个巧方案把 controller 和 broker 的监听器认证都放到同一个 SCRAM 用户上虽然不符合最小权限原则但能保证内聚快速跑通。等业务稳定后在拆分别一上来就和多账号体系死磕。4.4 坑四ACL 中看到允许条目但客户端依然报 TOPIC_AUTHORIZATION_FAILED对于 Kafka ACL它的判定逻辑不是“没有显式拒绝则放行”而是“没有显式允许则拒绝”默认白名单原则。所以一条消费报错必须做三检查。检查用户本身是否为super.users成员检查 topic 授权包含 Read 和 Describe检查 group 授权包含 Read 和 Describe。另外client ID 信息也会出现在某些授权错误日志里但 ACL 默认不针对 client ID别被误导。4.5 坑五客户端能访问所有 topic 的元数据现象某个用户只是授权了一个 topic但用kafka-topics.sh --list却把整个集群的主题列表拉了出来。这通常说明super.users里配置了该用户或者该用户被误配置成超级用户。超级用户会绕过所有 ACL 检查这是安全审计里最敏感的配置之一。我记得有次处理某平台整改排查到最后居然发现为了图省事把一批测试账号都塞进了super.users整个集群的权限体系等于摆设。这个配置只保留运维管理员账号业务账号一律走 ACL。4.6 给新接入 Kafka 团队的一个排障顺序建议遇到安全认证问题我建议按这个顺序排查能节省大量时间确认客户端和服务端版本再查配置语法看 Broker 端server.log尤其是Authentication和Authorization相关行用同一个用户在能通到 Broker 的机器上手动敲 CLI 命令区分是配置问题还是网络到 Broker 链路问题用--describe确认 ACL 并确认用户是否存在、是否在super.users中最后才考虑是不是代码或框架封装的锅这一步排查优先级最低因为框架问题往往在日志里会有明显的异常堆栈。这套顺序我给过好几拨人每次都能让他们从“瞎试”状态拉回来。最怕的是一上来就翻代码改代码然后越改越乱最后连原本能跑通的配置也被改坏。结尾一点体会我在实际运维 Kafka 的过程中体会到安全认证不是一次性的配置动作而是要当作一项基础设施能力持续建设。它和你的业务接入流程、账号生命周期管理、证书或密钥轮换机制是深度绑定的。今天你说“先让业务跑通安全后补”过三个月再回头往往要推倒重来还得同时安抚几十个被断连的业务方那种场面非常消耗信任。我的建议是即便初期业务很小也至少把 SCRAM ACL 跑通用最小权限模型对接业务方。传输加密可以等证书体系成熟后再升级但身份和权限的骨架一定要从第一天就立起来。等以后安全审计主动来找你你这边只需要拿出配置清单和授权策略就能从容应对而不是临时补课。如果你现在正准备给 Kafka 集群开启认证优先把文中的 Broker 端配置跑一遍再拿一个真实业务主题做端到端验证。脚本敲完、消息通掉的那一刻你会发现这个过程的难点其实不在于机制原理而在于每个环节的细节契合度而细节恰恰是这篇文章里花了最大篇幅去抠的部分。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑