news 2026/9/10 12:43:06

Backstage 集成 OpenShift OAuth 认证提供者:从 OAuth 客户端配置到 Kubernetes 插件免密接入

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Backstage 集成 OpenShift OAuth 认证提供者:从 OAuth 客户端配置到 Kubernetes 插件免密接入

Backstage 集成 OpenShift OAuth 认证提供者:从 OAuth 客户端配置到 Kubernetes 插件免密接入

【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage

OpenShift 认证提供者是 Backstage 内置在core-plugin-api/frontend-plugin-api中的一套 OAuth 认证方案,它允许用户通过 OpenShift 集群的 OAuth 服务完成登录,并进一步利用用户身份访问 OpenShift/Kubernetes 集群资源。本文以仓库中的官方文档 docs/auth/openshift/provider.md 为主体,结合 plugins/auth-backend-module-openshift-provider 的源码实现,完整讲解 OAuth 客户端的创建、app-config.yaml配置、后端模块安装、前端KubernetesAuthProviders接线,以及底层认证器的工作原理。读完本文,你将能够在自己的 Backstage 应用中启用 OpenShift 登录,并让 Kubernetes 插件以"用户本人权限"(On-Behalf-Of)方式访问 OpenShift 集群。

使用场景:让 Kubernetes 插件使用用户自己的 OpenShift 权限

OpenShift 认证提供者的典型用途是与 Kubernetes 插件 联动:当用户通过 OpenShift OAuth 登录 Backstage 后,Kubernetes 插件可以利用 OAuth 2.0 的On-Behalf-Of(OBO)流程,通过 Kubernetes Client Side Provider 以该用户的身份和权限访问 OpenShift 集群,而不是以服务账号的统一身份访问。

在 docs/features/kubernetes/authentication.md 中可以看到,Kubernetes 插件的认证分为两类:

  • Server Side Providers(如awsazuregoogleServiceAccountserviceAccount):以应用整体身份访问集群,所有登录用户共享同一权限;
  • Client Side Providers(如aksgoogleoidc):以每个登录用户的身份访问集群,用户在集群中被授权到什么范围,就能看到什么资源。

OpenShift 的接入方式走的是 Client Side 路线:把 OpenShift 当作一个oidc客户端侧提供者接入KubernetesAuthProviders,从而让每个 Backstage 用户以其 OpenShift 账户身份访问集群。

要让这套流程成立,还需要满足一个前提:Backstage catalog 中必须存在对应的User实体,且实体名称与 OpenShift 用户名完全一致。这一点会在后面的displayNameMatchingUserEntityName登录解析器中再次体现。

前端接线:将 OpenShift 注册为 KubernetesAuthProviders 的 OIDC 提供者

虽然 OpenShift 认证提供者本身不原生支持 OIDC,但你可以在KubernetesAuthProviders配置中把它当作 OIDC 提供者来使用。仓库文档给出了packages/app/src/apis.ts中的标准写法:

