@backstage/plugin-scaffolder-backend 4.1.0 → 4.2.0-next.1
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 +33 -17
- package/README.md +23 -0
- package/config.schema.json +64 -4
- package/dist/actions/createDryRunTemplateAction.cjs.js +2 -0
- package/dist/actions/createDryRunTemplateAction.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/DatabaseTaskStore.cjs.js +60 -36
- package/dist/scaffolder/tasks/DatabaseTaskStore.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js +52 -12
- package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js +53 -29
- package/dist/scaffolder/tasks/StorageTaskBroker.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/TaskWorker.cjs.js +14 -4
- package/dist/scaffolder/tasks/TaskWorker.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/WorkspaceService.cjs.js +26 -18
- package/dist/scaffolder/tasks/WorkspaceService.cjs.js.map +1 -1
- package/dist/scaffolder/tasks/taskRecoveryHelper.cjs.js +4 -0
- package/dist/scaffolder/tasks/taskRecoveryHelper.cjs.js.map +1 -1
- package/dist/service/router.cjs.js +5 -2
- package/dist/service/router.cjs.js.map +1 -1
- package/package.json +20 -20
- package/dist/scaffolder/tasks/DatabaseWorkspaceProvider.cjs.js +0 -23
- package/dist/scaffolder/tasks/DatabaseWorkspaceProvider.cjs.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskWorker.cjs.js","sources":["../../../src/scaffolder/tasks/TaskWorker.ts"],"sourcesContent":["/*\n * Copyright 2021 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 { AuditorService, LoggerService } from '@backstage/backend-plugin-api';\nimport type { MetricsService } from '@backstage/backend-plugin-api/alpha';\nimport { InputError, stringifyError, toError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport {\n TaskBroker,\n TaskContext,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport PQueue from 'p-queue';\nimport { TemplateActionRegistry } from '../actions/TemplateActionRegistry';\nimport { NunjucksWorkflowRunner } from './NunjucksWorkflowRunner';\nimport { WorkflowRunner } from './types';\nimport { setTimeout } from 'node:timers/promises';\nimport { JsonObject } from '@backstage/types';\nimport { Config } from '@backstage/config';\nimport { collectTemplateCapabilities } from '../../util/templating';\n\nconst DEFAULT_TASK_PARAMETER_MAX_LENGTH = 256;\n\n/**\n * TaskWorkerOptions\n */\nexport type TaskWorkerOptions = {\n taskBroker: TaskBroker;\n runners: {\n workflowRunner: WorkflowRunner;\n };\n concurrentTasksLimit: number;\n permissions?: PermissionEvaluator;\n logger?: LoggerService;\n auditor?: AuditorService;\n config?: Config;\n gracefulShutdown?: boolean;\n};\n\n/**\n * CreateWorkerOptions\n */\nexport type CreateWorkerOptions = {\n taskBroker: TaskBroker;\n actionRegistry: TemplateActionRegistry;\n integrations: ScmIntegrations;\n workingDirectory: string;\n logger: LoggerService;\n auditor?: AuditorService;\n config?: Config;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n /**\n * The number of tasks that can be executed at the same time by the worker\n * @defaultValue 10\n * @example\n * ```\n * {\n * concurrentTasksLimit: 1,\n * // OR\n * concurrentTasksLimit: Infinity\n * }\n * ```\n */\n concurrentTasksLimit?: number;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n permissions?: PermissionEvaluator;\n gracefulShutdown?: boolean;\n metrics: MetricsService;\n};\n\n/**\n * TaskWorker\n */\nexport class TaskWorker {\n private taskQueue: PQueue;\n private logger: LoggerService | undefined;\n private auditor: AuditorService | undefined;\n private parameterAuditTransform: ParameterAuditTransform;\n private stopWorkers: boolean;\n\n private readonly options: TaskWorkerOptions & {\n parameterAuditTransform: ParameterAuditTransform;\n };\n\n private constructor(\n options: TaskWorkerOptions & {\n parameterAuditTransform: ParameterAuditTransform;\n },\n ) {\n this.options = options;\n this.stopWorkers = false;\n this.logger = options.logger;\n this.auditor = options.auditor;\n this.taskQueue = new PQueue({\n concurrency: options.concurrentTasksLimit,\n });\n this.parameterAuditTransform = options.parameterAuditTransform;\n }\n\n static async create(options: CreateWorkerOptions): Promise<TaskWorker> {\n const {\n taskBroker,\n logger,\n auditor,\n config,\n actionRegistry,\n integrations,\n workingDirectory,\n additionalTemplateFilters,\n concurrentTasksLimit = 10, // from 1 to Infinity\n additionalTemplateGlobals,\n permissions,\n gracefulShutdown,\n metrics,\n } = options;\n\n const workflowRunner = new NunjucksWorkflowRunner({\n actionRegistry,\n integrations,\n logger,\n auditor,\n workingDirectory,\n templateCapabilities: collectTemplateCapabilities({\n filters: additionalTemplateFilters,\n globals: additionalTemplateGlobals,\n }),\n permissions,\n config,\n metrics,\n });\n\n return new TaskWorker({\n taskBroker: taskBroker,\n runners: { workflowRunner },\n concurrentTasksLimit,\n permissions,\n auditor,\n config,\n gracefulShutdown,\n parameterAuditTransform: createParameterTruncator(config),\n });\n }\n\n async recoverTasks() {\n try {\n await this.options.taskBroker.recoverTasks?.();\n } catch (err) {\n this.logger?.error(stringifyError(err));\n }\n }\n\n start() {\n (async () => {\n while (!this.stopWorkers) {\n await setTimeout(10000);\n await this.recoverTasks();\n }\n })();\n (async () => {\n while (!this.stopWorkers) {\n await this.onReadyToClaimTask();\n if (!this.stopWorkers) {\n const task = await this.options.taskBroker.claim();\n void this.taskQueue.add(() => this.runOneTask(task));\n }\n }\n })();\n }\n\n async stop() {\n this.stopWorkers = true;\n if (this.options?.gracefulShutdown) {\n while (this.taskQueue.size > 0) {\n await setTimeout(1000);\n }\n }\n }\n\n protected onReadyToClaimTask(): Promise<void> {\n if (this.taskQueue.pending < this.options.concurrentTasksLimit) {\n return Promise.resolve();\n }\n return new Promise(resolve => {\n // \"next\" event emits when a task completes\n // https://github.com/sindresorhus/p-queue#next\n this.taskQueue.once('next', () => {\n resolve();\n });\n });\n }\n\n async runOneTask(task: TaskContext) {\n const auditorEvent = await this.auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n meta: {\n actionType: 'execution',\n createdBy: task.createdBy,\n taskId: task.taskId,\n taskParameters: this.parameterAuditTransform(task.spec.parameters),\n templateRef: task.spec.templateInfo?.entityRef,\n },\n });\n\n try {\n if (task.spec.apiVersion !== 'scaffolder.backstage.io/v1beta3') {\n throw new Error(\n `Unsupported Template apiVersion ${task.spec.apiVersion}`,\n );\n }\n\n const { output } = await this.options.runners.workflowRunner.execute(\n task,\n );\n\n await task.complete('completed', { output });\n await auditorEvent?.success();\n } catch (error) {\n const err = toError(error);\n await auditorEvent?.fail({\n error: err,\n });\n await task.complete('failed', {\n error: { name: err.name, message: err.message },\n });\n }\n }\n}\n\ntype ParameterAuditTransform = (parameters: JsonObject) => JsonObject;\n\n/**\n * Truncates task parameters for audit logging using the configured max length.\n * @internal\n */\nexport function createParameterTruncator(\n config?: Config,\n): ParameterAuditTransform {\n const maxLength =\n config?.getOptionalNumber('scaffolder.auditor.taskParameterMaxLength') ??\n DEFAULT_TASK_PARAMETER_MAX_LENGTH;\n\n if (!Number.isSafeInteger(maxLength) || maxLength < -1) {\n throw new InputError(\n `Invalid configuration for 'scaffolder.auditor.taskParameterMaxLength', got ${maxLength}. Must be a positive integer or -1 to disable truncation.`,\n );\n }\n\n if (maxLength === -1) {\n return (parameters: JsonObject) => parameters;\n }\n\n return (parameters: JsonObject) => {\n function truncate(value: unknown): unknown {\n if (typeof value === 'string') {\n if (value.length > maxLength) {\n return value.slice(0, maxLength).concat('...<truncated>');\n }\n return value;\n }\n if (Array.isArray(value)) {\n return value.map(truncate);\n }\n if (value && typeof value === 'object') {\n const result: Record<string, unknown> = {};\n for (const k in value as object) {\n if (Object.hasOwn(value, k)) {\n result[k] = truncate((value as any)[k]);\n }\n }\n return result;\n }\n return value;\n }\n\n return truncate(parameters) as JsonObject;\n };\n}\n"],"names":["PQueue","NunjucksWorkflowRunner","collectTemplateCapabilities","stringifyError","setTimeout","toError","InputError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TaskWorker.cjs.js","sources":["../../../src/scaffolder/tasks/TaskWorker.ts"],"sourcesContent":["/*\n * Copyright 2021 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 { AuditorService, LoggerService } from '@backstage/backend-plugin-api';\nimport type { MetricsService } from '@backstage/backend-plugin-api/alpha';\nimport { InputError, stringifyError, toError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport {\n TaskBroker,\n TaskContext,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport PQueue from 'p-queue';\nimport { TemplateActionRegistry } from '../actions/TemplateActionRegistry';\nimport { NunjucksWorkflowRunner } from './NunjucksWorkflowRunner';\nimport { WorkflowRunner } from './types';\nimport { setTimeout } from 'node:timers/promises';\nimport { JsonObject } from '@backstage/types';\nimport { Config } from '@backstage/config';\nimport { collectTemplateCapabilities } from '../../util/templating';\n\nconst DEFAULT_TASK_PARAMETER_MAX_LENGTH = 256;\n\n/** How long to wait before trying to claim again after a failed claim. */\nconst CLAIM_RETRY_DELAY_MS = 1000;\n\n/**\n * TaskWorkerOptions\n */\nexport type TaskWorkerOptions = {\n taskBroker: TaskBroker;\n runners: {\n workflowRunner: WorkflowRunner;\n };\n concurrentTasksLimit: number;\n permissions?: PermissionEvaluator;\n logger?: LoggerService;\n auditor?: AuditorService;\n config?: Config;\n gracefulShutdown?: boolean;\n};\n\n/**\n * CreateWorkerOptions\n */\nexport type CreateWorkerOptions = {\n taskBroker: TaskBroker;\n actionRegistry: TemplateActionRegistry;\n integrations: ScmIntegrations;\n workingDirectory: string;\n logger: LoggerService;\n auditor?: AuditorService;\n config?: Config;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n /**\n * The number of tasks that can be executed at the same time by the worker\n * @defaultValue 10\n * @example\n * ```\n * {\n * concurrentTasksLimit: 1,\n * // OR\n * concurrentTasksLimit: Infinity\n * }\n * ```\n */\n concurrentTasksLimit?: number;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n permissions?: PermissionEvaluator;\n gracefulShutdown?: boolean;\n metrics: MetricsService;\n};\n\n/**\n * TaskWorker\n */\nexport class TaskWorker {\n private taskQueue: PQueue;\n private logger: LoggerService | undefined;\n private auditor: AuditorService | undefined;\n private parameterAuditTransform: ParameterAuditTransform;\n private stopWorkers: boolean;\n\n private readonly options: TaskWorkerOptions & {\n parameterAuditTransform: ParameterAuditTransform;\n };\n\n private constructor(\n options: TaskWorkerOptions & {\n parameterAuditTransform: ParameterAuditTransform;\n },\n ) {\n this.options = options;\n this.stopWorkers = false;\n this.logger = options.logger;\n this.auditor = options.auditor;\n this.taskQueue = new PQueue({\n concurrency: options.concurrentTasksLimit,\n });\n this.parameterAuditTransform = options.parameterAuditTransform;\n }\n\n static async create(options: CreateWorkerOptions): Promise<TaskWorker> {\n const {\n taskBroker,\n logger,\n auditor,\n config,\n actionRegistry,\n integrations,\n workingDirectory,\n additionalTemplateFilters,\n concurrentTasksLimit = 10, // from 1 to Infinity\n additionalTemplateGlobals,\n permissions,\n gracefulShutdown,\n metrics,\n } = options;\n\n const workflowRunner = new NunjucksWorkflowRunner({\n actionRegistry,\n integrations,\n logger,\n auditor,\n workingDirectory,\n templateCapabilities: collectTemplateCapabilities({\n filters: additionalTemplateFilters,\n globals: additionalTemplateGlobals,\n }),\n permissions,\n config,\n metrics,\n });\n\n return new TaskWorker({\n taskBroker: taskBroker,\n runners: { workflowRunner },\n concurrentTasksLimit,\n permissions,\n auditor,\n config,\n gracefulShutdown,\n parameterAuditTransform: createParameterTruncator(config),\n });\n }\n\n async recoverTasks() {\n try {\n await this.options.taskBroker.recoverTasks?.();\n } catch (err) {\n this.logger?.error(stringifyError(err));\n }\n }\n\n start() {\n (async () => {\n while (!this.stopWorkers) {\n await setTimeout(10000);\n await this.recoverTasks();\n }\n })();\n (async () => {\n while (!this.stopWorkers) {\n try {\n await this.onReadyToClaimTask();\n if (!this.stopWorkers) {\n const task = await this.options.taskBroker.claim();\n void this.taskQueue.add(() => this.runOneTask(task));\n }\n } catch (err) {\n // Without this the loop exits on the first rejection and the worker\n // stops claiming tasks for the rest of the process lifetime, leaving\n // every new task queued with no indication that anything is wrong.\n this.logger?.error(\n `Failed to claim task, retrying in ${CLAIM_RETRY_DELAY_MS}ms; caused by ${stringifyError(\n err,\n )}`,\n );\n await setTimeout(CLAIM_RETRY_DELAY_MS);\n }\n }\n })();\n }\n\n async stop() {\n this.stopWorkers = true;\n if (this.options?.gracefulShutdown) {\n while (this.taskQueue.size > 0) {\n await setTimeout(1000);\n }\n }\n }\n\n protected onReadyToClaimTask(): Promise<void> {\n if (this.taskQueue.pending < this.options.concurrentTasksLimit) {\n return Promise.resolve();\n }\n return new Promise(resolve => {\n // \"next\" event emits when a task completes\n // https://github.com/sindresorhus/p-queue#next\n this.taskQueue.once('next', () => {\n resolve();\n });\n });\n }\n\n async runOneTask(task: TaskContext) {\n const auditorEvent = await this.auditor?.createEvent({\n eventId: 'task',\n severityLevel: 'medium',\n meta: {\n actionType: 'execution',\n createdBy: task.createdBy,\n taskId: task.taskId,\n taskParameters: this.parameterAuditTransform(task.spec.parameters),\n templateRef: task.spec.templateInfo?.entityRef,\n },\n });\n\n try {\n if (task.spec.apiVersion !== 'scaffolder.backstage.io/v1beta3') {\n throw new Error(\n `Unsupported Template apiVersion ${task.spec.apiVersion}`,\n );\n }\n\n const { output } = await this.options.runners.workflowRunner.execute(\n task,\n );\n\n await task.complete('completed', { output });\n await auditorEvent?.success();\n } catch (error) {\n const err = toError(error);\n await auditorEvent?.fail({\n error: err,\n });\n await task.complete('failed', {\n error: { name: err.name, message: err.message },\n });\n }\n }\n}\n\ntype ParameterAuditTransform = (parameters: JsonObject) => JsonObject;\n\n/**\n * Truncates task parameters for audit logging using the configured max length.\n * @internal\n */\nexport function createParameterTruncator(\n config?: Config,\n): ParameterAuditTransform {\n const maxLength =\n config?.getOptionalNumber('scaffolder.auditor.taskParameterMaxLength') ??\n DEFAULT_TASK_PARAMETER_MAX_LENGTH;\n\n if (!Number.isSafeInteger(maxLength) || maxLength < -1) {\n throw new InputError(\n `Invalid configuration for 'scaffolder.auditor.taskParameterMaxLength', got ${maxLength}. Must be a positive integer or -1 to disable truncation.`,\n );\n }\n\n if (maxLength === -1) {\n return (parameters: JsonObject) => parameters;\n }\n\n return (parameters: JsonObject) => {\n function truncate(value: unknown): unknown {\n if (typeof value === 'string') {\n if (value.length > maxLength) {\n return value.slice(0, maxLength).concat('...<truncated>');\n }\n return value;\n }\n if (Array.isArray(value)) {\n return value.map(truncate);\n }\n if (value && typeof value === 'object') {\n const result: Record<string, unknown> = {};\n for (const k in value as object) {\n if (Object.hasOwn(value, k)) {\n result[k] = truncate((value as any)[k]);\n }\n }\n return result;\n }\n return value;\n }\n\n return truncate(parameters) as JsonObject;\n };\n}\n"],"names":["PQueue","NunjucksWorkflowRunner","collectTemplateCapabilities","stringifyError","setTimeout","toError","InputError"],"mappings":"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"}
|
|
@@ -1,30 +1,42 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var DatabaseWorkspaceProvider = require('./DatabaseWorkspaceProvider.cjs.js');
|
|
4
3
|
var fs = require('fs-extra');
|
|
5
4
|
|
|
6
5
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
7
6
|
|
|
8
7
|
var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
9
8
|
|
|
9
|
+
function resolveWorkspaceProvider(workspaceProviders, config) {
|
|
10
|
+
const legacySerializationEnabled = config?.getOptionalBoolean(
|
|
11
|
+
"scaffolder.EXPERIMENTAL_workspaceSerialization"
|
|
12
|
+
) ?? false;
|
|
13
|
+
const providerName = config?.getOptionalString("scaffolder.taskRecovery.workspaceProvider") ?? (legacySerializationEnabled ? config?.getOptionalString(
|
|
14
|
+
"scaffolder.EXPERIMENTAL_workspaceSerializationProvider"
|
|
15
|
+
) ?? "database" : void 0);
|
|
16
|
+
if (!providerName) {
|
|
17
|
+
return void 0;
|
|
18
|
+
}
|
|
19
|
+
const workspaceProvider = workspaceProviders && Object.prototype.hasOwnProperty.call(workspaceProviders, providerName) ? workspaceProviders[providerName] : void 0;
|
|
20
|
+
if (!workspaceProvider) {
|
|
21
|
+
const databaseProviderGuidance = providerName === "database" ? ` For database storage, add '@backstage/plugin-scaffolder-backend-module-workspace-database'. When running in production, also set 'scaffolder.taskRecovery.database.dangerouslyEnableInProduction' to true.` : "";
|
|
22
|
+
throw new Error(
|
|
23
|
+
`Workspace provider '${providerName}' is configured but not available. Make sure to install and register the corresponding module.${databaseProviderGuidance}`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
return workspaceProvider;
|
|
27
|
+
}
|
|
10
28
|
class DefaultWorkspaceService {
|
|
11
|
-
static create(task,
|
|
12
|
-
|
|
13
|
-
"scaffolder.EXPERIMENTAL_workspaceSerializationProvider"
|
|
14
|
-
) ?? "database";
|
|
15
|
-
const workspaceProvider = additionalWorkspaceProviders?.[workspaceProviderName] ?? DatabaseWorkspaceProvider.DatabaseWorkspaceProvider.create(storage);
|
|
16
|
-
return new DefaultWorkspaceService(task, workspaceProvider, config);
|
|
29
|
+
static create(task, workspaceProvider) {
|
|
30
|
+
return new DefaultWorkspaceService(task, workspaceProvider);
|
|
17
31
|
}
|
|
18
32
|
task;
|
|
19
33
|
workspaceProvider;
|
|
20
|
-
|
|
21
|
-
constructor(task, workspaceProvider, config) {
|
|
34
|
+
constructor(task, workspaceProvider) {
|
|
22
35
|
this.task = task;
|
|
23
36
|
this.workspaceProvider = workspaceProvider;
|
|
24
|
-
this.config = config;
|
|
25
37
|
}
|
|
26
38
|
async serializeWorkspace(options) {
|
|
27
|
-
if (this.
|
|
39
|
+
if (this.workspaceProvider) {
|
|
28
40
|
await this.workspaceProvider.serializeWorkspace({
|
|
29
41
|
path: options.path,
|
|
30
42
|
taskId: this.task.taskId
|
|
@@ -32,22 +44,18 @@ class DefaultWorkspaceService {
|
|
|
32
44
|
}
|
|
33
45
|
}
|
|
34
46
|
async cleanWorkspace() {
|
|
35
|
-
if (this.
|
|
47
|
+
if (this.workspaceProvider) {
|
|
36
48
|
await this.workspaceProvider.cleanWorkspace({ taskId: this.task.taskId });
|
|
37
49
|
}
|
|
38
50
|
}
|
|
39
51
|
async rehydrateWorkspace(options) {
|
|
40
|
-
if (this.
|
|
52
|
+
if (this.workspaceProvider) {
|
|
41
53
|
await fs__default.default.mkdirp(options.targetPath);
|
|
42
54
|
await this.workspaceProvider.rehydrateWorkspace(options);
|
|
43
55
|
}
|
|
44
56
|
}
|
|
45
|
-
isWorkspaceSerializationEnabled() {
|
|
46
|
-
return this.config?.getOptionalBoolean(
|
|
47
|
-
"scaffolder.EXPERIMENTAL_workspaceSerialization"
|
|
48
|
-
) ?? false;
|
|
49
|
-
}
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
exports.DefaultWorkspaceService = DefaultWorkspaceService;
|
|
60
|
+
exports.resolveWorkspaceProvider = resolveWorkspaceProvider;
|
|
53
61
|
//# sourceMappingURL=WorkspaceService.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkspaceService.cjs.js","sources":["../../../src/scaffolder/tasks/WorkspaceService.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { Config } from '@backstage/config';\nimport { CurrentClaimedTask } from './StorageTaskBroker';\nimport { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha';\nimport
|
|
1
|
+
{"version":3,"file":"WorkspaceService.cjs.js","sources":["../../../src/scaffolder/tasks/WorkspaceService.ts"],"sourcesContent":["/*\n * Copyright 2024 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 type { Config } from '@backstage/config';\nimport type { CurrentClaimedTask } from './StorageTaskBroker';\nimport type { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha';\nimport fs from 'fs-extra';\n\nexport interface WorkspaceService {\n serializeWorkspace(options: { path: string }): Promise<void>;\n\n cleanWorkspace(): Promise<void>;\n\n rehydrateWorkspace(options: {\n taskId: string;\n targetPath: string;\n }): Promise<void>;\n}\n\nexport function resolveWorkspaceProvider(\n workspaceProviders?: Record<string, WorkspaceProvider>,\n config?: Config,\n): WorkspaceProvider | undefined {\n const legacySerializationEnabled =\n config?.getOptionalBoolean(\n 'scaffolder.EXPERIMENTAL_workspaceSerialization',\n ) ?? false;\n const providerName =\n config?.getOptionalString('scaffolder.taskRecovery.workspaceProvider') ??\n (legacySerializationEnabled\n ? config?.getOptionalString(\n 'scaffolder.EXPERIMENTAL_workspaceSerializationProvider',\n ) ?? 'database'\n : undefined);\n\n if (!providerName) {\n return undefined;\n }\n\n const workspaceProvider =\n workspaceProviders &&\n Object.prototype.hasOwnProperty.call(workspaceProviders, providerName)\n ? workspaceProviders[providerName]\n : undefined;\n\n if (!workspaceProvider) {\n const databaseProviderGuidance =\n providerName === 'database'\n ? ` For database storage, add '@backstage/plugin-scaffolder-backend-module-workspace-database'. ` +\n `When running in production, also set ` +\n `'scaffolder.taskRecovery.database.dangerouslyEnableInProduction' to true.`\n : '';\n throw new Error(\n `Workspace provider '${providerName}' is configured but not available. Make sure to install and register the corresponding module.${databaseProviderGuidance}`,\n );\n }\n\n return workspaceProvider;\n}\n\nexport class DefaultWorkspaceService implements WorkspaceService {\n static create(\n task: CurrentClaimedTask,\n workspaceProvider?: WorkspaceProvider,\n ) {\n return new DefaultWorkspaceService(task, workspaceProvider);\n }\n\n private readonly task: CurrentClaimedTask;\n private readonly workspaceProvider?: WorkspaceProvider;\n\n private constructor(\n task: CurrentClaimedTask,\n workspaceProvider: WorkspaceProvider | undefined,\n ) {\n this.task = task;\n this.workspaceProvider = workspaceProvider;\n }\n\n public async serializeWorkspace(options: { path: string }): Promise<void> {\n if (this.workspaceProvider) {\n await this.workspaceProvider.serializeWorkspace({\n path: options.path,\n taskId: this.task.taskId,\n });\n }\n }\n\n public async cleanWorkspace(): Promise<void> {\n if (this.workspaceProvider) {\n await this.workspaceProvider.cleanWorkspace({ taskId: this.task.taskId });\n }\n }\n\n public async rehydrateWorkspace(options: {\n taskId: string;\n targetPath: string;\n }): Promise<void> {\n if (this.workspaceProvider) {\n await fs.mkdirp(options.targetPath);\n await this.workspaceProvider.rehydrateWorkspace(options);\n }\n }\n}\n"],"names":["fs"],"mappings":";;;;;;;;AAgCO,SAAS,wBAAA,CACd,oBACA,MAAA,EAC+B;AAC/B,EAAA,MAAM,6BACJ,MAAA,EAAQ,kBAAA;AAAA,IACN;AAAA,GACF,IAAK,KAAA;AACP,EAAA,MAAM,eACJ,MAAA,EAAQ,iBAAA,CAAkB,2CAA2C,CAAA,KACpE,6BACG,MAAA,EAAQ,iBAAA;AAAA,IACN;AAAA,OACG,UAAA,GACL,MAAA,CAAA;AAEN,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,iBAAA,GACJ,kBAAA,IACA,MAAA,CAAO,SAAA,CAAU,cAAA,CAAe,IAAA,CAAK,kBAAA,EAAoB,YAAY,CAAA,GACjE,kBAAA,CAAmB,YAAY,CAAA,GAC/B,MAAA;AAEN,EAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,IAAA,MAAM,wBAAA,GACJ,YAAA,KAAiB,UAAA,GACb,CAAA,2MAAA,CAAA,GAGA,EAAA;AACN,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,oBAAA,EAAuB,YAAY,CAAA,8FAAA,EAAiG,wBAAwB,CAAA;AAAA,KAC9J;AAAA,EACF;AAEA,EAAA,OAAO,iBAAA;AACT;AAEO,MAAM,uBAAA,CAAoD;AAAA,EAC/D,OAAO,MAAA,CACL,IAAA,EACA,iBAAA,EACA;AACA,IAAA,OAAO,IAAI,uBAAA,CAAwB,IAAA,EAAM,iBAAiB,CAAA;AAAA,EAC5D;AAAA,EAEiB,IAAA;AAAA,EACA,iBAAA;AAAA,EAET,WAAA,CACN,MACA,iBAAA,EACA;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,iBAAA,GAAoB,iBAAA;AAAA,EAC3B;AAAA,EAEA,MAAa,mBAAmB,OAAA,EAA0C;AACxE,IAAA,IAAI,KAAK,iBAAA,EAAmB;AAC1B,MAAA,MAAM,IAAA,CAAK,kBAAkB,kBAAA,CAAmB;AAAA,QAC9C,MAAM,OAAA,CAAQ,IAAA;AAAA,QACd,MAAA,EAAQ,KAAK,IAAA,CAAK;AAAA,OACnB,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAa,cAAA,GAAgC;AAC3C,IAAA,IAAI,KAAK,iBAAA,EAAmB;AAC1B,MAAA,MAAM,IAAA,CAAK,kBAAkB,cAAA,CAAe,EAAE,QAAQ,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA;AAAA,IAC1E;AAAA,EACF;AAAA,EAEA,MAAa,mBAAmB,OAAA,EAGd;AAChB,IAAA,IAAI,KAAK,iBAAA,EAAmB;AAC1B,MAAA,MAAMA,mBAAA,CAAG,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA;AAClC,MAAA,MAAM,IAAA,CAAK,iBAAA,CAAkB,kBAAA,CAAmB,OAAO,CAAA;AAAA,IACzD;AAAA,EACF;AACF;;;;;"}
|
|
@@ -13,6 +13,10 @@ const trimEventsTillLastRecovery = (events) => {
|
|
|
13
13
|
}
|
|
14
14
|
return { events };
|
|
15
15
|
};
|
|
16
|
+
const isTaskRecoveryEnabled = (config) => {
|
|
17
|
+
return config?.getOptionalBoolean("scaffolder.taskRecovery.enabled") ?? config?.getOptionalBoolean("scaffolder.EXPERIMENTAL_recoverTasks") ?? false;
|
|
18
|
+
};
|
|
16
19
|
|
|
20
|
+
exports.isTaskRecoveryEnabled = isTaskRecoveryEnabled;
|
|
17
21
|
exports.trimEventsTillLastRecovery = trimEventsTillLastRecovery;
|
|
18
22
|
//# sourceMappingURL=taskRecoveryHelper.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"taskRecoveryHelper.cjs.js","sources":["../../../src/scaffolder/tasks/taskRecoveryHelper.ts"],"sourcesContent":["/*\n * Copyright 2021 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 { SerializedTaskEvent } from '@backstage/plugin-scaffolder-node';\nimport { TaskRecoverStrategy } from '@backstage/plugin-scaffolder-common';\n\nexport const trimEventsTillLastRecovery = (\n events: SerializedTaskEvent[],\n): { events: SerializedTaskEvent[] } => {\n const recoveredEventInd = events\n .slice()\n .reverse()\n .findIndex(event => event.type === 'recovered');\n\n if (recoveredEventInd >= 0) {\n const ind = events.length - recoveredEventInd - 1;\n const { recoverStrategy } = events[ind].body as {\n recoverStrategy?: TaskRecoverStrategy;\n };\n if (recoverStrategy === 'startOver') {\n return {\n events: recoveredEventInd === 0 ? [] : events.slice(ind),\n };\n }\n }\n\n return { events };\n};\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"taskRecoveryHelper.cjs.js","sources":["../../../src/scaffolder/tasks/taskRecoveryHelper.ts"],"sourcesContent":["/*\n * Copyright 2021 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 { SerializedTaskEvent } from '@backstage/plugin-scaffolder-node';\nimport { Config } from '@backstage/config';\nimport { TaskRecoverStrategy } from '@backstage/plugin-scaffolder-common';\n\nexport const trimEventsTillLastRecovery = (\n events: SerializedTaskEvent[],\n): { events: SerializedTaskEvent[] } => {\n const recoveredEventInd = events\n .slice()\n .reverse()\n .findIndex(event => event.type === 'recovered');\n\n if (recoveredEventInd >= 0) {\n const ind = events.length - recoveredEventInd - 1;\n const { recoverStrategy } = events[ind].body as {\n recoverStrategy?: TaskRecoverStrategy;\n };\n if (recoverStrategy === 'startOver') {\n return {\n events: recoveredEventInd === 0 ? [] : events.slice(ind),\n };\n }\n }\n\n return { events };\n};\n\n/**\n * Resolves whether automatic task recovery is enabled, falling back to the\n * legacy `EXPERIMENTAL_recoverTasks` flag for backwards compatibility.\n */\nexport const isTaskRecoveryEnabled = (config?: Config): boolean => {\n return (\n config?.getOptionalBoolean('scaffolder.taskRecovery.enabled') ??\n config?.getOptionalBoolean('scaffolder.EXPERIMENTAL_recoverTasks') ??\n false\n );\n};\n"],"names":[],"mappings":";;AAoBO,MAAM,0BAAA,GAA6B,CACxC,MAAA,KACsC;AACtC,EAAA,MAAM,iBAAA,GAAoB,MAAA,CACvB,KAAA,EAAM,CACN,OAAA,GACA,SAAA,CAAU,CAAA,KAAA,KAAS,KAAA,CAAM,IAAA,KAAS,WAAW,CAAA;AAEhD,EAAA,IAAI,qBAAqB,CAAA,EAAG;AAC1B,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,MAAA,GAAS,iBAAA,GAAoB,CAAA;AAChD,IAAA,MAAM,EAAE,eAAA,EAAgB,GAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA;AAGxC,IAAA,IAAI,oBAAoB,WAAA,EAAa;AACnC,MAAA,OAAO;AAAA,QACL,QAAQ,iBAAA,KAAsB,CAAA,GAAI,EAAC,GAAI,MAAA,CAAO,MAAM,GAAG;AAAA,OACzD;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,MAAA,EAAO;AAClB;AAMO,MAAM,qBAAA,GAAwB,CAAC,MAAA,KAA6B;AACjE,EAAA,OACE,QAAQ,kBAAA,CAAmB,iCAAiC,KAC5D,MAAA,EAAQ,kBAAA,CAAmB,sCAAsC,CAAA,IACjE,KAAA;AAEJ;;;;;"}
|
|
@@ -43,6 +43,7 @@ var DatabaseTaskStore = require('../scaffolder/tasks/DatabaseTaskStore.cjs.js');
|
|
|
43
43
|
var StorageTaskBroker = require('../scaffolder/tasks/StorageTaskBroker.cjs.js');
|
|
44
44
|
var TaskWorker = require('../scaffolder/tasks/TaskWorker.cjs.js');
|
|
45
45
|
var createDryRunner = require('../scaffolder/dryrun/createDryRunner.cjs.js');
|
|
46
|
+
var taskRecoveryHelper = require('../scaffolder/tasks/taskRecoveryHelper.cjs.js');
|
|
46
47
|
var router = require('../schema/openapi/generated/router.cjs.js');
|
|
47
48
|
var checkPermissions = require('../util/checkPermissions.cjs.js');
|
|
48
49
|
var helpers = require('./helpers.cjs.js');
|
|
@@ -139,7 +140,8 @@ async function createRouter(options) {
|
|
|
139
140
|
if (!options.taskBroker) {
|
|
140
141
|
const databaseTaskStore = await DatabaseTaskStore.DatabaseTaskStore.create({
|
|
141
142
|
database,
|
|
142
|
-
events: eventsService
|
|
143
|
+
events: eventsService,
|
|
144
|
+
recoverTasksEnabled: taskRecoveryHelper.isTaskRecoveryEnabled(config)
|
|
143
145
|
});
|
|
144
146
|
taskBroker = new StorageTaskBroker.StorageTaskBroker(
|
|
145
147
|
databaseTaskStore,
|
|
@@ -278,6 +280,7 @@ async function createRouter(options) {
|
|
|
278
280
|
});
|
|
279
281
|
permissionsRegistry.addPermissions([
|
|
280
282
|
alpha.taskCreatePermission,
|
|
283
|
+
alpha.templateDryRunPermission,
|
|
281
284
|
alpha.templateManagementPermission
|
|
282
285
|
]);
|
|
283
286
|
router$1.get(
|
|
@@ -743,7 +746,7 @@ data: ${JSON.stringify(event)}
|
|
|
743
746
|
const credentials = await httpAuth.credentials(req);
|
|
744
747
|
await checkPermissions.checkPermission({
|
|
745
748
|
credentials,
|
|
746
|
-
permissions: [alpha.taskCreatePermission],
|
|
749
|
+
permissions: [alpha.taskCreatePermission, alpha.templateDryRunPermission],
|
|
747
750
|
permissionService: permissions$1
|
|
748
751
|
});
|
|
749
752
|
const bodySchema = v3.z.object({
|
|
@@ -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 AuditorService,\n AuditorServiceEvent,\n AuthService,\n BackstageCredentials,\n DatabaseService,\n HttpAuthService,\n LifecycleService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n resolveSafeChildPath,\n SchedulerService,\n} from '@backstage/backend-plugin-api';\nimport { validate, ValidatorResult } from 'jsonschema';\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 } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\n\nimport { EventsService } from '@backstage/plugin-events-node';\n\nimport {\n ConditionTransformer,\n createConditionAuthorizer,\n createConditionTransformer,\n} from '@backstage/plugin-permission-node';\nimport {\n TaskSpec,\n TemplateEntityV1beta3,\n templateEntityV1beta3Validator,\n} from '@backstage/plugin-scaffolder-common';\nimport {\n scaffolderActionPermissions,\n scaffolderTaskPermissions,\n scaffolderTemplatePermissions,\n taskCancelPermission,\n taskCreatePermission,\n taskReadPermission,\n templateManagementPermission,\n templateParameterReadPermission,\n templateStepReadPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport {\n TaskBroker,\n TaskFilters,\n SerializedTask,\n TaskStatus,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n CreatedTemplateFilter,\n CreatedTemplateGlobal,\n scaffolderActionPermissionResourceRef,\n scaffolderTaskPermissionResourceRef,\n scaffolderTemplatePermissionResourceRef,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport { HumanDuration, JsonObject } from '@backstage/types';\nimport express from 'express';\nimport { Duration } from 'luxon';\nimport { pathToFileURL } from 'node:url';\nimport { randomUUID as uuid } from 'node:crypto';\nimport { z } from 'zod/v3';\nimport {\n DatabaseTaskStore,\n DefaultTemplateActionRegistry,\n TaskWorker,\n} from '../scaffolder';\nimport { createDryRunner } from '../scaffolder/dryrun';\nimport { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker';\nimport { InternalTaskSecrets } from '../scaffolder/tasks/types';\nimport { createOpenApiRouter } from '../schema/openapi';\nimport type { SerializedTask as SerializedTaskResponse } from '../schema/openapi/generated/models/SerializedTask.model';\nimport {\n checkPermission,\n checkTaskPermission,\n getAuthorizeConditions,\n} from '../util/checkPermissions';\nimport {\n findTemplate,\n getEntityBaseUrl,\n getWorkingDirectory,\n parseStringsParam,\n} from './helpers';\n\nimport {\n convertFiltersToRecord,\n convertGlobalsToRecord,\n extractFilterMetadata,\n extractGlobalFunctionMetadata,\n extractGlobalValueMetadata,\n} from '../util/templating';\nimport { createDefaultFilters } from '../lib/templating/filters/createDefaultFilters';\nimport {\n ActionPermissionRuleInput,\n isActionPermissionRuleInput,\n isTaskPermissionRuleInput,\n isTemplatePermissionRuleInput,\n ScaffolderPermissionRuleInput,\n TaskPermissionRuleInput,\n TemplatePermissionRuleInput,\n} from './permissions';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\n\nimport {\n scaffolderActionRules,\n scaffolderTaskRules,\n scaffolderTemplateRules,\n} from './rules';\nimport {\n ActionsService,\n MetricsService,\n} from '@backstage/backend-plugin-api/alpha';\n\n/**\n * RouterOptions\n */\nexport interface RouterOptions {\n logger: LoggerService;\n config: Config;\n lifecycle?: LifecycleService;\n database: DatabaseService;\n catalog: CatalogService;\n scheduler?: SchedulerService;\n actions?: TemplateAction<any, any, any>[];\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?:\n | Record<string, TemplateFilter>\n | CreatedTemplateFilter<any, any>[];\n additionalTemplateGlobals?:\n | Record<string, TemplateGlobal>\n | CreatedTemplateGlobal[];\n additionalWorkspaceProviders?: Record<string, WorkspaceProvider>;\n permissions?: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n permissionRules?: Array<ScaffolderPermissionRuleInput>;\n auth: AuthService;\n httpAuth: HttpAuthService;\n events?: EventsService;\n auditor?: AuditorService;\n autocompleteHandlers?: Record<string, AutocompleteHandler>;\n actionsRegistry: ActionsService;\n metrics: MetricsService;\n}\n\nfunction isSupportedTemplate(entity: TemplateEntityV1beta3) {\n return entity.apiVersion === 'scaffolder.backstage.io/v1beta3';\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\nconst taskOrderFields = new Set(['created_at', 'status', 'created_by']);\n\nfunction formatSecretsValidationErrors(result: ValidatorResult) {\n return result.errors.map(err => {\n const property = err.property.replace(/^instance/, 'secrets');\n const secretName = err.argument;\n const message =\n err.name === 'required'\n ? `secrets.${secretName} is required`\n : `${property} ${err.message}`;\n return {\n ...err,\n property,\n message,\n instance: {},\n };\n });\n}\n\nasync function validateSecrets(options: {\n template: TemplateEntityV1beta3;\n secrets: Record<string, unknown>;\n res: express.Response;\n auditorEvent?: AuditorServiceEvent;\n}): Promise<boolean> {\n const { template, secrets, res, auditorEvent } = options;\n if (!template.spec.secrets?.schema) {\n return true;\n }\n\n const result = validate(secrets, template.spec.secrets.schema);\n if (result.valid) {\n return true;\n }\n\n await auditorEvent?.fail({\n error: new InputError('Secrets validation failed'),\n });\n\n res.status(400).json({\n errors: formatSecretsValidationErrors(result),\n });\n return false;\n}\n\nfunction serializeTask(task: SerializedTask): SerializedTaskResponse {\n return {\n id: task.id,\n spec: task.spec,\n status: task.status,\n createdAt: task.createdAt,\n lastHeartbeatAt: task.lastHeartbeatAt,\n createdBy: task.createdBy,\n };\n}\n\n/**\n * A method to create a router for the scaffolder backend plugin.\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const router = await createOpenApiRouter({\n middleware: [\n // Be generous in upload size to support a wide range of templates in dry-run mode.\n express.json({ limit: '10MB' }),\n ],\n });\n\n const {\n logger: parentLogger,\n config,\n database,\n catalog,\n actions = [],\n scheduler,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n additionalWorkspaceProviders,\n permissions,\n permissionsRegistry,\n permissionRules,\n autocompleteHandlers = {},\n events: eventsService,\n auth,\n httpAuth,\n auditor,\n actionsRegistry,\n metrics,\n } = options;\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 DefaultTemplateActionRegistry(\n actionsRegistry,\n logger,\n );\n\n const templateExtensions = {\n additionalTemplateFilters: convertFiltersToRecord(\n additionalTemplateFilters,\n ),\n additionalTemplateGlobals: convertGlobalsToRecord(\n additionalTemplateGlobals,\n ),\n };\n\n const workers: TaskWorker[] = [];\n if (concurrentTasksLimit !== 0) {\n const gracefulShutdown = config.getOptionalBoolean(\n 'scaffolder.EXPERIMENTAL_gracefulShutdown',\n );\n\n const worker = await TaskWorker.create({\n taskBroker,\n actionRegistry,\n integrations,\n logger,\n auditor,\n config,\n workingDirectory,\n concurrentTasksLimit,\n permissions,\n gracefulShutdown,\n metrics,\n ...templateExtensions,\n });\n\n workers.push(worker);\n }\n\n for (const action of actions) {\n actionRegistry.register(action);\n }\n\n const launchWorkers = () => workers.forEach(worker => worker.start());\n\n const shutdownWorkers = async () => {\n await Promise.allSettled(workers.map(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 permissions,\n config,\n metrics,\n ...templateExtensions,\n });\n\n const templateRules: TemplatePermissionRuleInput[] = Object.values(\n scaffolderTemplateRules,\n );\n const actionRules: ActionPermissionRuleInput[] = Object.values(\n scaffolderActionRules,\n );\n const taskRules: TaskPermissionRuleInput[] =\n Object.values(scaffolderTaskRules);\n\n if (permissionRules) {\n templateRules.push(\n ...permissionRules.filter(isTemplatePermissionRuleInput),\n );\n actionRules.push(...permissionRules.filter(isActionPermissionRuleInput));\n taskRules.push(...permissionRules.filter(isTaskPermissionRuleInput));\n }\n\n const isTemplateAuthorized = createConditionAuthorizer(\n Object.values(templateRules),\n );\n const isTaskAuthorized = createConditionAuthorizer(Object.values(taskRules));\n\n const taskTransformConditions: ConditionTransformer<TaskFilters> =\n createConditionTransformer(Object.values(taskRules));\n\n permissionsRegistry.addResourceType({\n resourceRef: scaffolderTemplatePermissionResourceRef,\n permissions: scaffolderTemplatePermissions,\n rules: templateRules,\n });\n\n permissionsRegistry.addResourceType({\n resourceRef: scaffolderActionPermissionResourceRef,\n permissions: scaffolderActionPermissions,\n rules: actionRules,\n });\n\n permissionsRegistry.addResourceType({\n resourceRef: scaffolderTaskPermissionResourceRef,\n permissions: scaffolderTaskPermissions,\n rules: taskRules,\n getResources: async resourceRefs => {\n return Promise.all(\n resourceRefs.map(async taskId => {\n return await taskBroker.get(taskId);\n }),\n );\n },\n });\n\n permissionsRegistry.addPermissions([\n taskCreatePermission,\n templateManagementPermission,\n ]);\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 template = await authorizeTemplate(req.params, credentials);\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:\n (schema.title as string) ??\n 'Please enter the following information',\n description: schema.description as string,\n schema,\n })),\n formDecorators:\n template.spec.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 const credentials = await httpAuth.credentials(req);\n\n try {\n const list = await actionRegistry.list({ credentials });\n const actionsList = Array.from(list.values())\n .map(action => {\n return {\n id: action.id,\n description: action.description,\n examples: action.examples,\n schema: action.schema,\n };\n })\n .sort((a, b) => a.id.localeCompare(b.id));\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 userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalog.getEntityByRef(userEntityRef, { credentials })\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 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 secretsValid = await validateSecrets({\n template,\n secrets: req.body.secrets ?? {},\n res,\n auditorEvent,\n });\n if (!secretsValid) {\n return;\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: (credentials as any).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\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 if (!taskOrderFields.has(match[2])) {\n throw new InputError(`Invalid order field \"${match[2]}\"`);\n }\n\n return {\n order: match[1] as 'asc' | 'desc',\n field: match[2],\n };\n });\n\n const { limit, offset } = req.query;\n\n const taskPermissionFilters = await getAuthorizeConditions({\n credentials: credentials,\n permission: taskReadPermission,\n permissionService: permissions,\n transformConditions: taskTransformConditions,\n });\n\n const taskList = await taskBroker.list({\n filters: {\n createdBy,\n status: status ? (status as TaskStatus[]) : undefined,\n },\n order,\n pagination: {\n limit,\n offset,\n },\n permissionFilters: taskPermissionFilters,\n });\n\n await auditorEvent?.success();\n\n res.status(200).json({\n tasks: taskList.tasks.map(serializeTask),\n totalTasks: taskList.totalTasks,\n });\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\n const task = await taskBroker.get(taskId);\n\n await checkTaskPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n task: task,\n isTaskAuthorized,\n });\n\n if (!task) {\n throw new NotFoundError(`Task with id ${taskId} does not exist`);\n }\n\n await auditorEvent?.success();\n\n res.status(200).json(serializeTask(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 const task = await taskBroker.get(taskId);\n // Requires both read and cancel permissions\n await checkTaskPermission({\n credentials,\n permissions: [taskCancelPermission, taskReadPermission],\n permissionService: permissions,\n task: task,\n isTaskAuthorized,\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 const task = await taskBroker.get(taskId);\n\n // Requires both read and create permissions\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission],\n permissionService: permissions,\n });\n\n await checkTaskPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n task: task,\n isTaskAuthorized,\n });\n\n // Validate secrets against template schema if defined\n if (task.spec.templateInfo?.entityRef) {\n const templateEntityRef = parseEntityRef(\n task.spec.templateInfo.entityRef,\n { defaultKind: 'template' },\n );\n const template = await authorizeTemplate(\n templateEntityRef,\n credentials,\n );\n\n const secretsValid = await validateSecrets({\n template,\n secrets: req.body.secrets ?? {},\n res,\n auditorEvent,\n });\n if (!secretsValid) {\n return;\n }\n }\n\n await auditorEvent?.success();\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\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 await taskBroker.retry?.({ secrets, taskId });\n res.status(201).json({ id: taskId });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n });\n (router as express.Router).get(\n '/v2/tasks/:taskId/eventstream',\n 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 const task = await taskBroker.get(taskId);\n\n await checkTaskPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n task: task,\n isTaskAuthorized,\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 );\n router\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 const task = await taskBroker.get(taskId);\n\n await checkTaskPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n task: task,\n isTaskAuthorized,\n });\n\n const after =\n req.query.after !== undefined ? 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 userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalog.getEntityByRef(userEntityRef, { credentials })\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 secretsValid = await validateSecrets({\n template,\n secrets: body.secrets ?? {},\n res,\n auditorEvent,\n });\n if (!secretsValid) {\n return;\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 backstageToken: (credentials as any).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 .get('/v2/templating-extensions', async (_req, res) => {\n res.status(200).json({\n filters: {\n ...extractFilterMetadata(createDefaultFilters({ integrations })),\n ...extractFilterMetadata(additionalTemplateFilters),\n },\n globals: {\n functions: extractGlobalFunctionMetadata(additionalTemplateGlobals),\n values: extractGlobalValueMetadata(additionalTemplateGlobals),\n },\n });\n });\n\n const app = express();\n app.set('logger', logger);\n app.use('/', router);\n\n async function authorizeTemplate(\n entityRef: CompoundEntityRef,\n credentials: BackstageCredentials,\n ) {\n const template = await findTemplate({\n catalog,\n entityRef,\n credentials,\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 isTemplateAuthorized(parameterDecision, step),\n );\n } else if (\n template.spec.parameters &&\n !isTemplateAuthorized(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 isTemplateAuthorized(stepDecision, step),\n );\n\n return template;\n }\n\n return app;\n}\n"],"names":["config","readDurationFromConfig","validate","InputError","router","createOpenApiRouter","express","permissions","getWorkingDirectory","ScmIntegrations","DatabaseTaskStore","StorageTaskBroker","Duration","DefaultTemplateActionRegistry","convertFiltersToRecord","convertGlobalsToRecord","TaskWorker","createDryRunner","scaffolderTemplateRules","scaffolderActionRules","scaffolderTaskRules","isTemplatePermissionRuleInput","isActionPermissionRuleInput","isTaskPermissionRuleInput","createConditionAuthorizer","createConditionTransformer","scaffolderTemplatePermissionResourceRef","scaffolderTemplatePermissions","scaffolderActionPermissionResourceRef","scaffolderActionPermissions","scaffolderTaskPermissionResourceRef","scaffolderTaskPermissions","taskCreatePermission","templateManagementPermission","parseEntityRef","checkPermission","result","getEntityBaseUrl","stringifyEntityRef","parseStringsParam","getAuthorizeConditions","taskReadPermission","checkTaskPermission","NotFoundError","taskCancelPermission","z","templateEntityV1beta3Validator","uuid","resolveSafeChildPath","pathToFileURL","extractFilterMetadata","createDefaultFilters","extractGlobalFunctionMetadata","extractGlobalValueMetadata","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 AuditorService,\n AuditorServiceEvent,\n AuthService,\n BackstageCredentials,\n DatabaseService,\n HttpAuthService,\n LifecycleService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n resolveSafeChildPath,\n SchedulerService,\n} from '@backstage/backend-plugin-api';\nimport { validate, ValidatorResult } from 'jsonschema';\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 } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\n\nimport { EventsService } from '@backstage/plugin-events-node';\n\nimport {\n ConditionTransformer,\n createConditionAuthorizer,\n createConditionTransformer,\n} from '@backstage/plugin-permission-node';\nimport {\n TaskSpec,\n TemplateEntityV1beta3,\n templateEntityV1beta3Validator,\n} from '@backstage/plugin-scaffolder-common';\nimport {\n scaffolderActionPermissions,\n scaffolderTaskPermissions,\n scaffolderTemplatePermissions,\n taskCancelPermission,\n taskCreatePermission,\n taskReadPermission,\n templateDryRunPermission,\n templateManagementPermission,\n templateParameterReadPermission,\n templateStepReadPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport {\n TaskBroker,\n TaskFilters,\n SerializedTask,\n TaskStatus,\n TemplateAction,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n CreatedTemplateFilter,\n CreatedTemplateGlobal,\n scaffolderActionPermissionResourceRef,\n scaffolderTaskPermissionResourceRef,\n scaffolderTemplatePermissionResourceRef,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport { HumanDuration, JsonObject } from '@backstage/types';\nimport express from 'express';\nimport { Duration } from 'luxon';\nimport { pathToFileURL } from 'node:url';\nimport { randomUUID as uuid } from 'node:crypto';\nimport { z } from 'zod/v3';\nimport {\n DatabaseTaskStore,\n DefaultTemplateActionRegistry,\n TaskWorker,\n} from '../scaffolder';\nimport { createDryRunner } from '../scaffolder/dryrun';\nimport { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker';\nimport { isTaskRecoveryEnabled } from '../scaffolder/tasks/taskRecoveryHelper';\nimport { InternalTaskSecrets } from '../scaffolder/tasks/types';\nimport { createOpenApiRouter } from '../schema/openapi';\nimport type { SerializedTask as SerializedTaskResponse } from '../schema/openapi/generated/models/SerializedTask.model';\nimport {\n checkPermission,\n checkTaskPermission,\n getAuthorizeConditions,\n} from '../util/checkPermissions';\nimport {\n findTemplate,\n getEntityBaseUrl,\n getWorkingDirectory,\n parseStringsParam,\n} from './helpers';\n\nimport {\n convertFiltersToRecord,\n convertGlobalsToRecord,\n extractFilterMetadata,\n extractGlobalFunctionMetadata,\n extractGlobalValueMetadata,\n} from '../util/templating';\nimport { createDefaultFilters } from '../lib/templating/filters/createDefaultFilters';\nimport {\n ActionPermissionRuleInput,\n isActionPermissionRuleInput,\n isTaskPermissionRuleInput,\n isTemplatePermissionRuleInput,\n ScaffolderPermissionRuleInput,\n TaskPermissionRuleInput,\n TemplatePermissionRuleInput,\n} from './permissions';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\n\nimport {\n scaffolderActionRules,\n scaffolderTaskRules,\n scaffolderTemplateRules,\n} from './rules';\nimport {\n ActionsService,\n MetricsService,\n} from '@backstage/backend-plugin-api/alpha';\n\n/**\n * RouterOptions\n */\nexport interface RouterOptions {\n logger: LoggerService;\n config: Config;\n lifecycle?: LifecycleService;\n database: DatabaseService;\n catalog: CatalogService;\n scheduler?: SchedulerService;\n actions?: TemplateAction<any, any, any>[];\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?:\n | Record<string, TemplateFilter>\n | CreatedTemplateFilter<any, any>[];\n additionalTemplateGlobals?:\n | Record<string, TemplateGlobal>\n | CreatedTemplateGlobal[];\n additionalWorkspaceProviders?: Record<string, WorkspaceProvider>;\n permissions?: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n permissionRules?: Array<ScaffolderPermissionRuleInput>;\n auth: AuthService;\n httpAuth: HttpAuthService;\n events?: EventsService;\n auditor?: AuditorService;\n autocompleteHandlers?: Record<string, AutocompleteHandler>;\n actionsRegistry: ActionsService;\n metrics: MetricsService;\n}\n\nfunction isSupportedTemplate(entity: TemplateEntityV1beta3) {\n return entity.apiVersion === 'scaffolder.backstage.io/v1beta3';\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\nconst taskOrderFields = new Set(['created_at', 'status', 'created_by']);\n\nfunction formatSecretsValidationErrors(result: ValidatorResult) {\n return result.errors.map(err => {\n const property = err.property.replace(/^instance/, 'secrets');\n const secretName = err.argument;\n const message =\n err.name === 'required'\n ? `secrets.${secretName} is required`\n : `${property} ${err.message}`;\n return {\n ...err,\n property,\n message,\n instance: {},\n };\n });\n}\n\nasync function validateSecrets(options: {\n template: TemplateEntityV1beta3;\n secrets: Record<string, unknown>;\n res: express.Response;\n auditorEvent?: AuditorServiceEvent;\n}): Promise<boolean> {\n const { template, secrets, res, auditorEvent } = options;\n if (!template.spec.secrets?.schema) {\n return true;\n }\n\n const result = validate(secrets, template.spec.secrets.schema);\n if (result.valid) {\n return true;\n }\n\n await auditorEvent?.fail({\n error: new InputError('Secrets validation failed'),\n });\n\n res.status(400).json({\n errors: formatSecretsValidationErrors(result),\n });\n return false;\n}\n\nfunction serializeTask(task: SerializedTask): SerializedTaskResponse {\n return {\n id: task.id,\n spec: task.spec,\n status: task.status,\n createdAt: task.createdAt,\n lastHeartbeatAt: task.lastHeartbeatAt,\n createdBy: task.createdBy,\n };\n}\n\n/**\n * A method to create a router for the scaffolder backend plugin.\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const router = await createOpenApiRouter({\n middleware: [\n // Be generous in upload size to support a wide range of templates in dry-run mode.\n express.json({ limit: '10MB' }),\n ],\n });\n\n const {\n logger: parentLogger,\n config,\n database,\n catalog,\n actions = [],\n scheduler,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n additionalWorkspaceProviders,\n permissions,\n permissionsRegistry,\n permissionRules,\n autocompleteHandlers = {},\n events: eventsService,\n auth,\n httpAuth,\n auditor,\n actionsRegistry,\n metrics,\n } = options;\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 recoverTasksEnabled: isTaskRecoveryEnabled(config),\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 DefaultTemplateActionRegistry(\n actionsRegistry,\n logger,\n );\n\n const templateExtensions = {\n additionalTemplateFilters: convertFiltersToRecord(\n additionalTemplateFilters,\n ),\n additionalTemplateGlobals: convertGlobalsToRecord(\n additionalTemplateGlobals,\n ),\n };\n\n const workers: TaskWorker[] = [];\n if (concurrentTasksLimit !== 0) {\n const gracefulShutdown = config.getOptionalBoolean(\n 'scaffolder.EXPERIMENTAL_gracefulShutdown',\n );\n\n const worker = await TaskWorker.create({\n taskBroker,\n actionRegistry,\n integrations,\n logger,\n auditor,\n config,\n workingDirectory,\n concurrentTasksLimit,\n permissions,\n gracefulShutdown,\n metrics,\n ...templateExtensions,\n });\n\n workers.push(worker);\n }\n\n for (const action of actions) {\n actionRegistry.register(action);\n }\n\n const launchWorkers = () => workers.forEach(worker => worker.start());\n\n const shutdownWorkers = async () => {\n await Promise.allSettled(workers.map(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 permissions,\n config,\n metrics,\n ...templateExtensions,\n });\n\n const templateRules: TemplatePermissionRuleInput[] = Object.values(\n scaffolderTemplateRules,\n );\n const actionRules: ActionPermissionRuleInput[] = Object.values(\n scaffolderActionRules,\n );\n const taskRules: TaskPermissionRuleInput[] =\n Object.values(scaffolderTaskRules);\n\n if (permissionRules) {\n templateRules.push(\n ...permissionRules.filter(isTemplatePermissionRuleInput),\n );\n actionRules.push(...permissionRules.filter(isActionPermissionRuleInput));\n taskRules.push(...permissionRules.filter(isTaskPermissionRuleInput));\n }\n\n const isTemplateAuthorized = createConditionAuthorizer(\n Object.values(templateRules),\n );\n const isTaskAuthorized = createConditionAuthorizer(Object.values(taskRules));\n\n const taskTransformConditions: ConditionTransformer<TaskFilters> =\n createConditionTransformer(Object.values(taskRules));\n\n permissionsRegistry.addResourceType({\n resourceRef: scaffolderTemplatePermissionResourceRef,\n permissions: scaffolderTemplatePermissions,\n rules: templateRules,\n });\n\n permissionsRegistry.addResourceType({\n resourceRef: scaffolderActionPermissionResourceRef,\n permissions: scaffolderActionPermissions,\n rules: actionRules,\n });\n\n permissionsRegistry.addResourceType({\n resourceRef: scaffolderTaskPermissionResourceRef,\n permissions: scaffolderTaskPermissions,\n rules: taskRules,\n getResources: async resourceRefs => {\n return Promise.all(\n resourceRefs.map(async taskId => {\n return await taskBroker.get(taskId);\n }),\n );\n },\n });\n\n permissionsRegistry.addPermissions([\n taskCreatePermission,\n templateDryRunPermission,\n templateManagementPermission,\n ]);\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 template = await authorizeTemplate(req.params, credentials);\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:\n (schema.title as string) ??\n 'Please enter the following information',\n description: schema.description as string,\n schema,\n })),\n formDecorators:\n template.spec.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 const credentials = await httpAuth.credentials(req);\n\n try {\n const list = await actionRegistry.list({ credentials });\n const actionsList = Array.from(list.values())\n .map(action => {\n return {\n id: action.id,\n description: action.description,\n examples: action.examples,\n schema: action.schema,\n };\n })\n .sort((a, b) => a.id.localeCompare(b.id));\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 userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalog.getEntityByRef(userEntityRef, { credentials })\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 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 secretsValid = await validateSecrets({\n template,\n secrets: req.body.secrets ?? {},\n res,\n auditorEvent,\n });\n if (!secretsValid) {\n return;\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: (credentials as any).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\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 if (!taskOrderFields.has(match[2])) {\n throw new InputError(`Invalid order field \"${match[2]}\"`);\n }\n\n return {\n order: match[1] as 'asc' | 'desc',\n field: match[2],\n };\n });\n\n const { limit, offset } = req.query;\n\n const taskPermissionFilters = await getAuthorizeConditions({\n credentials: credentials,\n permission: taskReadPermission,\n permissionService: permissions,\n transformConditions: taskTransformConditions,\n });\n\n const taskList = await taskBroker.list({\n filters: {\n createdBy,\n status: status ? (status as TaskStatus[]) : undefined,\n },\n order,\n pagination: {\n limit,\n offset,\n },\n permissionFilters: taskPermissionFilters,\n });\n\n await auditorEvent?.success();\n\n res.status(200).json({\n tasks: taskList.tasks.map(serializeTask),\n totalTasks: taskList.totalTasks,\n });\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\n const task = await taskBroker.get(taskId);\n\n await checkTaskPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n task: task,\n isTaskAuthorized,\n });\n\n if (!task) {\n throw new NotFoundError(`Task with id ${taskId} does not exist`);\n }\n\n await auditorEvent?.success();\n\n res.status(200).json(serializeTask(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 const task = await taskBroker.get(taskId);\n // Requires both read and cancel permissions\n await checkTaskPermission({\n credentials,\n permissions: [taskCancelPermission, taskReadPermission],\n permissionService: permissions,\n task: task,\n isTaskAuthorized,\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 const task = await taskBroker.get(taskId);\n\n // Requires both read and create permissions\n await checkPermission({\n credentials,\n permissions: [taskCreatePermission],\n permissionService: permissions,\n });\n\n await checkTaskPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n task: task,\n isTaskAuthorized,\n });\n\n // Validate secrets against template schema if defined\n if (task.spec.templateInfo?.entityRef) {\n const templateEntityRef = parseEntityRef(\n task.spec.templateInfo.entityRef,\n { defaultKind: 'template' },\n );\n const template = await authorizeTemplate(\n templateEntityRef,\n credentials,\n );\n\n const secretsValid = await validateSecrets({\n template,\n secrets: req.body.secrets ?? {},\n res,\n auditorEvent,\n });\n if (!secretsValid) {\n return;\n }\n }\n\n await auditorEvent?.success();\n\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\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 await taskBroker.retry?.({ secrets, taskId });\n res.status(201).json({ id: taskId });\n } catch (err) {\n await auditorEvent?.fail({ error: err });\n throw err;\n }\n });\n (router as express.Router).get(\n '/v2/tasks/:taskId/eventstream',\n 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 const task = await taskBroker.get(taskId);\n\n await checkTaskPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n task: task,\n isTaskAuthorized,\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 );\n router\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 const task = await taskBroker.get(taskId);\n\n await checkTaskPermission({\n credentials,\n permissions: [taskReadPermission],\n permissionService: permissions,\n task: task,\n isTaskAuthorized,\n });\n\n const after =\n req.query.after !== undefined ? 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, templateDryRunPermission],\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 userEntityRef = auth.isPrincipal(credentials, 'user')\n ? credentials.principal.userEntityRef\n : undefined;\n\n const userEntity = userEntityRef\n ? await catalog.getEntityByRef(userEntityRef, { credentials })\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 secretsValid = await validateSecrets({\n template,\n secrets: body.secrets ?? {},\n res,\n auditorEvent,\n });\n if (!secretsValid) {\n return;\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 backstageToken: (credentials as any).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 .get('/v2/templating-extensions', async (_req, res) => {\n res.status(200).json({\n filters: {\n ...extractFilterMetadata(createDefaultFilters({ integrations })),\n ...extractFilterMetadata(additionalTemplateFilters),\n },\n globals: {\n functions: extractGlobalFunctionMetadata(additionalTemplateGlobals),\n values: extractGlobalValueMetadata(additionalTemplateGlobals),\n },\n });\n });\n\n const app = express();\n app.set('logger', logger);\n app.use('/', router);\n\n async function authorizeTemplate(\n entityRef: CompoundEntityRef,\n credentials: BackstageCredentials,\n ) {\n const template = await findTemplate({\n catalog,\n entityRef,\n credentials,\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 isTemplateAuthorized(parameterDecision, step),\n );\n } else if (\n template.spec.parameters &&\n !isTemplateAuthorized(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 isTemplateAuthorized(stepDecision, step),\n );\n\n return template;\n }\n\n return app;\n}\n"],"names":["config","readDurationFromConfig","validate","InputError","router","createOpenApiRouter","express","permissions","getWorkingDirectory","ScmIntegrations","DatabaseTaskStore","isTaskRecoveryEnabled","StorageTaskBroker","Duration","DefaultTemplateActionRegistry","convertFiltersToRecord","convertGlobalsToRecord","TaskWorker","createDryRunner","scaffolderTemplateRules","scaffolderActionRules","scaffolderTaskRules","isTemplatePermissionRuleInput","isActionPermissionRuleInput","isTaskPermissionRuleInput","createConditionAuthorizer","createConditionTransformer","scaffolderTemplatePermissionResourceRef","scaffolderTemplatePermissions","scaffolderActionPermissionResourceRef","scaffolderActionPermissions","scaffolderTaskPermissionResourceRef","scaffolderTaskPermissions","taskCreatePermission","templateDryRunPermission","templateManagementPermission","parseEntityRef","checkPermission","result","getEntityBaseUrl","stringifyEntityRef","parseStringsParam","getAuthorizeConditions","taskReadPermission","checkTaskPermission","NotFoundError","taskCancelPermission","z","templateEntityV1beta3Validator","uuid","resolveSafeChildPath","pathToFileURL","extractFilterMetadata","createDefaultFilters","extractGlobalFunctionMetadata","extractGlobalValueMetadata","findTemplate","templateParameterReadPermission","templateStepReadPermission"],"mappings":"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"}
|