Skip to main content

服务对服务授权

本文介绍了介绍服务对服务授权(原_backend-to-backend_这样,插件后端就可以通过要求使用共享Secret签名的特殊类型服务对服务令牌,来确定给定请求是否来自合法的 backstage 插件(或其他外部调用者)。

在您的 Backstage 后端插件(例如目录)上启用这种保护后,生态系统中的其他调用者(例如搜索索引器和 scaffolder)需要向目录出示有效令牌才能请求目录内容。

设置

在新创建的 Backstage 应用程序中,后端设置为完全不需要任何身份验证。 这意味着生成的服务对服务令牌是空的,传入的请求也不会被验证。 如果您想启用服务对服务身份验证,第一步是在后端设置中调换以下一行,位置如下packages/backend/src/index.ts:

packages/backend/src/index.ts
const tokenManager = ServerTokenManager.noop();
const tokenManager = ServerTokenManager.fromConfig(config, { logger: root });

通过将无操作ServiceTokenManager转换为从 config 中创建的密钥后,您就可以为任何实现该功能的插件启用服务对服务身份验证。 本地开发设置一般不会受此影响,因为临时密钥是在引擎盖下生成的。 但对于生产设置,这意味着您现在必须提供一个共享Secret,使您的后端插件能够相互通信。

目前,后端服务对服务令牌总是使用单个Secret密钥签名。 它需要在所有后端插件和服务之间共享,以便进行跨服务通信。 密钥可以是任何 base64 编码的Secret。 可以使用以下命令在终端生成这样的密钥:

node -p 'require("crypto").randomBytes(24).toString("base64")'

然后将其放在后端配置中,可以直接作为值,也可以作为 env 变量注入。

# commonly in your app-config.production.yaml
backend:
auth:
keys:
- secret: <the string returned by the above crypto command>
# - secret: ${BACKEND_SECRET} - if you want to use an env variable instead

注意:为了便于开发,如果您没有在开发模式下配置Secret,我们会自动为您生成密钥。 您可以必须设定自己的秘密为了使服务对服务的认证在生产中正常运行,必须使用ServiceTokenManager如果没有可使用的密钥,就会在生产过程中出现异常,导致后端无法启动。

后端插件中的用法

如果您想在自己的后端插件中使用服务对服务身份验证,需要几个步骤。 首先,您需要在后端插件中添加TokenManagercreateRouter选项。tokenManager: TokenManager与此同时,您需要要求用户在后端设置代码中开始提供这一新的依赖关系。

一旦TokenManager的情况下,您可以使用.getToken()方法生成一个新的令牌,用于向其他 backstage 后端插件发出请求。 每次发出请求时都应调用该方法;请勿将令牌存储起来以备后用。TokenManager实现应该已经根据需要缓存了令牌。 然后,返回的令牌应该作为Bearer例如,上游请求的令牌:

const { token } = await this.tokenManager.getToken();

const response = await fetch(pluginBackendApiUrl, {
method: 'GET',
headers: {
...headers,
Authorization: `Bearer ${token}`,
},
});

要对接收到的请求进行身份验证,可以使用.authenticate(token)在撰写本文时,该方法并不返回任何内容,如果令牌无效,它将直接抛出。

await tokenManager.authenticate(token); // throws if token is invalid

外部来电的使用情况

如果启用了服务器到服务器 auth,您可能会对在 backstage 自身外部的代码中生成令牌感兴趣。 外部调用程序甚至可能是用 Node.js 之外的其他语言编写的。 本节将介绍如何自行生成有效令牌。

令牌必须是带有HS256它还必须包含以下有效载荷:

  • sub":"backstage-server"(目前只支持该值) * `exp":从生成时间算起的一小时,以纪元秒为单位

注意:JWT 必须将 alg 标头编码为受保护标头,如 > setProtectedHeader

分级访问控制

我们计划在未来构建更强大的服务对服务 Auth,但在此之前,您可以使用当前系统的一些技巧来加固您的部署。 本节假定您已经将后端插件分成多个后端部署,以便扩展或隔离它们。

后端认证配置支持提供多个密钥,例如

backend:
auth:
keys:
- secret: my-secret-key-1
- secret: my-secret-key-2
- secret: my-secret-key-3

第一个密钥将用于签署请求,而所有密钥都将用于验证。 这意味着可以设置非对称配置,让一些后端部署无法访问对方。

例如,假设我们将目录、脚手架和搜索插件分成了三个独立的后端部署,我们可以使用以下配置来允许脚手架和搜索插件与目录对话,但不能反过来,也不允许脚手架和搜索插件之间进行任何通信。

# catalog config
backend:
auth:
keys:
- secret: my-secret-key-catalog
- secret: my-secret-key-scaffolder
- secret: my-secret-key-search

# scaffolder config
backend:
auth:
keys:
- secret: my-secret-key-scaffolder

# search config
backend:
auth:
keys:
- secret: my-secret-key-search