diff --git a/.changeset/polite-horses-do.md b/.changeset/polite-horses-do.md new file mode 100644 index 0000000000..89a8621c4e --- /dev/null +++ b/.changeset/polite-horses-do.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-events-backend-module-github': patch +'@backstage/plugin-events-backend-module-gitlab': patch +--- + +Don't hard fail for not configuring `webhookSecret` for the GitHub and GitLab events backend. Instead, we don't add the ingress. diff --git a/plugins/events-backend-module-github/config.d.ts b/plugins/events-backend-module-github/config.d.ts index 692d8d4fb5..53e3bfef90 100644 --- a/plugins/events-backend-module-github/config.d.ts +++ b/plugins/events-backend-module-github/config.d.ts @@ -27,6 +27,8 @@ export interface Config { * See https://docs.github.com/en/developers/webhooks-and-events/webhooks/securing-your-webhooks * for more details. * + * Webhook listener will only be enabled if this is set. + * * @visibility secret */ webhookSecret?: string; diff --git a/plugins/events-backend-module-github/report.api.md b/plugins/events-backend-module-github/report.api.md index a1e468793e..8d1f4d939f 100644 --- a/plugins/events-backend-module-github/report.api.md +++ b/plugins/events-backend-module-github/report.api.md @@ -13,7 +13,7 @@ import { SubTopicEventRouter } from '@backstage/plugin-events-node'; // @public export function createGithubSignatureValidator( config: Config, -): RequestValidator; +): RequestValidator | undefined; // @public (undocumented) const _default: BackendFeature; diff --git a/plugins/events-backend-module-github/src/http/createGithubSignatureValidator.test.ts b/plugins/events-backend-module-github/src/http/createGithubSignatureValidator.test.ts index 3c96c98996..bb604e88d8 100644 --- a/plugins/events-backend-module-github/src/http/createGithubSignatureValidator.test.ts +++ b/plugins/events-backend-module-github/src/http/createGithubSignatureValidator.test.ts @@ -65,9 +65,9 @@ describe('createGithubSignatureValidator', () => { } as RequestDetails; }; - it('no secret configured, throw error', async () => { - expect(() => createGithubSignatureValidator(configWithoutSecret)).toThrow( - "Missing required config value at 'events.modules.github.webhookSecret'", + it('should return undefined if no secret is configured', async () => { + expect(createGithubSignatureValidator(configWithoutSecret)).toEqual( + undefined, ); }); @@ -76,7 +76,7 @@ describe('createGithubSignatureValidator', () => { const context = new TestContext(); const validator = createGithubSignatureValidator(configWithSecret); - await validator(request, context); + await validator!(request, context); expect(context.details).not.toBeUndefined(); expect(context.details?.status).toBe(403); @@ -88,7 +88,7 @@ describe('createGithubSignatureValidator', () => { const context = new TestContext(); const validator = createGithubSignatureValidator(configWithSecret); - await validator(request, context); + await validator!(request, context); expect(context.details).not.toBeUndefined(); expect(context.details?.status).toBe(403); @@ -100,7 +100,7 @@ describe('createGithubSignatureValidator', () => { const context = new TestContext(); const validator = createGithubSignatureValidator(configWithSecret); - await validator(request, context); + await validator!(request, context); expect(context.details).toBeUndefined(); }); diff --git a/plugins/events-backend-module-github/src/http/createGithubSignatureValidator.ts b/plugins/events-backend-module-github/src/http/createGithubSignatureValidator.ts index 87cb710697..f54c00b58a 100644 --- a/plugins/events-backend-module-github/src/http/createGithubSignatureValidator.ts +++ b/plugins/events-backend-module-github/src/http/createGithubSignatureValidator.ts @@ -35,8 +35,13 @@ import { verify } from '@octokit/webhooks-methods'; */ export function createGithubSignatureValidator( config: Config, -): RequestValidator { - const secret = config.getString('events.modules.github.webhookSecret'); +): RequestValidator | undefined { + const secret = config.getOptionalString( + 'events.modules.github.webhookSecret', + ); + if (!secret) { + return undefined; + } return async ( request: RequestDetails, diff --git a/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.test.ts b/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.test.ts index 3e7f281326..f8c8456217 100644 --- a/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.test.ts +++ b/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.test.ts @@ -42,6 +42,27 @@ describe('eventsModuleGithubWebhook', () => { } as RequestDetails; }; + it('should not add ingress if validator is undefined', async () => { + let addedIngress: HttpPostIngressOptions | undefined; + const extensionPoint = { + addHttpPostIngress: (ingress: any) => { + addedIngress = ingress; + }, + }; + + await startTestBackend({ + extensionPoints: [[eventsExtensionPoint, extensionPoint]], + features: [ + eventsModuleGithubWebhook, + mockServices.rootConfig.factory({ + data: {}, + }), + ], + }); + + expect(addedIngress).toBeUndefined(); + }); + it('should be correctly wired and set up', async () => { let addedIngress: HttpPostIngressOptions | undefined; const extensionPoint = { diff --git a/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.ts b/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.ts index 5cd10d8cc6..5cb9c88679 100644 --- a/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.ts +++ b/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.ts @@ -26,7 +26,7 @@ import { createGithubSignatureValidator } from '../http/createGithubSignatureVal * registering an HTTP POST ingress with request validator * which verifies the webhook signature based on a secret. * - * @alpha + * @public */ export default createBackendModule({ pluginId: 'events', @@ -38,10 +38,13 @@ export default createBackendModule({ events: eventsExtensionPoint, }, async init({ config, events }) { - events.addHttpPostIngress({ - topic: 'github', - validator: createGithubSignatureValidator(config), - }); + const validator = createGithubSignatureValidator(config); + if (validator) { + events.addHttpPostIngress({ + topic: 'github', + validator, + }); + } }, }); }, diff --git a/plugins/events-backend-module-gitlab/config.d.ts b/plugins/events-backend-module-gitlab/config.d.ts index 6d02533845..9e3b235677 100644 --- a/plugins/events-backend-module-gitlab/config.d.ts +++ b/plugins/events-backend-module-gitlab/config.d.ts @@ -27,6 +27,8 @@ export interface Config { * See https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#validate-payloads-by-using-a-secret-token * for more details. * + * Webhook listener will only be enabled if this is set. + * * @visibility secret */ webhookSecret?: string; diff --git a/plugins/events-backend-module-gitlab/report.api.md b/plugins/events-backend-module-gitlab/report.api.md index 359e78b565..2098a893fd 100644 --- a/plugins/events-backend-module-gitlab/report.api.md +++ b/plugins/events-backend-module-gitlab/report.api.md @@ -11,7 +11,9 @@ import { RequestValidator } from '@backstage/plugin-events-node'; import { SubTopicEventRouter } from '@backstage/plugin-events-node'; // @public -export function createGitlabTokenValidator(config: Config): RequestValidator; +export function createGitlabTokenValidator( + config: Config, +): RequestValidator | undefined; // @public (undocumented) const _default: BackendFeature; diff --git a/plugins/events-backend-module-gitlab/src/http/createGitlabTokenValidator.test.ts b/plugins/events-backend-module-gitlab/src/http/createGitlabTokenValidator.test.ts index 72fee279ea..4a05d88c30 100644 --- a/plugins/events-backend-module-gitlab/src/http/createGitlabTokenValidator.test.ts +++ b/plugins/events-backend-module-gitlab/src/http/createGitlabTokenValidator.test.ts @@ -55,10 +55,8 @@ describe('createGitlabTokenValidator', () => { } as Partial as unknown as RequestDetails; }; - it('no secret configured, throw error', async () => { - expect(() => createGitlabTokenValidator(configWithoutSecret)).toThrow( - "Missing required config value at 'events.modules.gitlab.webhookSecret'", - ); + it('should return undefined if no secret is configured', async () => { + expect(createGitlabTokenValidator(configWithoutSecret)).toEqual(undefined); }); it('secret configured, reject request without token', async () => { @@ -66,7 +64,7 @@ describe('createGitlabTokenValidator', () => { const context = new TestContext(); const validator = createGitlabTokenValidator(configWithSecret); - await validator(request, context); + await validator!(request, context); expect(context.details).not.toBeUndefined(); expect(context.details?.status).toBe(403); @@ -78,7 +76,7 @@ describe('createGitlabTokenValidator', () => { const context = new TestContext(); const validator = createGitlabTokenValidator(configWithSecret); - await validator(request, context); + await validator!(request, context); expect(context.details).not.toBeUndefined(); expect(context.details?.status).toBe(403); @@ -90,7 +88,7 @@ describe('createGitlabTokenValidator', () => { const context = new TestContext(); const validator = createGitlabTokenValidator(configWithSecret); - await validator(request, context); + await validator!(request, context); expect(context.details).toBeUndefined(); }); diff --git a/plugins/events-backend-module-gitlab/src/http/createGitlabTokenValidator.ts b/plugins/events-backend-module-gitlab/src/http/createGitlabTokenValidator.ts index 9ebc054194..4696e54699 100644 --- a/plugins/events-backend-module-gitlab/src/http/createGitlabTokenValidator.ts +++ b/plugins/events-backend-module-gitlab/src/http/createGitlabTokenValidator.ts @@ -30,8 +30,16 @@ import { * @param config - root config * @public */ -export function createGitlabTokenValidator(config: Config): RequestValidator { - const secret = config.getString('events.modules.gitlab.webhookSecret'); +export function createGitlabTokenValidator( + config: Config, +): RequestValidator | undefined { + const secret = config.getOptionalString( + 'events.modules.gitlab.webhookSecret', + ); + + if (!secret) { + return undefined; + } return async ( request: RequestDetails, diff --git a/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.test.ts b/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.test.ts index 7671b6740c..3278e8a8ad 100644 --- a/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.test.ts +++ b/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.test.ts @@ -31,6 +31,27 @@ describe('gitlabWebhookEventsModule', () => { } as Partial as unknown as RequestDetails; }; + it('should not add ingress if validator is undefined', async () => { + let addedIngress: HttpPostIngressOptions | undefined; + const extensionPoint = { + addHttpPostIngress: (ingress: any) => { + addedIngress = ingress; + }, + }; + + await startTestBackend({ + extensionPoints: [[eventsExtensionPoint, extensionPoint]], + features: [ + eventsModuleGitlabWebhook, + mockServices.rootConfig.factory({ + data: {}, + }), + ], + }); + + expect(addedIngress).toBeUndefined(); + }); + it('should be correctly wired and set up', async () => { let addedIngress: HttpPostIngressOptions | undefined; const extensionPoint = { diff --git a/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.ts b/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.ts index f0896e1a99..987e2194de 100644 --- a/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.ts +++ b/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.ts @@ -40,10 +40,13 @@ export default createBackendModule({ events: eventsExtensionPoint, }, async init({ config, events }) { - events.addHttpPostIngress({ - topic: 'gitlab', - validator: createGitlabTokenValidator(config), - }); + const validator = createGitlabTokenValidator(config); + if (validator) { + events.addHttpPostIngress({ + topic: 'gitlab', + validator: createGitlabTokenValidator(config), + }); + } }, }); },