首页 > 其他分享 >升级到 Pulsar3.0 后深入了解 JWT 鉴权

升级到 Pulsar3.0 后深入了解 JWT 鉴权

时间:2023-11-20 09:23:06浏览次数:50  
标签:admin JWT broker token Pulsar3.0 key 鉴权 proxy

背景

最近在测试将 Pulsar 2.11.2 升级到 3.0.1的过程中碰到一个鉴权问题,正好借着这个问题充分了解下 Pulsar 的鉴权机制是如何运转的。

Pulsar 支持 Namespace/Topic 级别的鉴权,在生产环境中往往会使用 topic 级别的鉴权,从而防止消息泄露或者其他因为权限管控不严格而导致的问题。

image.png

我们会在创建 topic 的时候为 topic 绑定一个应用,这样就只能由这个应用发送消息,其他的应用尝试发送消息的时候会遇到 401 鉴权的异常。

同理,对于订阅者也可以关联指定的应用,从而使得只有规定的应用可以消费消息。

鉴权流程

以上的两个功能本质上都是通过 Pulsaradmin-API 实现的。

image.png
这里关键的就是 role,在我们的场景下通常是一个应用的 AppId,只要是一个和项目唯一绑定的 ID 即可。

这只是授权的一步,整个鉴权流程图如下:

详细步骤

生成公私钥

bin/pulsar tokens create-key-pair --output-private-key my-private.key --output-public-key my-public.key

将公钥分发到 broker 的节点上,鉴权的时候 broker 会使用公钥进行验证。

而私钥通常是管理员单独保存起来用于在后续的步骤为客户端生成 token

使用私钥生成 token

之后我们便可以使用这个私钥生成 token 了:

bin/pulsar tokens create --private-key file:///path/to/my-private.key \
            --subject 123456

eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbiJ9

其中的 subject 和本文长提到的 role 相等

使用 subject 授权

只是单纯生成了 token 其实并没有什么作用,还得将 subject(role) 与 topic 进行授权绑定。

image.png
也就是上图的这个步骤。

这里创建的 admin 客户端也得使用一个 superRole 角色的 token 才有权限进行授权。
superRole 使用在 broker.conf 中进行配置。

客户端使用 token 接入 broker

PulsarClient client = PulsarClient.builder()
    .serviceUrl("pulsar://broker.example.com:6650/")
    .authentication(AuthenticationFactory.token("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.ipevRNuRP6HflG8cFKnmUPtypruRC4fb1DWtoLL62SY"))
    .build();

使用刚才私钥生成的 token 接入 broker 才能生产或者消费数据。

originalPrincipal cannot be a proxy role

这些流程正常都没啥问题,但直到我升级了 Pulsar3.0 后客户端直接就连不上了。

broker 中看到了 WARN 的警告日志:

cannot specify originalPrincipal when connecting without valid proxy role

image.png
之后在 3.0 的升级日志中看到相关的 Issue

从这个 PR 相关的代码和变更的文档可以得知:
image.png
image.png

升级到 3.0 之后风险校验等级提高了,proxyRole 这个字段需要在 broker 中进行指定(之前的版本不需要强制填写)。

因为我们使用了 Proxy 组件,所有的请求都需要从 proxy 中转一次,这个 proxyRole 是为了告诉 broker:只有使用了 proxyRole 作为 tokenProxy 才能访问 broker,这样保证了 broker 的安全。

superUserRoles: broker-admin,admin,proxy-admin 
proxyRoles: proxy-admin

以上是我的配置,我的 Proxy 配置的也是 proxy-admin 这个 token,所以理论上是没有问题的,但依然鉴权失败了,查看 broker 的日志后拿到以下日志:

Illegal combination of role [proxy-admin] and originalPrincipal [proxy-admin]: originalPrincipal cannot be a proxy role.

排查了许久依然没有太多头绪,所以我提了相关的 issue:
https://github.com/apache/pulsar/issues/21583
之后我咨询了 Pulsar 的 PMC @Technoboy 在他的提示下发现我在测试的时候使用的是 proxy-admin,正好和 proxyRoles 相等。
image.png
阅读源码和这个 PRcomment 之后得知:
image.png
也就是说客户端不能使用和 proxyRole 相同的角色进行连接,这个角色应当也只能给 Proxy 使用,这样的安全性才会高。

所以这个 Comment 还在讨论这是一个 breaking change? 还是一个增强补丁。
因为合并这个 PR 后对没有使用 proxyRole 的客户端将无法连接,同时也可能出现我这种 proxyRole 就是客户端使用的角色,这种情况也会鉴权失败。

所以我换了一个 superRole 角色就可以了,比如换成了 admin

但其实即便是放到我们的生产系统,只要配置了 proxyRole 也不会有问题,因为我们应用所使用的 role 都是不这里的 superUserRole,全部都是使用 AppId 生成的。

token 不一致

但也有一个疑惑,我在换为存放在 configmap 中的 admin token 之前(测试环境使用的是 helm 安装集群,所以这些 token 都是存放在 configmap 中的),

为了验证是否只要非 proxyRolesuperRole 都可以使用,我就自己使用了私钥重新生成了一个 admintoken

