Apache Kafka 中的认证、鉴权原理与应用

编辑导读:本篇内容将进一步介绍 Kafka 中的认证、鉴权等概念。AutoMQ 是与 Apache Kafka 100% 完全兼容的新一代 Kafka,可以帮助用户降低 90%以上的 Kafka 成本并且进行极速地自动弹性。作为 Kafka 生态的忠实拥护者,我们也会持续致力于传播 Kafka 技术,欢迎关注我们。

我们在此前的文章《AutoMQ SASL 安全身份认证配置教程》[1]介绍过 Apache Kafka (以下简称 Kafka)服务端和客户端的 SASL 认证协议配置,并在《AutoMQ SSL 安全协议配置教程》[2]详细介绍了如何利用 SSL(TLS) 实现 Kafka 或 AutoMQ 的安全通信。本文将进一步概述 Kakfa 中的认证方法和鉴权策略,并通过一个例子来说明我们在真实应用场景中如何对 Kafka 或者 AutoMQ 集群开启身份认证和鉴权。

注意,本文默认 Kafka 集群是以 Kraft 模式工作的。

Listener、安全协议、认证与鉴权的关系

先回顾一下 listener 的作用。listener 是 Kafka 服务端定义监听地址(域名/IP + 端口)和安全协议的实体。一般情况下,我们可以利用多 listener 来差异化设置:

  • broker 与 broker 之间,controller 与 broker 之间,client 与 broker 之间的通信安全协议;

  • 内网(局域网或 VPC 内部)访问 broker、外网访问 broker 时的通信安全协议;

我们可以将 listener name 跟安全协议进行映射,举例来说,Kafka 支持以下安全协议:

我们可以设置 client 与 broker 之间使用 SASL_SSL 协议保证加密性,而集群节点之间使用 SASL_PLAINTEXT 减少 CPU 加密解密的消耗:

listeners=EXTERNAL://:9092,BROKER://10.0.0.2:9094
advertised.listeners=EXTERNAL://broker1.example.com:9092,BROKER://broker1.local:9094
listener.security.protocol.map=EXTERNAL:SASL_SSL,BROKER:SASL_PLAINTEXT 
inter.broker.listener.name=BROKER

下图展示了 Listener、安全协议、认证与鉴权之间的关系

在这里插入图片描述

安全协议决定了服务端和客户端之间的认证(Authentication)协议,而鉴权(Authorization)基本独立于认证,只校验通过认证的主体对请求中涉及的资源是否有操作权限。下文将详细介绍认证方法和鉴权规则。

认证

认证主体

先简单介绍一下认证主体的概念。

认证主体是对 client 的身份标识,对应一个 KafkaPrincipal 对象[5]。当 client 通过认证协议完成认证后,broker 侧会将该 KafkaPrincipal 对象塞入 RequestContext,并向上传递,以供后续鉴权。一个 KafkaPrincipal 对象主要包括主体类型(目前仅有"User"这一类别)以及一个名称(可以简单理解为 client 声明的用户名)。

认证协议

安全协议到认证协议之间的映射为:

  • PLAINTEXT:无认证;

  • SSL:无认证/mTLS;

  • SASL_PLAINTEXT: SASL;

  • SASL_SSL: SASL;

其中 SSL 如果想要利用 mTLS 进行认证,需要在 broker 侧开启对 client 的 SSL 验证:

ssl.client.auth=required

利用证书中的“DistinguishedName”字段[4]识别认证主体。由于认证通常涉及到用户的管理,这种通过证书进行认证的方式在增删用户时显得比较“笨重”(尤其是动态增删用户的场景),并不是主流的认证方式。

SASL 认证协议又可以进一步细分为以下认证机制:

  • GSSAPI:借助第三方 Kerberos[3](一种基于 ticket 的加密认证协议)服务器进行认证认证;

  • PLAIN:简单账密认证,注意它跟前文的 PLAINTEXT 不是一个概念;

  • SCRAM-SHA-256/512:基于 SCRAM 算法,由 Kafka 节点基于 record 自认证;

  • OAUTHBEARER:借助第三方 OAuth 服务器认证;

Kafka broker 允许同时启用多种 SASL 认证,例如同时启用 SCRAM-SHA-256/512 + PLAIN:

sasl.enabled.mechanisms=SCRAM-SHA-256,PLAIN,SCRAM-SHA-512

Broker 侧还需要额外的 JAAS 配置,在《AutoMQ SASL 安全身份认证配置教程》中已经提及,这里不再赘述。

