From 42f91cf01eb40777010d3226366c62db6b990847 Mon Sep 17 00:00:00 2001 From: Juan Pablo Garcia Ripa Date: Tue, 5 Oct 2021 23:58:45 +0200 Subject: [PATCH] add glob option to cors origin config Signed-off-by: Juan Pablo Garcia Ripa --- packages/backend-common/package.json | 2 ++ .../src/service/lib/config.test.ts | 34 ++++++++++++++++++- .../backend-common/src/service/lib/config.ts | 20 ++++++++++- yarn.lock | 7 ++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 29018ef8c8..3c426d780a 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -57,6 +57,7 @@ "knex": "^0.95.1", "lodash": "^4.17.21", "logform": "^2.1.1", + "micromatch": "^4.0.4", "minimatch": "^3.0.4", "minimist": "^1.2.5", "morgan": "^1.10.0", @@ -84,6 +85,7 @@ "@types/concat-stream": "^1.6.0", "@types/fs-extra": "^9.0.3", "@types/http-errors": "^1.6.3", + "@types/micromatch": "^4.0.2", "@types/minimist": "^1.2.0", "@types/mock-fs": "^4.13.0", "@types/morgan": "^1.9.0", diff --git a/packages/backend-common/src/service/lib/config.test.ts b/packages/backend-common/src/service/lib/config.test.ts index f2f0c88cfb..10c2d705ca 100644 --- a/packages/backend-common/src/service/lib/config.test.ts +++ b/packages/backend-common/src/service/lib/config.test.ts @@ -15,7 +15,7 @@ */ import { ConfigReader } from '@backstage/config'; -import { readCspOptions } from './config'; +import { readCorsOptions, readCspOptions } from './config'; describe('config', () => { describe('readCspOptions', () => { @@ -42,4 +42,36 @@ describe('config', () => { expect(() => readCspOptions(config)).toThrow(/wanted string-array/); }); }); + + describe('readCorsOptions', () => { + it('reads single string', () => { + const config = new ConfigReader({ cors: { origin: 'https://*.value*' } }); + const cors = readCorsOptions(config); + expect(cors).toEqual( + expect.objectContaining({ + origin: expect.any(RegExp), + }), + ); + + const origin = cors?.origin as RegExp; + expect(origin.test('https://a.value')).toBe(true); + expect(origin.test('http://a.value')).toBe(false); + }); + + it('reads string array', () => { + const config = new ConfigReader({ + cors: { origin: ['https://*.value*', 'http(s|)://*.value*'] }, + }); + const cors = readCorsOptions(config); + expect(cors).toEqual( + expect.objectContaining({ + origin: expect.any(Array), + }), + ); + const origin = cors?.origin as RegExp[]; + expect(origin[0].test('https://a.value')).toBe(true); + expect(origin[1].test('https://a.value')).toBe(true); + expect(origin[1].test('http://a.value')).toBe(true); + }); + }); }); diff --git a/packages/backend-common/src/service/lib/config.ts b/packages/backend-common/src/service/lib/config.ts index 77ef925403..5d46e2fccf 100644 --- a/packages/backend-common/src/service/lib/config.ts +++ b/packages/backend-common/src/service/lib/config.ts @@ -16,6 +16,7 @@ import { Config } from '@backstage/config'; import { CorsOptions } from 'cors'; +import { makeRe } from 'micromatch'; export type BaseOptions = { listenPort?: string | number; @@ -112,7 +113,7 @@ export function readCorsOptions(config: Config): CorsOptions | undefined { } return removeUnknown({ - origin: getOptionalStringOrStrings(cc, 'origin'), + origin: getOptionalGlobOrGlobs(cc, 'origin'), methods: getOptionalStringOrStrings(cc, 'methods'), allowedHeaders: getOptionalStringOrStrings(cc, 'allowedHeaders'), exposedHeaders: getOptionalStringOrStrings(cc, 'exposedHeaders'), @@ -217,6 +218,23 @@ function getOptionalStringOrStrings( throw new Error(`Expected string or array of strings, got ${typeof value}`); } +function getOptionalGlobOrGlobs( + config: Config, + key: string, +): RegExp | RegExp[] | undefined { + const value = config.getOptional(key); + if (value === undefined) { + return value; + } + if (typeof value === 'string') { + return makeRe(value, { debug: true }); + } + if (isStringArray(value)) { + return value.map(val => makeRe(val)); + } + throw new Error(`Expected string or array of strings, got ${typeof value}`); +} + function isStringArray(value: any): value is string[] { if (!Array.isArray(value)) { return false; diff --git a/yarn.lock b/yarn.lock index c961b6045b..ca1483daf5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7088,6 +7088,13 @@ dependencies: "@types/braces" "*" +"@types/micromatch@^4.0.2": + version "4.0.2" + resolved "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.2.tgz#ce29c8b166a73bf980a5727b1e4a4d099965151d" + integrity sha512-oqXqVb0ci19GtH0vOA/U2TmHTcRY9kuZl4mqUxe0QmJAlIW13kzhuK5pi1i9+ngav8FjpSb9FVS/GE00GLX1VA== + dependencies: + "@types/braces" "*" + "@types/mime-types@^2.1.0": version "2.1.0" resolved "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz#9ca52cda363f699c69466c2a6ccdaad913ea7a73"