bin/pulsar tokens create --private-key file:///pulsar/private/private.key --subject admin

这样生成的 token 也是可以使用的,但是我将 token 复制出来之后却发现 helm 生成的 token 与我用 pulsar 命令行生成的 token 并不相同。

为了搞清楚为什么 token 不同但鉴权依然可以通过的原因,之后我将 token decode之后知道了原因:
image.png
image.png
原来是 Header 不同从而导致最终的 token 不同,helm 生成的 token 中多了一个 typ 字段。


之后我检查了 helm 安装的流程,发现原来 helm 的脚本中使用的并不是 Java 的命令行工具:

${PULSARCTL_BIN} token create -a RS256 --private-key-file ${privatekeytmpfile} --subject ${role} 2&> ${tokentmpfile}

这个 PULSARCTL_BIN 是一个由 Go 写的命令行工具,我查看了其中的源码,才知道 Go 的 JWT 工具会自带一个 header。
https://github.com/streamnative/pulsarctl

image.png
Java 是没有这个逻辑的,但也只是加了 headerpayload 的值都是相同的。
这样也就解释了为什么 token 不同但确依然能使用的原因。

标签:admin,JWT,broker,token,Pulsar3.0,key,鉴权,proxy
From: https://www.cnblogs.com/crossoverJie/p/17843188.html

相关文章

  • springboot 集成jwt 登录 拦截器获取token 解析token放入holder中
    一、依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency>......
  • 为什么要用JWT,JWT与Seeion区别
    一、为什么使用JWTHTTP是无状态的,开发人员需要基于HTTP来模拟实现状态的保存。经典的实现用户登录的做法是用Session,用户登录验证成功后,服务端生成SessionId。服务端会将SessionId与登录的用户信息的对应关系保存在服务器内存中,同时将SessionId返回给浏览器端,sessionId一般存储在......
  • SpringCloud系列八之微服务网关安全认证-JWT篇
    Gateway-JWT认证鉴权流程一、网关认证件鉴权流程目前主流的结合微服务网关及JWT令牌开发用户认证及服务访问鉴权的流程如下:用户认证流程:用户向网关发送登录认证请求,网关将请求转发给认证服务。认证服务校验用户登录信息(用户密码、短信及图片验证码)等信息之后,如果校验成功颁发一......
  • Spring Cloud Gateway实现鉴权认证流程总结(一)
    认证、授权、凭证1.1认证(Authentication)认证表示你是谁。系统如何正确分辨出操作用户的真实身份,比如通过输入用户名和密码来辨别身份。1.2授权(Authorization)授权表示你能干什么。系统如何控制一个用户能看到哪些数据和操作哪些功能,也就是具有哪些权限。1.3凭证(Credential)表示你......
  • Spring Cloud Gateway实现鉴权认证流程总结(二)
    微服务认证方案微服务认证方案目前有很多种,每个企业也是大不相同,但是总体分为两类,如下:网关只负责转发请求,认证鉴权交给每个微服务商控制统一在网关层面认证鉴权,微服务只负责业务你们公司目前用的是哪种方案?先来说说第一种方案,有着很大的弊端,如下:代码耦合严重,每个微服务都要......
  • 使用JWT、拦截器与ThreadLocal实现在任意位置获取Token中的信息,并结合自定义注解实现
    1.简介1.1JWTJWT,即JSONWebToken,是一种用于在网络上传递声明的开放标准(RFC7519)。JWT可以在用户和服务器之间传递安全可靠的信息,通常用于身份验证和信息交换。声明(Claims):JWT包含一组称为声明的信息,声明描述了一些数据。有三种类型的声明:注册声明(RegisteredClaims):这是......
  • JWT浅了解
    JWT通过数字签名的方式(让我想起了软考),以json对象为载体,在不同的服务终端之间安全传输信息是一种授权认证生成token的原理:通过header的加密方式,对payload进行加密。然后把header和payload再次加密生成signature贴一下我的settokenreturnJWT.create().withAudience(userId)//......
  • identityserver,OAuth2.0,JWT之间的关系
    OAuth2.0是一种授权框架,用于应用程序之间安全的共享用户资源,它允许用户授权第三方应用程序访问他们的资源,列如照片,视频,联系人列表等,而不必将用户名和密码提供给第三方应用程序,OAuth2.0通过令牌来代表用户授权,这些令牌可以被第三方应用程序用于访问用户资源,而不必知道用户的凭据。O......
  • HDFS基于Ranger鉴权原理
    1.背景在HDFS中,默认是通过setacl和getacl命令的方式增加和查询hdfs的acl信息。为了了解acl信息,需要亲自登陆机器执行hdfs命令,对于没有机器权限的业务人员非常不友好;同时,运维人员无法浏览HDFS所有acl信息,对于管理来说也不透明。为了解决该问题,引入了Ranger组件,将acl信息存放到Ran......
  • .Net Core之JWT授权
    一、什么是JWT文章参考:https://www.leo96.com/article/detail/55JSONWeb令牌(JWT)是一个开放标准(RFC7519),它定义 了一种紧凑且自包含的方式,用于在各方之间安全地传输信息作为JSON对象。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用秘密(使用HMAC算法)或使用RSA或EC......