需要注意的是,Kafka 提供了默认的 SASL/PLAIN 实现,需要在每个节点配置中显示声明账密信息。这种静态认证方式同样不利于用户的动态管理,可以通过集成外部的账密认证服务器来提供动态能力。

鉴权

鉴权是基于认证主体,检查是否有权限操作请求的资源。

鉴权配置

重要的配置包括:

  • authorizer.class.name:指定鉴权器,默认为空。Kraft 模式下可以填写官方提供的 “org.apache.kafka.metadata.authorizer.StandardAuthorizer”,基于 ACL(access control list)规则认证;

  • super.users:设置超级用户,默认为空。格式为 User:{userName}。这里指定的用户将不受 ACL 约束,直接拥有所有资源的所有操作权限

  • allow.everyone.if.no.acl.found:指定资源没有任意 ACL 约束时的默认权限,默认为 false。false 表示仅允许 super user 操作,true 表示允许任意用户操作。

鉴权规则

Kafka 是基于 ACL(access control list) 规则限制用户对资源的访问的。一条 ACL 规则包含两部分:

  • ResourcePattern:声明资源及其匹配方式,包含:

    • ResourceType:资源类型,包括 TOPIC、GROUP(消费者组)、CLUSTER 等;

    • ResourceName:资源名称;

    • PatternType:资源匹配方式,包括 LITERAL(全文匹配) 和 PREFIXED(前缀匹配);

  • AccessControlEntry:用户限制信息,包括:

    • Principal:认证主体,其实就是个用户名;

    • Host:用户主机地址;

    • AclOperation:操作行为,包括 Read、Write、CREATE、DELETE 等;

    • AclPermissionType:允许/禁止。

一句话串联上述规则信息就是:

允许/禁止 来自 {Host} 的用户 {Principal} 对匹配类型为 {PatternType} 、名称为 {ResourceName} 的资源进行 {AclOperation} 操作。

当同时满足:

  • 存在某条 ACL 允许用户操作

  • 不存在任何一条 ACL 禁止用户操作

时,允许用户对资源进行操作。

需要注意的是,可以将通配符“*”作为 ResourceName 或 Host 的内容。对于 Host 字段,填写“*” 表示任意地址。ResourceName 为 “*”,且 PatternType 为 LITERAL 时表示匹配任意名称;如果 ResourceName 为 “*”,PatternType 为 PREFIXED,表示匹配前缀名称为“*”的资源。

此外,当 ResourceType 为 CLUSTER 时,ResourceName 只能填写"kafka-cluster"

升级认证协议或开启鉴权

某些情况下我们需要考虑安全协议的切换,或者需要将集群从无鉴权转为开启鉴权。例如,在开发环境中,我们通常直接用默认的 PLAINTEXT 配置集群,如果不幸在测试或生产环境中也使用了 PLAINTEXT 协议,那么就需要考虑升级安全协议并开启鉴权。

以下以“PLAINTEXT、无鉴权”升级为“SASL_PLAINTEXT、开启鉴权”为例,介绍如何平滑过渡。其他安全协议的变化可以以此类推。

以下假定三台 Kafka 节点都在本机部署,使用不同的端口以示区分。三台节点均为 controller + broker 的混部节点。注意,各个阶段变更时,需要一一重启各个节点。

整体逻辑示意图:

在这里插入图片描述

集群共需要三轮重启,业务侧需要一轮重启。

原始配置

以下为第一个节点在 PLAINTEXT 协议下的部分配置,其他节点配置依次类推:

node.id=1
controller.quorum.voters=1@localhost:9093,2@localhost:9095,3@localhost:9097
listeners=PLAINTEXT://:9092,CONTROLLER://:9093
inter.broker.listener.name=PLAINTEXT
advertised.listeners=PLAINTEXT://localhost:9092
controller.listener.names=CONTROLLER
listener.security.protocol.map=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL

阶段一:新协议+默认 ALLOW 鉴权上线

node.id=1
# 保持不变
controller.quorum.voters=1@localhost:9093,2@localhost:9095,3@localhost:9097
# controller 和 broker 的新 listener 上线
listeners=PLAINTEXT://:9092,CONTROLLER://:9093,BROKER_SASL://:9192,CONTROLLER_SASL://:9193
# 保持不变
inter.broker.listener.name=PLAINTEXT
# 新地址上线
advertised.listeners=PLAINTEXT://localhost:9092,BROKER_SASL://localhost:9192
# 新 listener 上线
controller.listener.names=CONTROLLER,CONTROLLER_SASL

