Skip to main content

定义自定义权限规则

对于某些用例,您可能需要定义自定义的规则中的上一节我们使用了isEntityOwner规则来控制目录实体的访问。 让我们用一条自定义规则来扩展该策略,检查哪些系统实体的一部分。

定义自定义规则

插件应导出一个提供类型安全的规则工厂,确保与插件后端兼容。 目录插件导出了createCatalogPermissionRule@backstage/plugin-catalog-backend/alpha注意/alpha路径段是临时的,直到该 API 被标记为稳定为止。 在本例中,我们将在packages/backend/src/plugins/permission.ts.

在下面的示例中,我们使用 Zod。 安装时,运行

yarn workspace backend add zod
packages/backend/src/plugins/permission.ts
...

import type { Entity } from '@backstage/catalog-model';
import { createCatalogPermissionRule } from '@backstage/plugin-catalog-backend/alpha';
import { createConditionFactory } from '@backstage/plugin-permission-node';
import { z } from 'zod';

export const isInSystemRule = createCatalogPermissionRule({
name: 'IS_IN_SYSTEM',
description: 'Checks if an entity is part of the system provided',
resourceType: 'catalog-entity',
paramsSchema: z.object({
systemRef: z
.string()
.describe('SystemRef to check the resource is part of'),
}),
apply: (resource: Entity, { systemRef }) => {
if (!resource.relations) {
return false;
}

return resource.relations
.filter(relation => relation.type === 'partOf')
.some(relation => relation.targetRef === systemRef);
},
toQuery: ({ systemRef }) => ({
key: 'relations.partOf',
values: [systemRef],
}),
});

const isInSystem = createConditionFactory(isInSystemRule);

...

有关定义规则的详细说明,请参阅为插件作者提供文档.

仍在packages/backend/src/plugins/permission.ts文件中创建的条件。TestPermissionPolicy.

packages/backend/src/plugins/permission.ts
...
import { createCatalogPermissionRule } from '@backstage/plugin-catalog-backend/alpha';
import { catalogConditions, createCatalogConditionalDecision, createCatalogPermissionRule } from '@backstage/plugin-catalog-backend/alpha';
import { createConditionFactory } from '@backstage/plugin-permission-node';
import { PermissionPolicy, PolicyQuery, createConditionFactory } from '@backstage/plugin-permission-node';
import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
import { AuthorizeResult, PolicyDecision, isResourcePermission } from '@backstage/plugin-permission-common';
...

export const isInSystemRule = createCatalogPermissionRule({
name: 'IS_IN_SYSTEM',
description: 'Checks if an entity is part of the system provided',
resourceType: 'catalog-entity',
paramsSchema: z.object({
systemRef: z
.string()
.describe('SystemRef to check the resource is part of'),
}),
apply: (resource: Entity, { systemRef }) => {
if (!resource.relations) {
return false;
}

return resource.relations
.filter(relation => relation.type === 'partOf')
.some(relation => relation.targetRef === systemRef);
},
toQuery: ({ systemRef }) => ({
key: 'relations.partOf',
values: [systemRef],
}),
});

const isInSystem = createConditionFactory(isInSystemRule);

class TestPermissionPolicy implements PermissionPolicy {
async handle(
request: PolicyQuery,
user?: BackstageIdentityResponse,
): Promise<PolicyDecision> {
if (isResourcePermission(request.permission, 'catalog-entity')) {
return createCatalogConditionalDecision(
request.permission,
catalogConditions.isEntityOwner({
claims: user?.identity.ownershipEntityRefs ?? [],
}),
{
anyOf: [
catalogConditions.isEntityOwner({
claims: user?.identity.ownershipEntityRefs ?? [],
}),
isInSystem({ systemRef: 'interviewing' }),
],
},
);
}

return { result: AuthorizeResult.ALLOW };
}
}

...

在设置插件时提供规则

现在我们已经定义了自定义规则并将其添加到策略中,我们需要将其提供给目录插件。 这一步非常重要,因为目录插件将使用该规则的toQueryapply无法保证目录和权限后端在同一服务器上运行,因此我们必须显式链接规则,以确保其在运行时可用。

提供自定义规则的 api 可能因插件而异,但在创建后端路由器的过程中通常会有一些集成点。 对于目录来说,这个集成点可以通过以下方式实现CatalogBuilder.addPermissionRules.

packages/backend/src/plugins/catalog.ts
import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
import { isInSystemRule } from './permission';

...

export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
builder.addPermissionRules(isInSystemRule);
...
return router;
}

如果以下情况属实,更新后的策略将允许目录实体资源权限:

  • 用户拥有目标实体 * 目标实体是 "采访 "系统的一部分