diff --git a/packages/backend/package.json b/packages/backend/package.json index fd8ec82d91..57bb988f64 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -60,6 +60,7 @@ "@backstage/plugin-rollbar-backend": "workspace:^", "@backstage/plugin-scaffolder-backend": "workspace:^", "@backstage/plugin-scaffolder-backend-module-rails": "workspace:^", + "@backstage/plugin-scaffolder-common": "workspace:^", "@backstage/plugin-search-backend": "workspace:^", "@backstage/plugin-search-backend-module-elasticsearch": "workspace:^", "@backstage/plugin-search-backend-module-pg": "workspace:^", @@ -83,7 +84,9 @@ "pg": "^8.3.0", "pg-connection-string": "^2.3.0", "prom-client": "^14.0.1", - "winston": "^3.2.1" + "winston": "^3.2.1", + "zod": "~3.18.0", + "zod-to-json-schema": "~3.18.0" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/packages/backend/src/plugins/permission.ts b/packages/backend/src/plugins/permission.ts index a87e673309..c5f92c17d0 100644 --- a/packages/backend/src/plugins/permission.ts +++ b/packages/backend/src/plugins/permission.ts @@ -35,9 +35,9 @@ import { } from '@backstage/plugin-scaffolder-backend'; import { actionExecutePermission } from '@backstage/plugin-scaffolder-common'; import { Router } from 'express'; -import { PluginEnvironment } from '../types'; import { z } from 'zod'; import zodToJsonSchema from 'zod-to-json-schema'; +import { PluginEnvironment } from '../types'; const inputSchema = zodToJsonSchema( z.object({ message: z.enum(['hello']) }).strict(), diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index f238ab3c4a..9b28ac8199 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -66,8 +66,6 @@ "@gitbeaker/core": "^35.6.0", "@gitbeaker/node": "^35.1.0", "@octokit/webhooks": "^10.0.0", - "@types/express": "^4.17.6", - "@types/luxon": "^3.0.0", "ajv": "^8.12.0", "azure-devops-node-api": "^11.0.1", "command-exists": "^1.2.9", @@ -103,8 +101,10 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/command-exists": "^1.2.0", + "@types/express": "^4.17.6", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", + "@types/luxon": "^3.0.0", "@types/mock-fs": "^4.13.0", "@types/nunjucks": "^3.1.4", "@types/supertest": "^2.0.8", diff --git a/plugins/scaffolder-backend/src/service/rules.ts b/plugins/scaffolder-backend/src/service/rules.ts index 7113ec86e3..7f71693478 100644 --- a/plugins/scaffolder-backend/src/service/rules.ts +++ b/plugins/scaffolder-backend/src/service/rules.ts @@ -59,23 +59,34 @@ export const hasActionId = createActionPermissionRule({ }); export const matchesInput = createActionPermissionRule({ - name: 'MATCHED_INPUT', + name: 'MATCHES_INPUT', resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION, description: `Matches actionId and the input given`, paramsSchema: z.object({ action: z.string().describe('Name of the actionId to match on'), - // Pass in a json schema to validate the input against - schema: z.record(z.any()), + input: z + .any() + .optional() + .describe('JSON schema to validate input against') + .superRefine((value, ctx) => { + if (value && ajv.validateSchema(value)) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Invalid JSON schema', + }); + } + }), }), - apply: (resource, { action, schema }) => { + apply: (resource, { action, input }) => { if (resource.action !== action) { return true; } - if (!schema) { + + if (!input) { return true; } - return ajv.validate(schema, resource.input); + return ajv.validate(input, resource.input); }, toQuery: () => ({}), }); diff --git a/yarn.lock b/yarn.lock index 16b336dcb4..1fe70bea95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23494,6 +23494,7 @@ __metadata: "@backstage/plugin-rollbar-backend": "workspace:^" "@backstage/plugin-scaffolder-backend": "workspace:^" "@backstage/plugin-scaffolder-backend-module-rails": "workspace:^" + "@backstage/plugin-scaffolder-common": "workspace:^" "@backstage/plugin-search-backend": "workspace:^" "@backstage/plugin-search-backend-module-elasticsearch": "workspace:^" "@backstage/plugin-search-backend-module-pg": "workspace:^" @@ -23522,6 +23523,8 @@ __metadata: pg-connection-string: ^2.3.0 prom-client: ^14.0.1 winston: ^3.2.1 + zod: ~3.18.0 + zod-to-json-schema: ~3.18.0 languageName: unknown linkType: soft @@ -40643,6 +40646,15 @@ __metadata: languageName: node linkType: hard +"zod-to-json-schema@npm:~3.18.0": + version: 3.18.2 + resolution: "zod-to-json-schema@npm:3.18.2" + peerDependencies: + zod: ^3.18.0 + checksum: 10e84864a3ccc2e04500b9bc81369ed7c5b3ec068ea582a13369175ed40e785091a63ae7fa86ebb4ddf1bccd55c3dab32f4d3070bbcc3296e68305ff787c9df3 + languageName: node + linkType: hard + "zod@npm:^3.21.4": version: 3.21.4 resolution: "zod@npm:3.21.4"