# authorization
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
# 允许所有人访问资源
allow.everyone.if.no.acl.found=true
# 超级用户,用于节点之间认证
super.users=User:automq

sasl.enabled.mechanisms=SCRAM-SHA-256,PLAIN,SCRAM-SHA-512
# 指定与 broker 通信时具体的 SASL 机制
sasl.mechanism.inter.broker.protocol=PLAIN
# 指定与 controller 通信时具体的 SASL 机制
sasl.mechanism.controller.protocol=PLAIN
# 静态账密配置
listener.name.broker_sasl.plain.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
   username="automq" \
   password="automq-secret" \
   user_automq="automq-secret";

listener.name.controller_sasl.plain.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
   username="automq" \
   password="automq-secret" \
   user_automq="automq-secret";

# 认证模块配置
listener.name.broker_sasl.scram-sha-256.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;
listener.name.controller_sasl.scram-sha-256.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;
listener.name.broker_sasl.scram-sha-512.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;
listener.name.controller_sasl.scram-sha-512.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;

# 添加新 listener 到 安全协议的映射
listener.security.protocol.map=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL,BROKER_SASL:SASL_PLAINTEXT,CONTROLLER_SASL:SASL_PLAINTEXT

其中“allow.everyone.if.no.acl.found”设置为 true,是为了让线上的 client 能够正常认证,避免直接鉴权失败。

“controller.listener.names”设置为“CONTROLLER,CONTROLLER_SASL”,表示 controller 同时使用两个 listener,并且本 node 的 broker 将使用“CONTROLLER”映射的安全协议与 controller 通信。

本阶段结束以后,需要通知业务方重新配置基于 SASL_PLAINTEXT 配置客户端。同时,需要为各业务方配置 ACL 所需的规则。

阶段二:节点之间使用新协议+鉴权开启

在上一阶段执行后,新协议下的 listener 已经上线,并可以对外提供服务,但是集群的节点之间依旧维持原有的通信协议,本阶段会将内部通信进行升级:

node.id=1
# 使用新 controller 端口
controller.quorum.voters=1@localhost:9193,2@localhost:9195,3@localhost:9197
# 保持不变
listeners=PLAINTEXT://:9092,CONTROLLER://:9093,BROKER_SASL://:9192,CONTROLLER_SASL://:9193
# 使用新协议
inter.broker.listener.name=BROKER_SASL
# 使用新地址
advertised.listeners=PLAINTEXT://localhost:9092,BROKER_SASL://localhost:9192

# 注意顺序变化
controller.listener.names=CONTROLLER_SASL,CONTROLLER

# authorization
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
# allow.everyone.if.no.acl.found=true
super.users=User:automq

# 保持不变
sasl.enabled.mechanisms=SCRAM-SHA-256,PLAIN,SCRAM-SHA-512
sasl.mechanism.inter.broker.protocol=PLAIN
sasl.mechanism.controller.protocol=PLAIN
listener.name.broker_sasl.plain.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
   username="automq" \
   password="automq-secret" \
   user_automq="automq-secret";
listener.name.controller_sasl.plain.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
   username="automq" \
   password="automq-secret" \
   user_automq="automq-secret";

# 保持不变
listener.name.broker_sasl.scram-sha-256.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;
listener.name.controller_sasl.scram-sha-256.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;
listener.name.broker_sasl.scram-sha-512.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;
listener.name.controller_sasl.scram-sha-512.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;

# 保持不变
listener.security.protocol.map=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL,BROKER_SASL:SASL_PLAINTEXT,CONTROLLER_SASL:SASL_PLAINTEXT

注意,“allow.everyone.if.no.acl.found”配置被注释掉了,也就是不再默认允许任何人任意操作资源了。

阶段三:下线旧协议

node.id=1

# 保持不变
controller.quorum.voters=1@localhost:9193,2@localhost:9195,3@localhost:9197
# 下线旧 listener
listeners=BROKER_SASL://:9192,CONTROLLER_SASL://:9193

# 保持不变
inter.broker.listener.name=BROKER_SASL

# 下线旧地址
advertised.listeners=BROKER_SASL://localhost:9192

# 下线旧 listener
controller.listener.names=CONTROLLER_SASL

# authorization
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
# allow.everyone.if.no.acl.found=true
super.users=User:automq

