Backstage 集成 OpenShift OAuth 认证提供者从 OAuth 客户端配置到 Kubernetes 插件免密接入【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstageOpenShift 认证提供者是 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-OfOBO流程通过 Kubernetes Client Side Provider 以该用户的身份和权限访问 OpenShift 集群而不是以服务账号的统一身份访问。在 docs/features/kubernetes/authentication.md 中可以看到Kubernetes 插件的认证分为两类Server Side Providers如aws、azure、googleServiceAccount、serviceAccount以应用整体身份访问集群所有登录用户共享同一权限Client Side Providers如aks、google、oidc以每个登录用户的身份访问集群用户在集群中被授权到什么范围就能看到什么资源。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 导出。需要特别强调一个容易被忽视的差异原文档中的 noteOpenShift 认证 API不实现OpenIdConnectApi接口也就是说它不返回 ID token。它返回的是access tokenKubernetes 集成会将这个 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: displayNameMatchingUserEntityNameOpenShift provider 是一个包含以下配置键的结构配置键说明格式示例clientIdOpenShift OAuth 客户端的 Client IDmy-backstageclientSecret与该 OAuth 客户端绑定的 Client Secret从环境变量注入authorizationUrlOpenShift OAuth 客户端授权端点https://oauth-client-route/oauth/authorizetokenUrlOpenShift OAuth 客户端令牌端点https://oauth-client-route/oauth/tokenopenshiftApiServerUrlOpenShift API 服务器端点https://openshift-apisessionDuration可选用户会话的存活时长支持ms库格式如24h、2 days、ISO 时长、代码中使用的 human durationsignIn登录流程配置含用于将认证提供者用户与 Backstage catalog 中用户实体匹配的resolvers通常一个 resolver 就足够见下方说明这些键的类型约束在 plugins/auth-backend-module-openshift-provider/config.d.ts 中有精确声明clientId、authorizationUrl、tokenUrl、openshiftApiServerUrl均为必填字符串clientSecret标记为visibility secret应从环境变量注入避免明文入库callbackUrl为可选字段未配置时由提供者根据运行时环境推导signIn.resolvers目前仅支持displayNameMatchingUserEntityName可附带布尔选项dangerouslyAllowSignInWithoutUserInCatalogsessionDuration的类型为HumanDuration | string。关于 scope 的强制要求OpenShift provider 需要使用的 scope 为user:full。这不仅是前端调用getAccessToken(user:full)的约定在底层认证器createOAuthAuthenticator的声明中也被固化为必选 scope见 plugins/auth-backend-module-openshift-provider/src/authenticator.tsscopes: { 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 中的createBackendModule将openshiftprovider 注册到authProvidersExtensionPoint并把认证器与登录解析器工厂组装为createOAuthProviderFactory。源码剖析认证器如何与 OpenShift API 交互OpenShift 认证器基于passport-oauth2实现标准 OAuth 2.0 授权码流程其核心逻辑全部位于 plugins/auth-backend-module-openshift-provider/src/authenticator.ts。以下要点可以帮助你理解它的底层行为。用户资料通过 user.openshift.io API 获取初始化时认证器读取clientId、clientSecret、authorizationUrl、tokenUrl和openshiftApiServerUrl五个必填配置构造OAuth2Strategy。其中自定义的userProfile方法会携带 access token 请求 OpenShift APIGET {openshiftApiServerUrl}/apis/user.openshift.io/v1/users/~返回体按照user.openshift.io/v1的User结构用 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 tokenlogout登出时会先校验 token 是否仍有效若有效则根据oauth.openshift.io/v1的OAuthAccessToken命名规则对 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: User、namespace: default、name: displayName的实体引用调用ctx.signInWithCatalogUser完成 catalog 登录。配套的可选参数dangerouslyAllowSignInWithoutUserInCatalog若置为true当 catalog 中不存在对应用户实体时会降级使用仅含用户名的entityRef回退登录适用于尚未完成目录同步的过渡环境。因此最稳妥的实践仍然是确保 Backstage catalog 中存在与 OpenShift 用户同名default命名空间下的User实体这样登录与 Kubernetes 插件按用户授权访问才能闭环。完整落地检查清单在 OpenShift 集群创建OAuthClient回调地址为https://fqdn/api/auth/openshift/handler/frame将clientId、clientSecret、authorizationUrl、tokenUrl、openshiftApiServerUrl通过环境变量注入app-config.yaml的auth.providers.openshift.env按需设置sessionDuration如{ hours: 24 }或1d并配置signIn.resolvers为displayNameMatchingUserEntityName执行yarn --cwd packages/backend add backstage/plugin-auth-backend-module-openshift-provider并在packages/backend/src/index.ts注册模块在packages/app/src/apis.ts中把openshiftAuthApiRef接入KubernetesAuthProviders的oidcProvidersscope 固定为user:full确保 catalog 中存在与 OpenShift 用户名一致的User实体default命名空间重启前后端后使用 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),仅供参考