@backstage/plugin-scaffolder-backend 1.29.0 → 1.30.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/README.md +29 -0
- package/dist/ScaffolderPlugin.cjs.js +8 -5
- package/dist/ScaffolderPlugin.cjs.js.map +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/scaffolder/dryrun/createDryRunner.cjs.js +5 -4
- package/dist/scaffolder/dryrun/createDryRunner.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js +18 -14
- package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js +14 -5
- package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/TaskWorker.cjs.js +21 -2
- package/dist/scaffolder/tasks/TaskWorker.cjs.js.map +1 -1
- package/dist/service/router.cjs.js +475 -309
- package/dist/service/router.cjs.js.map +1 -1
- package/package.json +31 -31
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createLegacyAuthAdapters,\n HostDiscovery,\n} from '@backstage/backend-common';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport {\n CompoundEntityRef,\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n UserEntity,\n} from '@backstage/catalog-model';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { InputError, NotFoundError, stringifyError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { HumanDuration, JsonObject, JsonValue } from '@backstage/types';\nimport {\n TaskSpec,\n TemplateEntityStepV1beta3,\n TemplateEntityV1beta3,\n templateEntityV1beta3Validator,\n TemplateParametersV1beta3,\n} from '@backstage/plugin-scaffolder-common';\nimport {\n RESOURCE_TYPE_SCAFFOLDER_ACTION,\n RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n scaffolderActionPermissions,\n scaffolderPermissions,\n scaffolderTemplatePermissions,\n taskCancelPermission,\n taskCreatePermission,\n taskReadPermission,\n templateParameterReadPermission,\n templateStepReadPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { validate } from 'jsonschema';\nimport { Logger } from 'winston';\nimport { z } from 'zod';\nimport {\n TaskBroker,\n TaskStatus,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n createBuiltinActions,\n DatabaseTaskStore,\n TaskWorker,\n TemplateActionRegistry,\n} from '../scaffolder';\nimport { createDryRunner } from '../scaffolder/dryrun';\nimport { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker';\nimport {\n findTemplate,\n getEntityBaseUrl,\n getWorkingDirectory,\n parseNumberParam,\n parseStringsParam,\n} from './helpers';\nimport { PermissionRuleParams } from '@backstage/plugin-permission-common';\nimport {\n createConditionAuthorizer,\n createPermissionIntegrationRouter,\n PermissionRule,\n} from '@backstage/plugin-permission-node';\nimport { scaffolderActionRules, scaffolderTemplateRules } from './rules';\nimport { Duration } from 'luxon';\nimport {\n AuthService,\n BackstageCredentials,\n DatabaseService,\n DiscoveryService,\n HttpAuthService,\n LifecycleService,\n PermissionsService,\n resolveSafeChildPath,\n SchedulerService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport {\n IdentityApi,\n IdentityApiGetIdentityRequest,\n} from '@backstage/plugin-auth-node';\nimport { InternalTaskSecrets } from '../scaffolder/tasks/types';\nimport { checkPermission } from '../util/checkPermissions';\nimport {\n AutocompleteHandler,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport { pathToFileURL } from 'url';\nimport { v4 as uuid } from 'uuid';\nimport { EventsService } from '@backstage/plugin-events-node';\n\n/**\n *\n * @public\n */\nexport type TemplatePermissionRuleInput<\n TParams extends PermissionRuleParams = PermissionRuleParams,\n> = PermissionRule<\n TemplateEntityStepV1beta3 | TemplateParametersV1beta3,\n {},\n typeof RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n TParams\n>;\nfunction isTemplatePermissionRuleInput(\n permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput,\n): permissionRule is TemplatePermissionRuleInput {\n return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_TEMPLATE;\n}\n\n/**\n *\n * @public\n */\nexport type ActionPermissionRuleInput<\n TParams extends PermissionRuleParams = PermissionRuleParams,\n> = PermissionRule<\n TemplateEntityStepV1beta3 | TemplateParametersV1beta3,\n {},\n typeof RESOURCE_TYPE_SCAFFOLDER_ACTION,\n TParams\n>;\nfunction isActionPermissionRuleInput(\n permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput,\n): permissionRule is ActionPermissionRuleInput {\n return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_ACTION;\n}\n\n/**\n * RouterOptions\n *\n * @public\n * @deprecated Please migrate to the new backend system as this will be removed in the future.\n */\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n reader: UrlReaderService;\n lifecycle?: LifecycleService;\n database: DatabaseService;\n catalogClient: CatalogApi;\n scheduler?: SchedulerService;\n actions?: TemplateAction<any, any>[];\n /**\n * @deprecated taskWorkers is deprecated in favor of concurrentTasksLimit option with a single TaskWorker\n * @defaultValue 1\n */\n taskWorkers?: number;\n /**\n * Sets the number of concurrent tasks that can be run at any given time on the TaskWorker\n * @defaultValue 10\n */\n concurrentTasksLimit?: number;\n taskBroker?: TaskBroker;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n additionalWorkspaceProviders?: Record<string, WorkspaceProvider>;\n permissions?: PermissionsService;\n permissionRules?: Array<\n TemplatePermissionRuleInput | ActionPermissionRuleInput\n >;\n auth?: AuthService;\n httpAuth?: HttpAuthService;\n identity?: IdentityApi;\n discovery?: DiscoveryService;\n events?: EventsService;\n\n autocompleteHandlers?: Record<string, AutocompleteHandler>;\n}\n\nfunction isSupportedTemplate(entity: TemplateEntityV1beta3) {\n return entity.apiVersion === 'scaffolder.backstage.io/v1beta3';\n}\n\n/*\n * @deprecated This function remains as the DefaultIdentityClient behaves slightly differently to the pre-existing\n * scaffolder behaviour. Specifically if the token fails to parse, the DefaultIdentityClient will raise an error.\n * The scaffolder did not raise an error in this case. As such we chose to allow it to behave as it did previously\n * until someone explicitly passes an IdentityApi. When we have reasonable confidence that most backstage deployments\n * are using the IdentityApi, we can remove this function.\n */\nfunction buildDefaultIdentityClient(options: RouterOptions): IdentityApi {\n return {\n getIdentity: async ({ request }: IdentityApiGetIdentityRequest) => {\n const header = request.headers.authorization;\n const { logger } = options;\n\n if (!header) {\n return undefined;\n }\n\n try {\n const token = header.match(/^Bearer\\s(\\S+\\.\\S+\\.\\S+)$/i)?.[1];\n if (!token) {\n throw new TypeError('Expected Bearer with JWT');\n }\n\n const [_header, rawPayload, _signature] = token.split('.');\n const payload: JsonValue = JSON.parse(\n Buffer.from(rawPayload, 'base64').toString(),\n );\n\n if (\n typeof payload !== 'object' ||\n payload === null ||\n Array.isArray(payload)\n ) {\n throw new TypeError('Malformed JWT payload');\n }\n\n const sub = payload.sub;\n if (typeof sub !== 'string') {\n throw new TypeError('Expected string sub claim');\n }\n\n if (sub === 'backstage-server') {\n return undefined;\n }\n\n // Check that it's a valid ref, otherwise this will throw.\n parseEntityRef(sub);\n\n return {\n identity: {\n userEntityRef: sub,\n ownershipEntityRefs: [],\n type: 'user',\n },\n token,\n };\n } catch (e) {\n logger.error(`Invalid authorization header: ${stringifyError(e)}`);\n return undefined;\n }\n },\n };\n}\n\nconst readDuration = (\n config: Config,\n key: string,\n defaultValue: HumanDuration,\n) => {\n if (config.has(key)) {\n return readDurationFromConfig(config, { key });\n }\n return defaultValue;\n};\n\n/**\n * A method to create a router for the scaffolder backend plugin.\n * @public\n * @deprecated Please migrate to the new backend system as this will be removed in the future.\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const router = Router();\n // Be generous in upload size to support a wide range of templates in dry-run mode.\n router.use(express.json({ limit: '10MB' }));\n\n const {\n logger: parentLogger,\n config,\n reader,\n database,\n catalogClient,\n actions,\n taskWorkers,\n scheduler,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n additionalWorkspaceProviders,\n permissions,\n permissionRules,\n discovery = HostDiscovery.fromConfig(config),\n identity = buildDefaultIdentityClient(options),\n autocompleteHandlers = {},\n events: eventsService,\n } = options;\n\n const { auth, httpAuth } = createLegacyAuthAdapters({\n ...options,\n identity,\n discovery,\n });\n\n const concurrentTasksLimit =\n options.concurrentTasksLimit ??\n options.config.getOptionalNumber('scaffolder.concurrentTasksLimit');\n\n const logger = parentLogger.child({ plugin: 'scaffolder' });\n\n const workingDirectory = await getWorkingDirectory(config, logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n let taskBroker: TaskBroker;\n if (!options.taskBroker) {\n const databaseTaskStore = await DatabaseTaskStore.create({\n database,\n events: eventsService,\n });\n taskBroker = new StorageTaskBroker(\n databaseTaskStore,\n logger,\n config,\n auth,\n additionalWorkspaceProviders,\n );\n\n if (scheduler && databaseTaskStore.listStaleTasks) {\n await scheduler.scheduleTask({\n id: 'close_stale_tasks',\n frequency: readDuration(\n config,\n 'scaffolder.taskTimeoutJanitorFrequency',\n {\n minutes: 5,\n },\n ),\n timeout: { minutes: 15 },\n fn: async () => {\n const { tasks } = await databaseTaskStore.listStaleTasks({\n timeoutS: Duration.fromObject(\n readDuration(config, 'scaffolder.taskTimeout', {\n hours: 24,\n }),\n ).as('seconds'),\n });\n\n for (const task of tasks) {\n await databaseTaskStore.shutdownTask(task);\n logger.info(`Successfully closed stale task ${task.taskId}`);\n }\n },\n });\n }\n } else {\n taskBroker = options.taskBroker;\n }\n\n const actionRegistry = new TemplateActionRegistry();\n\n const workers: TaskWorker[] = [];\n if (concurrentTasksLimit !== 0) {\n for (let i = 0; i < (taskWorkers || 1); i++) {\n const worker = await TaskWorker.create({\n taskBroker,\n actionRegistry,\n integrations,\n logger,\n workingDirectory,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n concurrentTasksLimit,\n permissions,\n });\n workers.push(worker);\n }\n }\n\n const actionsToRegister = Array.isArray(actions)\n ? actions\n : createBuiltinActions({\n integrations,\n catalogClient,\n reader,\n config,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n });\n\n actionsToRegister.forEach(action => actionRegistry.register(action));\n\n const launchWorkers = () => workers.forEach(worker => worker.start());\n\n const shutdownWorkers = () => {\n workers.forEach(worker => worker.stop());\n };\n\n if (options.lifecycle) {\n options.lifecycle.addStartupHook(launchWorkers);\n options.lifecycle.addShutdownHook(shutdownWorkers);\n } else {\n launchWorkers();\n }\n\n const dryRunner = createDryRunner({\n actionRegistry,\n integrations,\n logger,\n workingDirectory,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n permissions,\n });\n\n const templateRules: TemplatePermissionRuleInput[] = Object.values(\n scaffolderTemplateRules,\n );\n const actionRules: ActionPermissionRuleInput[] = Object.values(\n scaffolderActionRules,\n );\n\n if (permissionRules) {\n templateRules.push(\n ...permissionRules.filter(isTemplatePermissionRuleInput),\n );\n actionRules.push(...permissionRules.filter(isActionPermissionRuleInput));\n }\n\n const isAuthorized = createConditionAuthorizer(Object.values(templateRules));\n\n const permissionIntegrationRouter = createPermissionIntegrationRouter({\n resources: [\n {\n resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n permissions: scaffolderTemplatePermissions,\n rules: templateRules,\n },\n {\n resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,\n permissions: scaffolderActionPermissions,\n rules: actionRules,\n },\n ],\n permissions: scaffolderPermissions,\n });\n\n router.use(permissionIntegrationRouter);\n\n router\n .get(\n '/v2/templates/:namespace/:kind/:name/parameter-schema',\n async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const template = await authorizeTemplate(\n req.params,\n token,\n credentials,\n );\n\n const parameters = [template.spec.parameters ?? []].flat();\n\n const presentation = template.spec.presentation;\n\n res.json({\n title: template.metadata.title ?? template.metadata.name,\n ...(presentation ? { presentation } : {}),\n description: template.metadata.description,\n 'ui:options': template.metadata['ui:options'],\n steps: parameters.map(schema => ({\n title: schema.title ?? 'Please enter the following information',\n description: schema.description,\n schema,\n })),\n EXPERIMENTAL_formDecorators:\n template.spec.EXPERIMENTAL_formDecorators,\n });\n },\n )\n .get('/v2/actions', async (_req, res) => {\n const actionsList = actionRegistry.list().map(action => {\n return {\n id: action.id,\n description: action.description,\n examples: action.examples,\n schema: action.schema,\n };\n });\n res.json(actionsList);\n })\n .post('/v2/tasks', async (req, res) => {\n const templateRef: string = req.body.templateRef;\n const { kind, namespace, name } = parseEntityRef(templateRef, {\n defaultKind: 'template',\n });\n\n const credentials = await httpAuth.credentials(req);\n\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission],\n permissionService: permissions,\n });\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalogClient.getEntityByRef(userEntityRef, { token })\n : undefined;\n\n let auditLog = `Scaffolding task for ${templateRef}`;\n if (userEntityRef) {\n auditLog += ` created by ${userEntityRef}`;\n }\n logger.info(auditLog);\n\n const values = req.body.values;\n\n const template = await authorizeTemplate(\n { kind, namespace, name },\n token,\n credentials,\n );\n\n for (const parameters of [template.spec.parameters ?? []].flat()) {\n const result = validate(values, parameters);\n\n if (!result.valid) {\n res.status(400).json({ errors: result.errors });\n return;\n }\n }\n\n const baseUrl = getEntityBaseUrl(template);\n\n const taskSpec: TaskSpec = {\n apiVersion: template.apiVersion,\n steps: template.spec.steps.map((step, index) => ({\n ...step,\n id: step.id ?? `step-${index + 1}`,\n name: step.name ?? step.action,\n })),\n EXPERIMENTAL_recovery: template.spec.EXPERIMENTAL_recovery,\n output: template.spec.output ?? {},\n parameters: values,\n user: {\n entity: userEntity as UserEntity,\n ref: userEntityRef,\n },\n templateInfo: {\n entityRef: stringifyEntityRef({ kind, name, namespace }),\n baseUrl,\n entity: {\n metadata: template.metadata,\n },\n },\n };\n\n const secrets: InternalTaskSecrets = {\n ...req.body.secrets,\n backstageToken: token,\n __initiatorCredentials: JSON.stringify({\n ...credentials,\n // credentials.token is nonenumerable and will not be serialized, so we need to add it explicitly\n token: (credentials as any).token,\n }),\n };\n\n const result = await taskBroker.dispatch({\n spec: taskSpec,\n createdBy: userEntityRef,\n secrets,\n });\n\n res.status(201).json({ id: result.taskId });\n })\n .get('/v2/tasks', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n if (!taskBroker.list) {\n throw new Error(\n 'TaskBroker does not support listing tasks, please implement the list method on the TaskBroker.',\n );\n }\n\n const createdBy = parseStringsParam(req.query.createdBy, 'createdBy');\n const status = parseStringsParam(req.query.status, 'status');\n\n const order = parseStringsParam(req.query.order, 'order')?.map(item => {\n const match = item.match(/^(asc|desc):(.+)$/);\n if (!match) {\n throw new InputError(\n `Invalid order parameter \"${item}\", expected \"<asc or desc>:<field name>\"`,\n );\n }\n\n return {\n order: match[1] as 'asc' | 'desc',\n field: match[2],\n };\n });\n\n const limit = parseNumberParam(req.query.limit, 'limit');\n const offset = parseNumberParam(req.query.offset, 'offset');\n\n const tasks = await taskBroker.list({\n filters: {\n createdBy,\n status: status ? (status as TaskStatus[]) : undefined,\n },\n order,\n pagination: {\n limit: limit ? limit[0] : undefined,\n offset: offset ? offset[0] : undefined,\n },\n });\n\n res.status(200).json(tasks);\n })\n .get('/v2/tasks/:taskId', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n const task = await taskBroker.get(taskId);\n if (!task) {\n throw new NotFoundError(`Task with id ${taskId} does not exist`);\n }\n // Do not disclose secrets\n delete task.secrets;\n res.status(200).json(task);\n })\n .post('/v2/tasks/:taskId/cancel', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n // Requires both read and cancel permissions\n await checkPermission({\n credentials,\n permissions: [taskCancelPermission, taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n await taskBroker.cancel?.(taskId);\n res.status(200).json({ status: 'cancelled' });\n })\n .post('/v2/tasks/:taskId/retry', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n // Requires both read and cancel permissions\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission, taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n await taskBroker.retry?.(taskId);\n res.status(201).json({ id: taskId });\n })\n .get('/v2/tasks/:taskId/eventstream', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n const after =\n req.query.after !== undefined ? Number(req.query.after) : undefined;\n\n logger.debug(`Event stream observing taskId '${taskId}' opened`);\n\n // Mandatory headers and http status to keep connection open\n res.writeHead(200, {\n Connection: 'keep-alive',\n 'Cache-Control': 'no-cache',\n 'Content-Type': 'text/event-stream',\n });\n\n // After client opens connection send all events as string\n const subscription = taskBroker.event$({ taskId, after }).subscribe({\n error: error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n res.end();\n },\n next: ({ events }) => {\n let shouldUnsubscribe = false;\n for (const event of events) {\n res.write(\n `event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`,\n );\n if (event.type === 'completion' && !event.isTaskRecoverable) {\n shouldUnsubscribe = true;\n }\n }\n // res.flush() is only available with the compression middleware\n res.flush?.();\n if (shouldUnsubscribe) {\n subscription.unsubscribe();\n res.end();\n }\n },\n });\n\n // When client closes connection we update the clients list\n // avoiding the disconnected one\n req.on('close', () => {\n subscription.unsubscribe();\n logger.debug(`Event stream observing taskId '${taskId}' closed`);\n });\n })\n .get('/v2/tasks/:taskId/events', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const { taskId } = req.params;\n const after = Number(req.query.after) || undefined;\n\n // cancel the request after 30 seconds. this aligns with the recommendations of RFC 6202.\n const timeout = setTimeout(() => {\n res.json([]);\n }, 30_000);\n\n // Get all known events after an id (always includes the completion event) and return the first callback\n const subscription = taskBroker.event$({ taskId, after }).subscribe({\n error: error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n },\n next: ({ events }) => {\n clearTimeout(timeout);\n subscription.unsubscribe();\n res.json(events);\n },\n });\n\n // When client closes connection we update the clients list\n // avoiding the disconnected one\n req.on('close', () => {\n subscription.unsubscribe();\n clearTimeout(timeout);\n });\n })\n .post('/v2/dry-run', async (req, res) => {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission],\n permissionService: permissions,\n });\n\n const bodySchema = z.object({\n template: z.unknown(),\n values: z.record(z.unknown()),\n secrets: z.record(z.string()).optional(),\n directoryContents: z.array(\n z.object({ path: z.string(), base64Content: z.string() }),\n ),\n });\n const body = await bodySchema.parseAsync(req.body).catch(e => {\n throw new InputError(`Malformed request: ${e}`);\n });\n\n const template = body.template as TemplateEntityV1beta3;\n if (!(await templateEntityV1beta3Validator.check(template))) {\n throw new InputError('Input template is not a template');\n }\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalogClient.getEntityByRef(userEntityRef, { token })\n : undefined;\n\n for (const parameters of [template.spec.parameters ?? []].flat()) {\n const result = validate(body.values, parameters);\n if (!result.valid) {\n res.status(400).json({ errors: result.errors });\n return;\n }\n }\n\n const steps = template.spec.steps.map((step, index) => ({\n ...step,\n id: step.id ?? `step-${index + 1}`,\n name: step.name ?? step.action,\n }));\n\n const dryRunId = uuid();\n const contentsPath = resolveSafeChildPath(\n workingDirectory,\n `dry-run-content-${dryRunId}`,\n );\n\n const templateInfo = {\n entityRef: stringifyEntityRef(template),\n entity: {\n metadata: template.metadata,\n },\n baseUrl: pathToFileURL(\n resolveSafeChildPath(contentsPath, 'template.yaml'),\n ).toString(),\n };\n\n const result = await dryRunner({\n spec: {\n apiVersion: template.apiVersion,\n steps,\n output: template.spec.output ?? {},\n parameters: body.values as JsonObject,\n user: {\n entity: userEntity as UserEntity,\n ref: userEntityRef,\n },\n },\n templateInfo: templateInfo,\n directoryContents: (body.directoryContents ?? []).map(file => ({\n path: file.path,\n content: Buffer.from(file.base64Content, 'base64'),\n })),\n secrets: {\n ...body.secrets,\n ...(token && { backstageToken: token }),\n },\n credentials,\n });\n\n res.status(200).json({\n ...result,\n steps,\n directoryContents: result.directoryContents.map(file => ({\n path: file.path,\n executable: file.executable,\n base64Content: file.content.toString('base64'),\n })),\n });\n })\n .post('/v2/autocomplete/:provider/:resource', async (req, res) => {\n const { token, context } = req.body;\n const { provider, resource } = req.params;\n\n if (!token) throw new InputError('Missing token query parameter');\n\n if (!autocompleteHandlers[provider]) {\n throw new InputError(`Unsupported provider: ${provider}`);\n }\n\n const { results } = await autocompleteHandlers[provider]({\n resource,\n token,\n context,\n });\n\n res.status(200).json({ results });\n });\n\n const app = express();\n app.set('logger', logger);\n app.use('/', router);\n\n async function authorizeTemplate(\n entityRef: CompoundEntityRef,\n token: string | undefined,\n credentials: BackstageCredentials,\n ) {\n const template = await findTemplate({\n catalogApi: catalogClient,\n entityRef,\n token,\n });\n\n if (!isSupportedTemplate(template)) {\n throw new InputError(\n `Unsupported apiVersion field in schema entity, ${\n (template as Entity).apiVersion\n }`,\n );\n }\n\n if (!permissions) {\n return template;\n }\n\n const [parameterDecision, stepDecision] =\n await permissions.authorizeConditional(\n [\n { permission: templateParameterReadPermission },\n { permission: templateStepReadPermission },\n ],\n { credentials },\n );\n\n // Authorize parameters\n if (Array.isArray(template.spec.parameters)) {\n template.spec.parameters = template.spec.parameters.filter(step =>\n isAuthorized(parameterDecision, step),\n );\n } else if (\n template.spec.parameters &&\n !isAuthorized(parameterDecision, template.spec.parameters)\n ) {\n template.spec.parameters = undefined;\n }\n\n // Authorize steps\n template.spec.steps = template.spec.steps.filter(step =>\n isAuthorized(stepDecision, step),\n );\n\n return template;\n }\n\n return app;\n}\n"],"names":["RESOURCE_TYPE_SCAFFOLDER_TEMPLATE","RESOURCE_TYPE_SCAFFOLDER_ACTION","parseEntityRef","stringifyError","config","readDurationFromConfig","Router","express","HostDiscovery","createLegacyAuthAdapters","getWorkingDirectory","ScmIntegrations","DatabaseTaskStore","StorageTaskBroker","Duration","TemplateActionRegistry","TaskWorker","createBuiltinActions","createDryRunner","scaffolderTemplateRules","scaffolderActionRules","createConditionAuthorizer","createPermissionIntegrationRouter","scaffolderTemplatePermissions","scaffolderActionPermissions","scaffolderPermissions","checkPermission","taskCreatePermission","result","validate","getEntityBaseUrl","stringifyEntityRef","taskReadPermission","parseStringsParam","InputError","parseNumberParam","NotFoundError","taskCancelPermission","z","templateEntityV1beta3Validator","uuid","resolveSafeChildPath","pathToFileURL","findTemplate","templateParameterReadPermission","templateStepReadPermission"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createLegacyAuthAdapters,\n HostDiscovery,\n} from '@backstage/backend-common';\nimport {\n AuditorService,\n AuthService,\n BackstageCredentials,\n DatabaseService,\n DiscoveryService,\n HttpAuthService,\n LifecycleService,\n PermissionsService,\n resolveSafeChildPath,\n SchedulerService,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport {\n CompoundEntityRef,\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n UserEntity,\n} from '@backstage/catalog-model';\nimport { Config, readDurationFromConfig } from '@backstage/config';\nimport { InputError, NotFoundError, stringifyError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n IdentityApi,\n IdentityApiGetIdentityRequest,\n} from '@backstage/plugin-auth-node';\nimport { EventsService } from '@backstage/plugin-events-node';\nimport { PermissionRuleParams } from '@backstage/plugin-permission-common';\nimport {\n createConditionAuthorizer,\n createPermissionIntegrationRouter,\n PermissionRule,\n} from '@backstage/plugin-permission-node';\nimport {\n TaskSpec,\n TemplateEntityStepV1beta3,\n TemplateEntityV1beta3,\n templateEntityV1beta3Validator,\n TemplateParametersV1beta3,\n} from '@backstage/plugin-scaffolder-common';\nimport {\n RESOURCE_TYPE_SCAFFOLDER_ACTION,\n RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n scaffolderActionPermissions,\n scaffolderPermissions,\n scaffolderTemplatePermissions,\n taskCancelPermission,\n taskCreatePermission,\n taskReadPermission,\n templateParameterReadPermission,\n templateStepReadPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport {\n TaskBroker,\n TaskStatus,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport { HumanDuration, JsonObject, JsonValue } from '@backstage/types';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { validate } from 'jsonschema';\nimport { Duration } from 'luxon';\nimport { pathToFileURL } from 'url';\nimport { v4 as uuid } from 'uuid';\nimport { Logger } from 'winston';\nimport { z } from 'zod';\nimport {\n createBuiltinActions,\n DatabaseTaskStore,\n TaskWorker,\n TemplateActionRegistry,\n} from '../scaffolder';\nimport { createDryRunner } from '../scaffolder/dryrun';\nimport { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker';\nimport { InternalTaskSecrets } from '../scaffolder/tasks/types';\nimport { checkPermission } from '../util/checkPermissions';\nimport {\n findTemplate,\n getEntityBaseUrl,\n getWorkingDirectory,\n parseNumberParam,\n parseStringsParam,\n} from './helpers';\nimport { scaffolderActionRules, scaffolderTemplateRules } from './rules';\n\n/**\n *\n * @public\n */\nexport type TemplatePermissionRuleInput<\n TParams extends PermissionRuleParams = PermissionRuleParams,\n> = PermissionRule<\n TemplateEntityStepV1beta3 | TemplateParametersV1beta3,\n {},\n typeof RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n TParams\n>;\nfunction isTemplatePermissionRuleInput(\n permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput,\n): permissionRule is TemplatePermissionRuleInput {\n return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_TEMPLATE;\n}\n\n/**\n *\n * @public\n */\nexport type ActionPermissionRuleInput<\n TParams extends PermissionRuleParams = PermissionRuleParams,\n> = PermissionRule<\n TemplateEntityStepV1beta3 | TemplateParametersV1beta3,\n {},\n typeof RESOURCE_TYPE_SCAFFOLDER_ACTION,\n TParams\n>;\nfunction isActionPermissionRuleInput(\n permissionRule: TemplatePermissionRuleInput | ActionPermissionRuleInput,\n): permissionRule is ActionPermissionRuleInput {\n return permissionRule.resourceType === RESOURCE_TYPE_SCAFFOLDER_ACTION;\n}\n\n/**\n * RouterOptions\n *\n * @public\n * @deprecated Please migrate to the new backend system as this will be removed in the future.\n */\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n reader: UrlReaderService;\n lifecycle?: LifecycleService;\n database: DatabaseService;\n catalogClient: CatalogApi;\n scheduler?: SchedulerService;\n actions?: TemplateAction<any, any>[];\n /**\n * @deprecated taskWorkers is deprecated in favor of concurrentTasksLimit option with a single TaskWorker\n * @defaultValue 1\n */\n taskWorkers?: number;\n /**\n * Sets the number of concurrent tasks that can be run at any given time on the TaskWorker\n * @defaultValue 10\n */\n concurrentTasksLimit?: number;\n taskBroker?: TaskBroker;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n additionalWorkspaceProviders?: Record<string, WorkspaceProvider>;\n permissions?: PermissionsService;\n permissionRules?: Array<\n TemplatePermissionRuleInput | ActionPermissionRuleInput\n >;\n auth?: AuthService;\n httpAuth?: HttpAuthService;\n identity?: IdentityApi;\n discovery?: DiscoveryService;\n events?: EventsService;\n auditor?: AuditorService;\n autocompleteHandlers?: Record<string, AutocompleteHandler>;\n}\n\nfunction isSupportedTemplate(entity: TemplateEntityV1beta3) {\n return entity.apiVersion === 'scaffolder.backstage.io/v1beta3';\n}\n\n/*\n * @deprecated This function remains as the DefaultIdentityClient behaves slightly differently to the pre-existing\n * scaffolder behaviour. Specifically if the token fails to parse, the DefaultIdentityClient will raise an error.\n * The scaffolder did not raise an error in this case. As such we chose to allow it to behave as it did previously\n * until someone explicitly passes an IdentityApi. When we have reasonable confidence that most backstage deployments\n * are using the IdentityApi, we can remove this function.\n */\nfunction buildDefaultIdentityClient(options: RouterOptions): IdentityApi {\n return {\n getIdentity: async ({ request }: IdentityApiGetIdentityRequest) => {\n const header = request.headers.authorization;\n const { logger } = options;\n\n if (!header) {\n return undefined;\n }\n\n try {\n const token = header.match(/^Bearer\\s(\\S+\\.\\S+\\.\\S+)$/i)?.[1];\n if (!token) {\n throw new TypeError('Expected Bearer with JWT');\n }\n\n const [_header, rawPayload, _signature] = token.split('.');\n const payload: JsonValue = JSON.parse(\n Buffer.from(rawPayload, 'base64').toString(),\n );\n\n if (\n typeof payload !== 'object' ||\n payload === null ||\n Array.isArray(payload)\n ) {\n throw new TypeError('Malformed JWT payload');\n }\n\n const sub = payload.sub;\n if (typeof sub !== 'string') {\n throw new TypeError('Expected string sub claim');\n }\n\n if (sub === 'backstage-server') {\n return undefined;\n }\n\n // Check that it's a valid ref, otherwise this will throw.\n parseEntityRef(sub);\n\n return {\n identity: {\n userEntityRef: sub,\n ownershipEntityRefs: [],\n type: 'user',\n },\n token,\n };\n } catch (e) {\n logger.error(`Invalid authorization header: ${stringifyError(e)}`);\n return undefined;\n }\n },\n };\n}\n\nconst readDuration = (\n config: Config,\n key: string,\n defaultValue: HumanDuration,\n) => {\n if (config.has(key)) {\n return readDurationFromConfig(config, { key });\n }\n return defaultValue;\n};\n\n/**\n * A method to create a router for the scaffolder backend plugin.\n * @public\n * @deprecated Please migrate to the new backend system as this will be removed in the future.\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const router = Router();\n // Be generous in upload size to support a wide range of templates in dry-run mode.\n router.use(express.json({ limit: '10MB' }));\n\n const {\n logger: parentLogger,\n config,\n reader,\n database,\n catalogClient,\n actions,\n taskWorkers,\n scheduler,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n additionalWorkspaceProviders,\n permissions,\n permissionRules,\n discovery = HostDiscovery.fromConfig(config),\n identity = buildDefaultIdentityClient(options),\n autocompleteHandlers = {},\n events: eventsService,\n auditor,\n } = options;\n\n const { auth, httpAuth } = createLegacyAuthAdapters({\n ...options,\n identity,\n discovery,\n });\n\n const concurrentTasksLimit =\n options.concurrentTasksLimit ??\n options.config.getOptionalNumber('scaffolder.concurrentTasksLimit');\n\n const logger = parentLogger.child({ plugin: 'scaffolder' });\n\n const workingDirectory = await getWorkingDirectory(config, logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n let taskBroker: TaskBroker;\n if (!options.taskBroker) {\n const databaseTaskStore = await DatabaseTaskStore.create({\n database,\n events: eventsService,\n });\n taskBroker = new StorageTaskBroker(\n databaseTaskStore,\n logger,\n config,\n auth,\n additionalWorkspaceProviders,\n auditor,\n );\n\n if (scheduler && databaseTaskStore.listStaleTasks) {\n await scheduler.scheduleTask({\n id: 'close_stale_tasks',\n frequency: readDuration(\n config,\n 'scaffolder.taskTimeoutJanitorFrequency',\n {\n minutes: 5,\n },\n ),\n timeout: { minutes: 15 },\n fn: async () => {\n const { tasks } = await databaseTaskStore.listStaleTasks({\n timeoutS: Duration.fromObject(\n readDuration(config, 'scaffolder.taskTimeout', {\n hours: 24,\n }),\n ).as('seconds'),\n });\n\n for (const task of tasks) {\n await databaseTaskStore.shutdownTask(task);\n logger.info(`Successfully closed stale task ${task.taskId}`);\n }\n },\n });\n }\n } else {\n taskBroker = options.taskBroker;\n }\n\n const actionRegistry = new TemplateActionRegistry();\n\n const workers: TaskWorker[] = [];\n if (concurrentTasksLimit !== 0) {\n for (let i = 0; i < (taskWorkers || 1); i++) {\n const worker = await TaskWorker.create({\n taskBroker,\n actionRegistry,\n integrations,\n logger,\n auditor,\n workingDirectory,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n concurrentTasksLimit,\n permissions,\n });\n workers.push(worker);\n }\n }\n\n const actionsToRegister = Array.isArray(actions)\n ? actions\n : createBuiltinActions({\n integrations,\n catalogClient,\n reader,\n config,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n });\n\n actionsToRegister.forEach(action => actionRegistry.register(action));\n\n const launchWorkers = () => workers.forEach(worker => worker.start());\n\n const shutdownWorkers = () => {\n workers.forEach(worker => worker.stop());\n };\n\n if (options.lifecycle) {\n options.lifecycle.addStartupHook(launchWorkers);\n options.lifecycle.addShutdownHook(shutdownWorkers);\n } else {\n launchWorkers();\n }\n\n const dryRunner = createDryRunner({\n actionRegistry,\n integrations,\n logger,\n auditor,\n workingDirectory,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n permissions,\n });\n\n const templateRules: TemplatePermissionRuleInput[] = Object.values(\n scaffolderTemplateRules,\n );\n const actionRules: ActionPermissionRuleInput[] = Object.values(\n scaffolderActionRules,\n );\n\n if (permissionRules) {\n templateRules.push(\n ...permissionRules.filter(isTemplatePermissionRuleInput),\n );\n actionRules.push(...permissionRules.filter(isActionPermissionRuleInput));\n }\n\n const isAuthorized = createConditionAuthorizer(Object.values(templateRules));\n\n const permissionIntegrationRouter = createPermissionIntegrationRouter({\n resources: [\n {\n resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,\n permissions: scaffolderTemplatePermissions,\n rules: templateRules,\n },\n {\n resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,\n permissions: scaffolderActionPermissions,\n rules: actionRules,\n },\n ],\n permissions: scaffolderPermissions,\n });\n\n router.use(permissionIntegrationRouter);\n\n router\n .get(\n '/v2/templates/:namespace/:kind/:name/parameter-schema',\n async (req, res) => {\n const requestedTemplateRef = `${req.params.kind}:${req.params.namespace}/${req.params.name}`;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'template-parameter-schema',\n request: req,\n meta: { templateRef: requestedTemplateRef },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const template = await authorizeTemplate(\n req.params,\n token,\n credentials,\n );\n\n const parameters = [template.spec.parameters ?? []].flat();\n\n const presentation = template.spec.presentation;\n\n const templateRef = `${template.kind}:${\n template.metadata.namespace || 'default'\n }/${template.metadata.name}`;\n\n await auditorEvent?.success({ meta: { templateRef: templateRef } });\n\n res.json({\n title: template.metadata.title ?? template.metadata.name,\n ...(presentation ? { presentation } : {}),\n description: template.metadata.description,\n 'ui:options': template.metadata['ui:options'],\n steps: parameters.map(schema => ({\n title: schema.title ?? 'Please enter the following information',\n description: schema.description,\n schema,\n })),\n EXPERIMENTAL_formDecorators:\n template.spec.EXPERIMENTAL_formDecorators,\n });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n },\n )\n .get('/v2/actions', async (req, res) => {\n const auditorEvent = await auditor?.createEvent({\n eventId: 'action-fetch',\n request: req,\n });\n\n try {\n const actionsList = actionRegistry.list().map(action => {\n return {\n id: action.id,\n description: action.description,\n examples: action.examples,\n schema: action.schema,\n };\n });\n\n await auditorEvent?.success();\n\n res.json(actionsList);\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .post('/v2/tasks', async (req, res) => {\n const templateRef: string = req.body.templateRef;\n const { kind, namespace, name } = parseEntityRef(templateRef, {\n defaultKind: 'template',\n });\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n request: req,\n meta: {\n actionType: 'create',\n templateRef: templateRef,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission],\n permissionService: permissions,\n });\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalogClient.getEntityByRef(userEntityRef, { token })\n : undefined;\n\n let auditLog = `Scaffolding task for ${templateRef}`;\n if (userEntityRef) {\n auditLog += ` created by ${userEntityRef}`;\n }\n logger.info(auditLog);\n\n const values = req.body.values;\n\n const template = await authorizeTemplate(\n { kind, namespace, name },\n token,\n credentials,\n );\n\n for (const parameters of [template.spec.parameters ?? []].flat()) {\n const result = validate(values, parameters);\n\n if (!result.valid) {\n await auditorEvent?.fail({\n // TODO(Rugvip): Seems like there aren't proper types for AggregateError yet\n error: (AggregateError as any)(\n result.errors,\n 'Could not create entity',\n ),\n });\n\n res.status(400).json({ errors: result.errors });\n return;\n }\n }\n\n const baseUrl = getEntityBaseUrl(template);\n\n const taskSpec: TaskSpec = {\n apiVersion: template.apiVersion,\n steps: template.spec.steps.map((step, index) => ({\n ...step,\n id: step.id ?? `step-${index + 1}`,\n name: step.name ?? step.action,\n })),\n EXPERIMENTAL_recovery: template.spec.EXPERIMENTAL_recovery,\n output: template.spec.output ?? {},\n parameters: values,\n user: {\n entity: userEntity as UserEntity,\n ref: userEntityRef,\n },\n templateInfo: {\n entityRef: stringifyEntityRef({ kind, name, namespace }),\n baseUrl,\n entity: {\n metadata: template.metadata,\n },\n },\n };\n\n const secrets: InternalTaskSecrets = {\n ...req.body.secrets,\n backstageToken: token,\n __initiatorCredentials: JSON.stringify({\n ...credentials,\n // credentials.token is nonenumerable and will not be serialized, so we need to add it explicitly\n token: (credentials as any).token,\n }),\n };\n\n const result = await taskBroker.dispatch({\n spec: taskSpec,\n createdBy: userEntityRef,\n secrets,\n });\n\n await auditorEvent?.success({ meta: { taskId: result.taskId } });\n\n res.status(201).json({ id: result.taskId });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks', async (req, res) => {\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'list',\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n if (!taskBroker.list) {\n throw new Error(\n 'TaskBroker does not support listing tasks, please implement the list method on the TaskBroker.',\n );\n }\n\n const createdBy = parseStringsParam(req.query.createdBy, 'createdBy');\n const status = parseStringsParam(req.query.status, 'status');\n\n const order = parseStringsParam(req.query.order, 'order')?.map(item => {\n const match = item.match(/^(asc|desc):(.+)$/);\n if (!match) {\n throw new InputError(\n `Invalid order parameter \"${item}\", expected \"<asc or desc>:<field name>\"`,\n );\n }\n\n return {\n order: match[1] as 'asc' | 'desc',\n field: match[2],\n };\n });\n\n const limit = parseNumberParam(req.query.limit, 'limit');\n const offset = parseNumberParam(req.query.offset, 'offset');\n\n const tasks = await taskBroker.list({\n filters: {\n createdBy,\n status: status ? (status as TaskStatus[]) : undefined,\n },\n order,\n pagination: {\n limit: limit ? limit[0] : undefined,\n offset: offset ? offset[0] : undefined,\n },\n });\n\n await auditorEvent?.success();\n\n res.status(200).json(tasks);\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks/:taskId', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'get',\n taskId: taskId,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const task = await taskBroker.get(taskId);\n if (!task) {\n throw new NotFoundError(`Task with id ${taskId} does not exist`);\n }\n\n await auditorEvent?.success();\n\n // Do not disclose secrets\n delete task.secrets;\n res.status(200).json(task);\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .post('/v2/tasks/:taskId/cancel', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n request: req,\n meta: {\n actionType: 'cancel',\n taskId: taskId,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n // Requires both read and cancel permissions\n await checkPermission({\n credentials,\n permissions: [taskCancelPermission, taskReadPermission],\n permissionService: permissions,\n });\n\n await taskBroker.cancel?.(taskId);\n\n await auditorEvent?.success();\n\n res.status(200).json({ status: 'cancelled' });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .post('/v2/tasks/:taskId/retry', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n request: req,\n meta: {\n actionType: 'retry',\n taskId: taskId,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n // Requires both read and cancel permissions\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission, taskReadPermission],\n permissionService: permissions,\n });\n\n await auditorEvent?.success();\n\n await taskBroker.retry?.(taskId);\n res.status(201).json({ id: taskId });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks/:taskId/eventstream', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'stream',\n taskId: taskId,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const after =\n req.query.after !== undefined ? Number(req.query.after) : undefined;\n\n logger.debug(`Event stream observing taskId '${taskId}' opened`);\n\n // Mandatory headers and http status to keep connection open\n res.writeHead(200, {\n Connection: 'keep-alive',\n 'Cache-Control': 'no-cache',\n 'Content-Type': 'text/event-stream',\n });\n\n // After client opens connection send all events as string\n const subscription = taskBroker.event$({ taskId, after }).subscribe({\n error: async error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n await auditorEvent?.fail({ error: error });\n res.end();\n },\n next: ({ events }) => {\n let shouldUnsubscribe = false;\n for (const event of events) {\n res.write(\n `event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`,\n );\n if (event.type === 'completion' && !event.isTaskRecoverable) {\n shouldUnsubscribe = true;\n }\n }\n // res.flush() is only available with the compression middleware\n res.flush?.();\n if (shouldUnsubscribe) {\n subscription.unsubscribe();\n res.end();\n }\n },\n });\n\n // When client closes connection we update the clients list\n // avoiding the disconnected one\n req.on('close', async () => {\n subscription.unsubscribe();\n logger.debug(`Event stream observing taskId '${taskId}' closed`);\n await auditorEvent?.success();\n });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .get('/v2/tasks/:taskId/events', async (req, res) => {\n const { taskId } = req.params;\n\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'events',\n taskId: taskId,\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n });\n\n const after = Number(req.query.after) || undefined;\n\n // cancel the request after 30 seconds. this aligns with the recommendations of RFC 6202.\n const timeout = setTimeout(() => {\n res.json([]);\n }, 30_000);\n\n // Get all known events after an id (always includes the completion event) and return the first callback\n const subscription = taskBroker.event$({ taskId, after }).subscribe({\n error: async error => {\n logger.error(\n `Received error from event stream when observing taskId '${taskId}', ${error}`,\n );\n await auditorEvent?.fail({ error: error });\n },\n next: async ({ events }) => {\n clearTimeout(timeout);\n subscription.unsubscribe();\n await auditorEvent?.success();\n res.json(events);\n },\n });\n\n // When client closes connection we update the clients list\n // avoiding the disconnected one\n req.on('close', () => {\n subscription.unsubscribe();\n clearTimeout(timeout);\n });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .post('/v2/dry-run', async (req, res) => {\n const auditorEvent = await auditor?.createEvent({\n eventId: 'task',\n request: req,\n meta: {\n actionType: 'dry-run',\n },\n });\n\n try {\n const credentials = await httpAuth.credentials(req);\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission],\n permissionService: permissions,\n });\n\n const bodySchema = z.object({\n template: z.unknown(),\n values: z.record(z.unknown()),\n secrets: z.record(z.string()).optional(),\n directoryContents: z.array(\n z.object({ path: z.string(), base64Content: z.string() }),\n ),\n });\n const body = await bodySchema.parseAsync(req.body).catch(e => {\n throw new InputError(`Malformed request: ${e}`);\n });\n\n const template = body.template as TemplateEntityV1beta3;\n if (!(await templateEntityV1beta3Validator.check(template))) {\n throw new InputError('Input template is not a template');\n }\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalogClient.getEntityByRef(userEntityRef, { token })\n : undefined;\n\n const templateRef: string = `${template.kind}:${\n template.metadata.namespace || 'default'\n }/${template.metadata.name}`;\n\n for (const parameters of [template.spec.parameters ?? []].flat()) {\n const result = validate(body.values, parameters);\n if (!result.valid) {\n await auditorEvent?.fail({\n // TODO(Rugvip): Seems like there aren't proper types for AggregateError yet\n error: (AggregateError as any)(\n result.errors,\n 'Could not execute dry run',\n ),\n meta: {\n templateRef: templateRef,\n parameters: template.spec.parameters,\n },\n });\n\n res.status(400).json({ errors: result.errors });\n return;\n }\n }\n\n const steps = template.spec.steps.map((step, index) => ({\n ...step,\n id: step.id ?? `step-${index + 1}`,\n name: step.name ?? step.action,\n }));\n\n const dryRunId = uuid();\n const contentsPath = resolveSafeChildPath(\n workingDirectory,\n `dry-run-content-${dryRunId}`,\n );\n const templateInfo = {\n entityRef: 'template:default/dry-run',\n entity: {\n metadata: template.metadata,\n },\n baseUrl: pathToFileURL(\n resolveSafeChildPath(contentsPath, 'template.yaml'),\n ).toString(),\n };\n\n const result = await dryRunner({\n spec: {\n apiVersion: template.apiVersion,\n steps,\n output: template.spec.output ?? {},\n parameters: body.values as JsonObject,\n user: {\n entity: userEntity as UserEntity,\n ref: userEntityRef,\n },\n },\n templateInfo: templateInfo,\n directoryContents: (body.directoryContents ?? []).map(file => ({\n path: file.path,\n content: Buffer.from(file.base64Content, 'base64'),\n })),\n secrets: {\n ...body.secrets,\n ...(token && { backstageToken: token }),\n },\n credentials,\n });\n\n await auditorEvent?.success({\n meta: {\n templateRef: templateRef,\n parameters: template.spec.parameters,\n },\n });\n\n res.status(200).json({\n ...result,\n steps,\n directoryContents: result.directoryContents.map(file => ({\n path: file.path,\n executable: file.executable,\n base64Content: file.content.toString('base64'),\n })),\n });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n })\n .post('/v2/autocomplete/:provider/:resource', async (req, res) => {\n const { token, context } = req.body;\n const { provider, resource } = req.params;\n\n if (!token) throw new InputError('Missing token query parameter');\n\n if (!autocompleteHandlers[provider]) {\n throw new InputError(`Unsupported provider: ${provider}`);\n }\n\n const { results } = await autocompleteHandlers[provider]({\n resource,\n token,\n context,\n });\n\n res.status(200).json({ results });\n });\n\n const app = express();\n app.set('logger', logger);\n app.use('/', router);\n\n async function authorizeTemplate(\n entityRef: CompoundEntityRef,\n token: string | undefined,\n credentials: BackstageCredentials,\n ) {\n const template = await findTemplate({\n catalogApi: catalogClient,\n entityRef,\n token,\n });\n\n if (!isSupportedTemplate(template)) {\n throw new InputError(\n `Unsupported apiVersion field in schema entity, ${\n (template as Entity).apiVersion\n }`,\n );\n }\n\n if (!permissions) {\n return template;\n }\n\n const [parameterDecision, stepDecision] =\n await permissions.authorizeConditional(\n [\n { permission: templateParameterReadPermission },\n { permission: templateStepReadPermission },\n ],\n { credentials },\n );\n\n // Authorize parameters\n if (Array.isArray(template.spec.parameters)) {\n template.spec.parameters = template.spec.parameters.filter(step =>\n isAuthorized(parameterDecision, step),\n );\n } else if (\n template.spec.parameters &&\n !isAuthorized(parameterDecision, template.spec.parameters)\n ) {\n template.spec.parameters = undefined;\n }\n\n // Authorize steps\n template.spec.steps = template.spec.steps.filter(step =>\n isAuthorized(stepDecision, step),\n );\n\n return template;\n }\n\n return app;\n}\n"],"names":["RESOURCE_TYPE_SCAFFOLDER_TEMPLATE","RESOURCE_TYPE_SCAFFOLDER_ACTION","parseEntityRef","stringifyError","config","readDurationFromConfig","Router","express","HostDiscovery","createLegacyAuthAdapters","getWorkingDirectory","ScmIntegrations","DatabaseTaskStore","StorageTaskBroker","Duration","TemplateActionRegistry","TaskWorker","createBuiltinActions","createDryRunner","scaffolderTemplateRules","scaffolderActionRules","createConditionAuthorizer","createPermissionIntegrationRouter","scaffolderTemplatePermissions","scaffolderActionPermissions","scaffolderPermissions","checkPermission","taskCreatePermission","result","validate","getEntityBaseUrl","stringifyEntityRef","taskReadPermission","parseStringsParam","InputError","parseNumberParam","NotFoundError","taskCancelPermission","z","templateEntityV1beta3Validator","uuid","resolveSafeChildPath","pathToFileURL","findTemplate","templateParameterReadPermission","templateStepReadPermission"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-scaffolder-backend",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.30.0-next.0",
|
|
4
4
|
"description": "The Backstage backend plugin that helps you create new things",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "backend-plugin",
|
|
@@ -72,31 +72,31 @@
|
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"@backstage/backend-common": "^0.25.0",
|
|
75
|
-
"@backstage/backend-defaults": "
|
|
76
|
-
"@backstage/backend-plugin-api": "
|
|
77
|
-
"@backstage/catalog-client": "
|
|
78
|
-
"@backstage/catalog-model": "
|
|
79
|
-
"@backstage/config": "
|
|
80
|
-
"@backstage/errors": "
|
|
81
|
-
"@backstage/integration": "
|
|
82
|
-
"@backstage/plugin-auth-node": "
|
|
83
|
-
"@backstage/plugin-bitbucket-cloud-common": "
|
|
84
|
-
"@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "
|
|
85
|
-
"@backstage/plugin-catalog-node": "
|
|
86
|
-
"@backstage/plugin-events-node": "
|
|
87
|
-
"@backstage/plugin-permission-common": "
|
|
88
|
-
"@backstage/plugin-permission-node": "
|
|
89
|
-
"@backstage/plugin-scaffolder-backend-module-azure": "
|
|
90
|
-
"@backstage/plugin-scaffolder-backend-module-bitbucket": "
|
|
91
|
-
"@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "
|
|
92
|
-
"@backstage/plugin-scaffolder-backend-module-bitbucket-server": "
|
|
93
|
-
"@backstage/plugin-scaffolder-backend-module-gerrit": "
|
|
94
|
-
"@backstage/plugin-scaffolder-backend-module-gitea": "
|
|
95
|
-
"@backstage/plugin-scaffolder-backend-module-github": "
|
|
96
|
-
"@backstage/plugin-scaffolder-backend-module-gitlab": "
|
|
97
|
-
"@backstage/plugin-scaffolder-common": "
|
|
98
|
-
"@backstage/plugin-scaffolder-node": "
|
|
99
|
-
"@backstage/types": "
|
|
75
|
+
"@backstage/backend-defaults": "0.8.0-next.0",
|
|
76
|
+
"@backstage/backend-plugin-api": "1.2.0-next.0",
|
|
77
|
+
"@backstage/catalog-client": "1.9.1",
|
|
78
|
+
"@backstage/catalog-model": "1.7.3",
|
|
79
|
+
"@backstage/config": "1.3.2",
|
|
80
|
+
"@backstage/errors": "1.2.7",
|
|
81
|
+
"@backstage/integration": "1.16.1",
|
|
82
|
+
"@backstage/plugin-auth-node": "0.5.7-next.0",
|
|
83
|
+
"@backstage/plugin-bitbucket-cloud-common": "0.2.27",
|
|
84
|
+
"@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.5-next.0",
|
|
85
|
+
"@backstage/plugin-catalog-node": "1.15.2-next.0",
|
|
86
|
+
"@backstage/plugin-events-node": "0.4.8-next.0",
|
|
87
|
+
"@backstage/plugin-permission-common": "0.8.4",
|
|
88
|
+
"@backstage/plugin-permission-node": "0.8.8-next.0",
|
|
89
|
+
"@backstage/plugin-scaffolder-backend-module-azure": "0.2.6-next.0",
|
|
90
|
+
"@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.7-next.0",
|
|
91
|
+
"@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.6-next.0",
|
|
92
|
+
"@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.6-next.0",
|
|
93
|
+
"@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.6-next.0",
|
|
94
|
+
"@backstage/plugin-scaffolder-backend-module-gitea": "0.2.6-next.0",
|
|
95
|
+
"@backstage/plugin-scaffolder-backend-module-github": "0.5.6-next.0",
|
|
96
|
+
"@backstage/plugin-scaffolder-backend-module-gitlab": "0.7.2-next.0",
|
|
97
|
+
"@backstage/plugin-scaffolder-common": "1.5.9",
|
|
98
|
+
"@backstage/plugin-scaffolder-node": "0.7.0-next.0",
|
|
99
|
+
"@backstage/types": "1.2.1",
|
|
100
100
|
"@opentelemetry/api": "^1.9.0",
|
|
101
101
|
"@types/express": "^4.17.6",
|
|
102
102
|
"@types/luxon": "^3.0.0",
|
|
@@ -126,11 +126,11 @@
|
|
|
126
126
|
"zod": "^3.22.4"
|
|
127
127
|
},
|
|
128
128
|
"devDependencies": {
|
|
129
|
-
"@backstage/backend-app-api": "
|
|
130
|
-
"@backstage/backend-defaults": "
|
|
131
|
-
"@backstage/backend-test-utils": "
|
|
132
|
-
"@backstage/cli": "
|
|
133
|
-
"@backstage/plugin-scaffolder-node-test-utils": "
|
|
129
|
+
"@backstage/backend-app-api": "1.1.2-next.0",
|
|
130
|
+
"@backstage/backend-defaults": "0.8.0-next.0",
|
|
131
|
+
"@backstage/backend-test-utils": "1.3.0-next.0",
|
|
132
|
+
"@backstage/cli": "0.30.0-next.0",
|
|
133
|
+
"@backstage/plugin-scaffolder-node-test-utils": "0.1.19-next.0",
|
|
134
134
|
"@types/fs-extra": "^11.0.0",
|
|
135
135
|
"@types/nunjucks": "^3.1.4",
|
|
136
136
|
"@types/supertest": "^2.0.8",
|