# 保持不变
sasl.enabled.mechanisms=SCRAM-SHA-256,PLAIN,SCRAM-SHA-512
sasl.mechanism.inter.broker.protocol=PLAIN
sasl.mechanism.controller.protocol=PLAIN
listener.name.broker_sasl.plain.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
   username="automq" \
   password="automq-secret" \
   user_automq="automq-secret";
listener.name.controller_sasl.plain.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
   username="automq" \
   password="automq-secret" \
   user_automq="automq-secret";

# 保持不变
listener.name.broker_sasl.scram-sha-256.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;
listener.name.controller_sasl.scram-sha-256.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;
listener.name.broker_sasl.scram-sha-512.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;
listener.name.controller_sasl.scram-sha-512.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required;

# 保持不变
listener.security.protocol.map=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL,BROKER_SASL:SASL_PLAINTEXT,CONTROLLER_SASL:SASL_PLAINTEXT

至此,旧协议下线,所有通信基于 SASL_PLAINTEXT 协议。

总结

本文概述了 Kafka 中的认证协议和鉴权策略。首先介绍了 listener 与安全协议的映射,以及安全协议与认证方法的映射。接着分别介绍 Kafka 中支持的多种认证协议,以及 ACL 鉴权策略。在认证通过后,Kafka 会生成一个认证主体,供上层进行细粒度的鉴权。最后介绍了如何对一个运行中的 Kafka 集群中进行认证协议升级以及开启鉴权。

参考文献

[1] https://www.automq.com/blog/automq-sasl-security-authentication-configuration-guide

[2] https://www.automq.com/blog/automq-ssl-security-protocol-configuration-tutorial

[3] https://developer.confluent.io/courses/security/authentication-basics/

[4] https://smallstep.com/hello-mtls/doc/server/kafka

[5] https://web.mit.edu/kerberos/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/968456.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

初阶数据结构:树---二叉树的链式结构

