Signed-off-by: Harry Hogg <hhogg@spotify.com>
This commit is contained in:
Harry Hogg
2023-02-07 13:29:33 +00:00
committed by Vincenzo Scamporlino
parent 7b86882985
commit e2571d1761
4 changed files with 109 additions and 28 deletions
@@ -66,6 +66,7 @@ type TemplateContext = {
entity?: UserEntity;
ref?: string;
};
token?: string;
};
const isValidTaskSpec = (taskSpec: TaskSpec): taskSpec is TaskSpecV1beta3 => {
@@ -378,31 +378,7 @@ export async function createRouter(
const baseUrl = getEntityBaseUrl(template);
const taskSpec: TaskSpec = {
apiVersion: template.apiVersion,
steps: template.spec.steps.map((step, index) => ({
...step,
id: step.id ?? `step-${index + 1}`,
name: step.name ?? step.action,
})),
output: template.spec.output ?? {},
parameters: values,
user: {
entity: userEntity as UserEntity,
ref: userEntityRef,
},
templateInfo: {
entityRef: stringifyEntityRef({
kind,
namespace,
name: template.metadata?.name,
}),
baseUrl,
entity: {
metadata: template.metadata,
},
},
};
const taskSpec = await authorizeTaskSpec(template);
const result = await taskBroker.dispatch({
spec: taskSpec,
@@ -651,5 +627,35 @@ export async function createRouter(
return template;
}
async function authorizeTaskSpec(template: TemplateEntityV1beta3): TaskSpec {
const taskSpec: TaskSpec = {
apiVersion: template.apiVersion,
steps: template.spec.steps.map((step, index) => ({
...step,
id: step.id ?? `step-${index + 1}`,
name: step.name ?? step.action,
})),
output: template.spec.output ?? {},
parameters: values,
user: {
entity: userEntity as UserEntity,
ref: userEntityRef,
},
templateInfo: {
entityRef: stringifyEntityRef({
kind,
namespace,
name: template.metadata?.name,
}),
baseUrl,
entity: {
metadata: template.metadata,
},
},
};
return taskSpec;
}
return app;
}
@@ -15,21 +15,75 @@
*/
import { makeCreatePermissionRule } from '@backstage/plugin-permission-node';
import {
RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,
RESOURCE_TYPE_SCAFFOLDER_ACTION,
} from '@backstage/plugin-scaffolder-common/alpha';
import {
TemplateEntityStepV1beta3,
TemplateParametersV1beta3,
} from '@backstage/plugin-scaffolder-common';
import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE } from '@backstage/plugin-scaffolder-common/alpha';
import { z } from 'zod';
import { JsonObject } from '@backstage/types';
export const createScaffolderPermissionRule = makeCreatePermissionRule<
export const createTemplatePermissionRule = makeCreatePermissionRule<
TemplateEntityStepV1beta3 | TemplateParametersV1beta3,
{},
typeof RESOURCE_TYPE_SCAFFOLDER_TEMPLATE
>();
export const hasTag = createScaffolderPermissionRule({
export const createActionPermissionRule = makeCreatePermissionRule<
{
actionId: string;
input: JsonObject;
template: TemplateEntityStepV1beta3 | TemplateParametersV1beta3;
},
{},
typeof RESOURCE_TYPE_SCAFFOLDER_ACTION
>();
export const hasActionId = createActionPermissionRule({
name: 'HAS_ACTION_ID',
resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,
description: `Match actions with the given actionId`,
paramsSchema: z.object({
actionId: z.string().describe('Name of the actionId to match on'),
}),
apply: (resource, { actionId }) => {
return resource.actionId === actionId;
},
toQuery: () => ({}),
});
export const matchesInput = createActionPermissionRule({
name: 'MATCHED_INPUT',
resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,
description: `Matches actionId and the input given`,
paramsSchema: z.object({
actionId: z.string().describe('Name of the actionId to match on'),
// Pass in a json schema to validate the input against
input: z.jsonSchema({}).describe('Input to match on'),
}),
apply: (resource, { actionId, input }) => {
if (resource.actionId !== actionId) {
return false;
}
for (const [key, value] of Object.entries(input)) {
if (resource.input[key] !== value) {
return false;
}
}
return true;
},
toQuery: () => ({}),
});
export const hasTag = createTemplatePermissionRule({
name: 'HAS_TAG',
resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,
description: `Match parameters or steps with the given tag`,
@@ -23,6 +23,25 @@ import { createPermission } from '@backstage/plugin-permission-common';
*/
export const RESOURCE_TYPE_SCAFFOLDER_TEMPLATE = 'scaffolder-template';
/**
* Permission resource type which corresponds to a scaffolder action.
*
* @alpha
*/
export const RESOURCE_TYPE_SCAFFOLDER_ACTION = 'scaffolder-action';
/**
* This permission is used to authorize actions that involve executing
* an action from a template.
*
* @alpha
*/
export const actionExecutePermission = createPermission({
name: 'scaffolder.action.execute',
attributes: {},
resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,
});
/**
* This permission is used to authorize actions that involve reading
* one or more parameters from a template.
@@ -64,6 +83,7 @@ export const templateStepReadPermission = createPermission({
* @alpha
*/
export const scaffolderPermissions = [
actionExecutePermission,
templateParameterReadPermission,
templateStepReadPermission,
];