基于 K8S 部署 Backstage,集成 oauth2-proxy 和 Keycloak,实现用户管理、认证和授权,配置详解和原理介绍。
如果你遇到以下问题或诉求,可以参考此文档。
- Backstage 接入 oauth2-proxy,登录或认证失败。
- Backstage 实现 RBAC、ABAC 授权管理,以及如何实现自定义权限。
- oauth2-proxy 对接 keycloak,参数不理解或者配置一直错误。
在开始之前,我们先了解一个点,Backstage 官方开源有开箱即用的容器镜像,也有丰富的插件生态,然而区别于其他插件类应用,Backstage 有自己的特点:
Backstage 插件分为 frontend 和 backend,一个完整的插件可能包含两种,也可能只包含其中一种。
开源发布的开箱即用的容器镜像,只包含基础插件,一般只用来作为初次学习使用。
如果想使用其他插件,需要做一些编码工作,一般步骤如下。
- 使用
npx @backstage/create-app@latest
创建一个基础项目。 - 按插件要求安装插件,配置插件菜单、UI 效果、权限、认证信息等,每个插件要求不同。
- 按需开发自己的插件。
- 编译成新容器镜像,某些插件可能还需要在容器中额外安装一些依赖包,部署时使用此容器镜像。
- 使用
基本上每个插件都有自己的配置要求,需根据插件文档配置 app-config.yaml。
可以把 Backstage 类比于 Spring Boot,提供了 starter、framework、plugins,如果想真实使用,需要自己引入依赖,编译成自己的镜像发布部署,欢迎 star 我们基于 Backstage 定制的开源项目 xlabs-developer-platform 。
核心组件介绍:
- 用户同步使用 Red Hat 贡献的社区开源插件 @backstage-community/plugin-catalog-backend-module-keycloak ,将 keycloak 用户同步到 Backstage 数据库,后面我们会提到为什么需要这一步。
- 认证使用官方内置的 OAuth 2 Proxy Provider .
- 授权,权限管理 Permissions,支持 RBAC、ABAC, 使用 Red Hat 贡献的社区开源插件 @backstage-community/plugin-rbac ,虽然插件名字叫 RBAC,但是实际上支持 ABAC。注意 Spotify 也有 RBAC 插件 需要购买 License 才能用,两个插件别弄混了。
以上认证和授权是独立的,如果你只需要认证,不需要授权,那可以不需要 RBAC 插件。
整体架构流程图:
安装部署配置详解和原理分析
在开始之前,我们先特别注意几个比较容易踩坑的点:
- Backstage OAuth 2 Proxy Provider 除了进行用户登录认证外,还会校验用户是否已经存在,如果不存在会返回错误,所以我们需要使用
@backstage-community/plugin-catalog-backend-module-keycloak
插件,先将用户同步到 backstage 里。 - Backstage 的
Sign In resolver
依赖 oauth2-proxy 传递的 http header,所以我们把 backstage 作为 oauth2-proxy 的 upstream,网络流量是 User -> oauth2-proxy -> Backstage。下面我们会单独说明依赖哪些 Header。 - oauth2-proxy 以 email 作为用户校验和识别,所以尽量为用户设置 email,否则后续会有很多额外配置和开发工作。等报错了就知道怎么解决了,能解决,只是带来额外的工作。
下面的安装部署配置,都在我们的部署脚本 xlabs-ops 源码里,可供参考,方便复制粘贴。
Keycloak 配置准备
Keycloak 需要准备两对 client id 和 client secret,都是 OpenID Connect
, 分别给 Backstage @backstage-community/plugin-catalog-backend-module-keycloak
插件同步用户用, 和 oauth2-proxy 登录认证使用。如果你想省事,也可以把两个 client 合并成一个。
给 Backstage 同步用户使用,假设 id 叫
backstage
,需要在 keycloak 开启Authorization
,并在Service Account Roles
授权查询 users 和 groups 的权限。他的作用就是通过 keycloak 的 api 将 users 和 groups 同步到 backstage,如果没有权限,在 backstage 的日志里应该能看到一些相应的错误信息。给 oauth2-proxy 登录认证用,假设 id 叫
oauth2-proxy
, 需要在 keycloak 设置Valid redirect URIs
为你 backstage 的回调地址,支持通配符,比如https://backstage.nxest.com/*
,并设置Audience
和Groups
scope, 否则登录失败。具体设置 scope 方式请参考官方文档 oauth2-proxy-keycloak-oidc 和我的另外一遍博客 traefik-oauth2-proxy-keycloak 。
oauth2-proxy 配置
oauth2-proxy 也有很多部署方式,以 K8S 内部署 bitnami/oauth2-proxy
helm chart 为例,核心配置参考如下。
注意这里几个特别关键的配置:
- 将
<%= keycloakBaseUrl %>
替换为你的 keycloak 真实 URL 地址,设置为对外地址,比如 ingress 的域名。 - devops 是我自定义的 realm 名字,请根据你自己实际的情况设置,keycloak 默认的 realm 是 master。
- upstreams:设置为 backstage 的服务地址。我这里设置的是 backstage 的 k8s service 地址,因为 oauth2-proxy 和 Backstage 都在 K8S 集群内,能通即可。
- cookie_refresh : 设置为 Keycloak Access-Token lifespan - 1m
- cookie_expire : 设置为 Keycloak Refresh-Token lifespan (Keycloak client_session_idle)
- skip_auth_routes 对某些 url 不做认证,可写可不写,看你爱好。
关于 keycloak token 过期时间的配置,可以参考 keycloak 官方文档或 IDaaS Book 。
Backstage 配置
Backstage 需要编码,引入 Keycloak 和 RBAC 插件,修改导航栏菜单,然后才是配置文件。这部分并没有什么难度,参考插件说明即可完成,注意请根据插件的最新版本说明配置,这里提到的一切都可能过时,Backstage 变化实在是太大了。
Backstage 我们区分认证和授权两部分,两部分可独立配置,但是都依赖用户同步,所以先把用户同步到 Backstage 数据库。
用户同步
官方英文最新文档请参考 catalog-backend-module-keycloak ,请根据最新文档操作。
基本步骤:
安装插件依赖。
在 backstage 注册插件,backstage 工程
packages/backend/src/index.ts
增加以下代码。配置插件同步需要的 client id 和 client secret,同步周期,在 backstage 的 app-config.yaml 增加以下片段。
以上配置完成后,观察下 backstage 的运行日志,成功的话会有同步了多少个 user 和 group 的日志,失败的话会有失败原因,确保同步成功。
用户认证
官方英文最新文档请参考 OAuth 2 Proxy Provider ,请根据最新文档操作。
基本步骤:
安装 backstage 后端插件依赖。
配置 backstage 后端代码,启用插件,在
packages/backend/src/index.ts
增加以下代码。配置 oauth2Proxy 认证组件需要的参数,在 backstage 的 app-config.yaml 增加以下片段。
改前端代码,修改登录页面,使用 oauth2Proxy 的登录组件,参考 官方文档 . 在
packages/app/src/App.tsx
找到SignInPage
修改为如下片段,当然,你可以根据自己的环境定制更多自己的登录页面。
上面我们使用了 backstage 的 resolvers forwardedUserMatchingUserEntityName
, 他就是从 Http Header 中获取 oauth2-proxy 传递过来的 x-forwarded-user
值与数据库比对,找到用户信息。
oauth2-proxy 传递到 upstream 的常用 header 有:
至此,登录认证已经可以了。
用户授权
RBAC 授权插件有前端和后端两个插件。
先安装 backend 后端插件,基本步骤:
安装 backstage 后端插件依赖。
配置 backstage 后端代码,启用插件,在
packages/backend/src/index.ts
补充以下代码。配置 RBAC 插件用户权限,在 backstage 的 app-config.yaml 增加以下片段。
再安装 frontend 前端插件,把 RBAC 管理界面放出来,基本步骤:
安装 backstage 前端插件依赖。
配置 backstage 前端代码,在
packages/app/src/App.tsx
补充以下代码,增加 Route。配置导航菜单,修改
packages/app/src/components/Root/Root.tsx
。
至此,用以上配置有权限的用户登录,就可以访问 RBAC 管理界面了。根据 权限管理文档 开启自定义权限之旅吧。