目录 一、二叉树的链式结构 (一)、概念 二、二叉树链式结构的实现 (一)、二叉树链式结构的遍历 1、前序遍历 2、中序遍历 3、后序遍历 4、层序遍历 (二)、二叉树的构建 (三&#xff0…

SurfGen爬虫:解析HTML与提取关键数据

一、SurfGen爬虫框架简介 SurfGen是一个基于Swift语言开发的爬虫框架,它提供了丰富的功能,包括网络请求、HTML解析、数据提取等。SurfGen的核心优势在于其简洁易用的API和高效的性能,使得开发者能够快速构建爬虫程序。以下是SurfGen的主要特…

pyrender 渲染报错解决

pyrender渲染后,出来的图样子不对: 正确的图: 解决方法: pip install numpy1.26 下面的不是必须的: pip install pyrender0.1.45 os.environ["PYOPENGL_PLATFORM"] "egl" os.environ[EGL_DEVI…

C++,STL容器,unordered_map/unordered_multimap:无序映射/无序多重映射深入解析

文章目录 一、容器概览与核心特性核心特性对比二、底层实现原理:哈希表架构1. 哈希表核心结构2. 动态扩容机制三、核心操作详解1. 容器初始化与配置2. 元素插入与更新3. 元素访问与查找4. 元素删除策略四、实战应用场景1. 缓存系统实现2. 分布式系统路由表五、性能优化策略1. …

Qt 控件整理 —— 按钮类

一、PushButton 1. 介绍 在Qt中最常见的就是按钮,它的继承关系如下: 2. 常用属性 3. 例子 我们之前写过一个例子,根据上下左右的按钮去操控一个按钮,当时只是做了一些比较粗糙的去演示信号和槽是这么连接的,这次我们…

python-leetcode 27.合并两个有序链表

题目: 将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4] 方法一:递归 函数在运行时调用自己,这个函数叫递归函数…

Unity中实现动态图集算法

在 Unity 中,动态图集(Dynamic Atlas)是一种在运行时将多个纹理合并成一个大纹理图集的技术,这样可以减少渲染时的纹理切换次数,提高渲染效率。 实现原理: 动态图集的核心思想是在运行时动态地将多个小纹理…

公然上线传销项目,Web3 的底线已经被无限突破

作者:Techub 热点速递 撰文:Yangz,Techub News 今天早些时候,OKX 将上线 PI 的消息在圈内引起轩然大波,对于上线被板上钉钉为传销盘子的「项目」 ,Techub News 联系了 OKX 公关,但对方拒绝置评…

元宵节快乐

早上吃的一碗小颗粒汤圆。 晚上做了三个小菜,一碗米饭和一杯饮料。 整理了Chrome浏览器收藏夹书签,删除了太多不需要的书签,重新分类,更加细化。 看到某博主推荐的5本书,下载这学期看看。点击此处下载 看来这段关系…

SAP系统常见的接口方式及特点介绍

【SAP系统研究】 在SAP系统中,接口主要用于系统间或系统与外部应用的数据交换和集成。以下是常见的接口方式及其特点: 一、IDoc方式 IDoc,Intermediate document,是SAP历史很悠久的接口技术,是一种系统间通用的数据交换媒介文件。IDoc基于XML的标准格式,常用于EDI、系…

【嵌入式Linux应用开发基础】open函数与close函数

目录 一、open函数 1.1. 函数原型 1.2 参数说明 1.3 返回值 1.4. 示例代码 二、close函数 2.1. 函数原型 2.2. 示例代码 三、关键注意事项 3.1. 资源管理与泄漏防范 3.2. 错误处理的严谨性 3.3. 标志(flags)与权限(mode&#xff…

LabVIEW国内外开发的区别

LabVIEW作为全球领先的图形化编程平台,在国内外工业测控领域均占据重要地位。本文从开发理念、技术生态、应用深度及自主可控性四个维度,对比分析国内外LabVIEW开发的差异,并结合国内实际应用场景,探讨其未来发展趋势。 ​ 一、开…

【大模型】阿里云百炼平台对接DeepSeek-R1大模型使用详解

目录 一、前言 二、DeepSeek简介 2.1 DeepSeek 是什么 2.2 DeepSeek R1特点 2.2.1 DeepSeek-R1创新点 2.3 DeepSeek R1应用场景 2.4 与其他大模型对比 三、阿里云百炼大平台介绍 3.1 阿里云百炼大平台是什么 3.2 阿里云百炼平台主要功能 3.2.1 应用场景 3.3 为什么选…

【DuodooBMS】给PDF附件加“受控”水印的完整Python实现

给PDF附件加“受控”水印的完整Python实现 功能需求 在实际工作中,许多文件需要添加水印以标识其状态,例如“受控”“机密”等。对于PDF文件,添加水印不仅可以增强文件的可识别性,还可以防止未经授权的使用。本代码的功能需求是…

linux的三剑客和进程处理

Linux三剑客: grep:查找 sed:编辑 awk:分析 grep - 正则表达式 [rootlocalhost ~]# grep ^a hello.txt abc grep - 忽略大小写,还有一些场景需要查询出来对应字符串所在的行号,方便我们快速在文件中定位字…

ASUS/华硕飞行堡垒9 FX506H FX706H 原厂Win10系统 工厂文件 带ASUS Recovery恢复

华硕工厂文件恢复系统 ,安装结束后带隐藏分区,带一键恢复,以及机器所有的驱动和软件。 支持型号:FX506HC, FX506HE, FX506HM, FX706HC, FX706HE, FX706HM, FX506HHR, FX706HMB, FX706HEB, FX706HCB, FX506HMB, FX506HEB, FX506HC…

13.StringTable

String的基本特性 String:字符串,使用一对 ”” 引起来表示 String s1 "mogublog" ; // 字面量的定义方式String s2 new String("moxi"); string声明为final的,不可被继承String实现了Serializable接口:表…

JavaSE基本知识补充 -Map集合

目录 Map(key,value键值对呈现) 1.1 Map的映射的特点 1. 2.HashMap (键值对的业务偏多,而且hashmap在jdk1.7和1.8之间有所不同,性能做了提升,面试高频考点) 1.3 Map接口的方法 方法 HashMap遍…

JAVA学习第二天

ArryList的构造方法和添加方法 01。构造方法的<>里面可以放数据类型 02. add&#xff08;&#xff09;可以直接在后面加入数据&#xff0c;也可以指定下标的插入元素。 ArrayList的常用方法 ArrayList存储对象 在Java中&#xff0c;System.out.println()可以打印基本数据…

基于窄带物联网的矿车追踪定位系统(论文+源码+实物)

1.功能设计 鉴于智能物联网的大趋势&#xff0c;本次基于窄带物联网的矿车追踪定位系统应具备以下功能&#xff1a; &#xff08;1&#xff09;实现实时定位&#xff0c;真正实现矿车随时随地定位; &#xff08;2&#xff09;定位精度高&#xff0c;采用该系统可以实现矿车在…