import { KubernetesAuthProviders, kubernetesAuthProvidersApiRef, } from '@backstage/plugin-kubernetes'; import { googleAuthApiRef, microsoftAuthApiRef, openshiftAuthApiRef, } from '@backstage/core-plugin-api'; export const apis: AnyApiFactory[] = [ // ... createApiFactory({ api: kubernetesAuthProvidersApiRef, deps: { microsoftAuthApi: microsoftAuthApiRef, googleAuthApi: googleAuthApiRef, openshiftAuthApi: openshiftAuthApiRef, }, factory({ microsoftAuthApi, googleAuthApi, openshiftAuthApi }) { return new KubernetesAuthProviders({ microsoftAuthApi, googleAuthApi, oidcProviders: { openshift: { async getIdToken(_) { return await openshiftAuthApi.getAccessToken('user:full'); }, }, }, }); }, }), //... ];

其中openshiftAuthApiRef定义在@backstage/core-plugin-api中,并从 packages/core-plugin-api/src/apis/definitions/auth.ts 导出。

需要特别强调一个容易被忽视的差异(原文档中的 note):

OpenShift 认证 API不实现OpenIdConnectApi接口,也就是说它不返回 ID token。它返回的是access token,Kubernetes 集成会将这个 access token 当作 ID token 使用。这是它与标准 OIDC 认证流程唯一的功能性区别。

因此在上面的getIdToken(_)中,实际调用的是openshiftAuthApi.getAccessToken('user:full'),请求的 scope 必须是user:full(这一点在源码的 scopes 定义中也被强制要求,见下文)。

在 OpenShift 中创建 OAuth 客户端

在开始配置 Backstage 之前,请确认 OpenShift 集群中存在可用的 OAuth 客户端。OpenShift 的配置方式是创建一个OAuthClient自定义资源。

创建时必须设置回调地址(redirect URI),格式如下:

https://<fqdn>/api/auth/openshift/handler/frame

其中<fqdn>是你的 Backstage 应用对外暴露的域名,路径/api/auth/openshift/handler/frame由认证提供者的回调处理器约定,不能随意更改。改好域名后,OAuth 授权码流程的回调就会落在 Backstage 后端的 OpenShift 处理器上。

应用配置:app-config.yaml 中的 provider 配置

将 provider 配置添加到app-config.yaml根级auth配置下:

auth: environment: development providers: openshift: development: clientId: ${AUTH_OPENSHIFT_CLIENT_ID} clientSecret: ${AUTH_OPENSHIFT_CLIENT_SECRET} authorizationUrl: ${AUTH_OPENSHIFT_AUTHORIZATION_URL} tokenUrl: ${AUTH_OPENSHIFT_TOKEN_URL} openshiftApiServerUrl: ${OPENSHIFT_API_SERVER_URL} ## uncomment to set lifespan of user session # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code # sessionDuration: 1d signIn: resolvers: - resolver: displayNameMatchingUserEntityName

OpenShift provider 是一个包含以下配置键的结构:

配置键说明格式示例
clientIdOpenShift OAuth 客户端的 Client IDmy-backstage
clientSecret与该 OAuth 客户端绑定的 Client Secret从环境变量注入
authorizationUrlOpenShift OAuth 客户端授权端点https://<oauth-client-route>/oauth/authorize
tokenUrlOpenShift OAuth 客户端令牌端点https://<oauth-client-route>/oauth/token
openshiftApiServerUrlOpenShift API 服务器端点https://<openshift-api>
sessionDuration(可选)用户会话的存活时长支持ms库格式(如'24h''2 days')、ISO 时长、代码中使用的 "human duration"
signIn登录流程配置,含用于将认证提供者用户与 Backstage catalog 中用户实体匹配的resolvers(通常一个 resolver 就足够)见下方说明

这些键的类型约束在 plugins/auth-backend-module-openshift-provider/config.d.ts 中有精确声明:

  • clientIdauthorizationUrltokenUrlopenshiftApiServerUrl均为必填字符串;
  • clientSecret标记为@visibility secret,应从环境变量注入,避免明文入库;
  • callbackUrl为可选字段(未配置时由提供者根据运行时环境推导);
  • signIn.resolvers目前仅支持displayNameMatchingUserEntityName,可附带布尔选项dangerouslyAllowSignInWithoutUserInCatalog
  • sessionDuration的类型为HumanDuration | string

关于 scope 的强制要求

OpenShift provider 需要使用的 scope 为user:full。这不仅是前端调用getAccessToken('user:full')的约定,在底层认证器createOAuthAuthenticator的声明中也被固化为必选 scope,见 plugins/auth-backend-module-openshift-provider/src/authenticator.ts:

scopes: { required: ['user:full'], },

后端安装:注册 auth-backend 模块

OpenShift 认证提供者的后端实现位于独立的 npm 包@backstage/plugin-auth-backend-module-openshift-provider中。在 Backstage 根目录执行:

yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-openshift-provider

然后在packages/backend/src/index.ts中注册该模块:

backend.add(import('@backstage/plugin-auth-backend')); /* highlight-add-start */ backend.add(import('@backstage/plugin-auth-backend-module-openshift-provider')); /* highlight-add-end */

该模块在源码层面通过新后端系统注册为auth插件的子模块,plugins/auth-backend-module-openshift-provider/src/module.ts 中的createBackendModuleopenshiftprovider 注册到authProvidersExtensionPoint,并把认证器与登录解析器工厂组装为createOAuthProviderFactory

源码剖析:认证器如何与 OpenShift API 交互

OpenShift 认证器基于passport-oauth2实现标准 OAuth 2.0 授权码流程,其核心逻辑全部位于 plugins/auth-backend-module-openshift-provider/src/authenticator.ts。以下要点可以帮助你理解它的底层行为。

用户资料通过 user.openshift.io API 获取

初始化时,认证器读取clientIdclientSecretauthorizationUrltokenUrlopenshiftApiServerUrl五个必填配置,构造OAuth2Strategy。其中自定义的userProfile方法会携带 access token 请求 OpenShift API:

GET {openshiftApiServerUrl}/apis/user.openshift.io/v1/users/~

返回体按照user.openshift.io/v1User结构用 zod 校验(见 authenticator.ts),并把metadata.name作为displayName提供给上层——这正是"catalog 中 User 实体名必须与 OpenShift 用户名一致"这一前提的来源。

启动、认证与刷新流程

  • start:跳转到授权端点,附加accessType: 'offline'prompt: 'consent'参数;
  • authenticate:完成授权码交换后,将refreshToken覆盖为 access token、刷新有效期对齐 access token 的expiresInSeconds——这是针对 OpenShift OAuth 不签发独立刷新令牌的变通处理;
  • refresh:由于登录时刷新令牌实际就是 access token,此处直接用refreshToken作为 access token 重新拉取用户资料,遇到 401 则抛出 "Invalid access token";
  • logout:登出时会先校验 token 是否仍有效,若有效则根据oauth.openshift.io/v1OAuthAccessToken命名规则,对 token 去掉sha256~前缀后做 SHA-256 并 Base64URL 编码得到 token 名,再调用:
DELETE {openshiftApiServerUrl}/apis/oauth.openshift.io/v1/oauthaccesstokens/sha256~{tokenName}

从而在 OpenShift 侧真正吊销该访问令牌(返回 401 则抛出unauthorized)。

登录解析器:将 OpenShift 用户匹配到 catalog 中的 User 实体

signIn.resolvers中使用的displayNameMatchingUserEntityName由模块自带的解析器工厂实现,见 plugins/auth-backend-module-openshift-provider/src/resolvers.ts。其行为如下:

  • 从认证结果 profile 中取出displayName(即 OpenShift 用户名),缺少时抛出 "OpenShift user profile does not contain a displayName";
  • stringifyEntityRef构造kind: Usernamespace: defaultname: displayName的实体引用;
  • 调用ctx.signInWithCatalogUser完成 catalog 登录。

配套的可选参数dangerouslyAllowSignInWithoutUserInCatalog若置为true,当 catalog 中不存在对应用户实体时,会降级使用仅含用户名的entityRef回退登录,适用于尚未完成目录同步的过渡环境。因此,最稳妥的实践仍然是:确保 Backstage catalog 中存在与 OpenShift 用户同名(default命名空间下)的User实体,这样登录与 Kubernetes 插件按用户授权访问才能闭环。

完整落地检查清单

  1. 在 OpenShift 集群创建OAuthClient,回调地址为https://<fqdn>/api/auth/openshift/handler/frame
  2. clientIdclientSecretauthorizationUrltokenUrlopenshiftApiServerUrl通过环境变量注入app-config.yamlauth.providers.openshift.<env>
  3. 按需设置sessionDuration(如{ hours: 24 }1d),并配置signIn.resolversdisplayNameMatchingUserEntityName
  4. 执行yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-openshift-provider,并在packages/backend/src/index.ts注册模块;
  5. packages/app/src/apis.ts中把openshiftAuthApiRef接入KubernetesAuthProvidersoidcProviders,scope 固定为user:full
  6. 确保 catalog 中存在与 OpenShift 用户名一致的User实体(default命名空间);
  7. 重启前后端后,使用 OpenShift 账户登录,并在 Kubernetes 插件的集群配置中将authProvider指向oidc类型的客户端侧提供者(对应 OpenShift 集群)。

按上述步骤完成后,用户即可用自己的 OpenShift 身份访问集群资源,而无需在 Backstage 中为 Kubernetes 插件配置任何服务账号或静态凭据。

【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 12:42:53

OpenCore Legacy Patcher免费完整指南:老Mac装最新macOS,一天搞定

OpenCore Legacy Patcher免费完整指南&#xff1a;老Mac装最新macOS&#xff0c;一天搞定 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你那台停更多年的老…

作者头像 李华
网站建设 2026/9/10 12:41:44

TaskMaster Autonomous Workflow

TaskMaster Autonomous Workflow 【免费下载链接】claude-task-master An AI-powered task-management system you can drop into Cursor, Lovable, Windsurf, Roo, and others. 项目地址: https://gitcode.com/GitHub_Trending/cl/claude-task-master When working on …

作者头像 李华
网站建设 2026/9/10 12:40:44

STM32与GPS/北斗模块:NMEA解析与DMA双缓冲TFT显示实战

简介&#xff1a;面向STM32开发者&#xff0c;这份DEMO例程源码演示了如何读写ATGM336H(GPS)模块并驱动3.5寸TFT液晶实时显示定位信息。代码基于HAL库&#xff0c;完整覆盖NMEA协议解码、UTC转北京时间、经纬度格式换算等关键环节&#xff0c;并采用DMA中断方式接收串口数据&am…

作者头像 李华
网站建设 2026/9/10 12:38:20

Cal.diy 部署在反向代理后面出现 SSL 证书错误怎么排查?

Cal.diy 部署在反向代理后面出现 SSL 证书错误怎么排查&#xff1f; 【免费下载链接】cal.diy Scheduling infrastructure for absolutely everyone. 项目地址: https://gitcode.com/GitHub_Trending/ca/cal.diy 当你把 Cal.diy&#xff08;一个自托管的日程安排应用&am…

作者头像 李华