diff --git a/packages/backend-app-api/src/lib/http/config.test.ts b/packages/backend-app-api/src/lib/http/config.test.ts index 3ab5eda5e9..f54ba927ca 100644 --- a/packages/backend-app-api/src/lib/http/config.test.ts +++ b/packages/backend-app-api/src/lib/http/config.test.ts @@ -18,6 +18,12 @@ import { ConfigReader } from '@backstage/config'; import { readHttpServerOptions } from './config'; describe('readHttpServerOptions', () => { + it('should return defaults', () => { + expect(readHttpServerOptions()).toEqual({ + listen: { host: '', port: 7007 }, + }); + }); + it.each([ [{}, { listen: { host: '', port: 7007 } }], [{ listen: ':80' }, { listen: { host: '', port: 80 } }], diff --git a/packages/backend-app-api/src/lib/http/config.ts b/packages/backend-app-api/src/lib/http/config.ts index 3c5acf0ffd..e3b41c63de 100644 --- a/packages/backend-app-api/src/lib/http/config.ts +++ b/packages/backend-app-api/src/lib/http/config.ts @@ -34,15 +34,15 @@ const DEFAULT_HOST = ''; * const opts = readHttpServerOptions(config.getConfig('backend')); * ``` */ -export function readHttpServerOptions(config: Config): HttpServerOptions { +export function readHttpServerOptions(config?: Config): HttpServerOptions { return { listen: readHttpListenOptions(config), https: readHttpsOptions(config), }; } -function readHttpListenOptions(config: Config): HttpServerOptions['listen'] { - const listen = config.getOptional('listen'); +function readHttpListenOptions(config?: Config): HttpServerOptions['listen'] { + const listen = config?.getOptional('listen'); if (typeof listen === 'string') { const parts = String(listen).split(':'); const port = parseInt(parts[parts.length - 1], 10); @@ -60,22 +60,22 @@ function readHttpListenOptions(config: Config): HttpServerOptions['listen'] { } // Workaround to allow empty string - const host = config.getOptional('listen.host') ?? DEFAULT_HOST; + const host = config?.getOptional('listen.host') ?? DEFAULT_HOST; if (typeof host !== 'string') { - config.getOptionalString('listen.host'); // will throw + config?.getOptionalString('listen.host'); // will throw throw new Error('unreachable'); } return { - port: config.getOptionalNumber('listen.port') ?? DEFAULT_PORT, + port: config?.getOptionalNumber('listen.port') ?? DEFAULT_PORT, host, }; } -function readHttpsOptions(config: Config): HttpServerOptions['https'] { - const https = config.getOptional('https'); +function readHttpsOptions(config?: Config): HttpServerOptions['https'] { + const https = config?.getOptional('https'); if (https === true) { - const baseUrl = config.getString('baseUrl'); + const baseUrl = config!.getString('baseUrl'); let hostname; try { hostname = new URL(baseUrl).hostname; @@ -86,7 +86,7 @@ function readHttpsOptions(config: Config): HttpServerOptions['https'] { return { certificate: { type: 'generated', hostname } }; } - const cc = config.getOptionalConfig('https'); + const cc = config?.getOptionalConfig('https'); if (!cc) { return undefined; } diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/readCorsOptions.test.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/readCorsOptions.test.ts index 113b2a8ee6..af490a26f9 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/readCorsOptions.test.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/readCorsOptions.test.ts @@ -19,7 +19,7 @@ import { readCorsOptions } from './readCorsOptions'; describe('readCorsOptions', () => { it('should be disabled by default', () => { - expect(readCorsOptions(new ConfigReader({}))).toEqual({ + expect(readCorsOptions()).toEqual({ origin: false, }); }); diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/readCorsOptions.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/readCorsOptions.ts index 809ee9b527..98b548d02e 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/readCorsOptions.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/readCorsOptions.ts @@ -29,8 +29,8 @@ import { Minimatch } from 'minimatch'; * const corsOptions = readCorsOptions(config.getConfig('backend')); * ``` */ -export function readCorsOptions(config: Config): CorsOptions { - const cc = config.getOptionalConfig('cors'); +export function readCorsOptions(config?: Config): CorsOptions { + const cc = config?.getOptionalConfig('cors'); if (!cc) { return { origin: false }; // Disable CORS } diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/readHelmetOptions.test.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/readHelmetOptions.test.ts index d5e0e29264..bc31404634 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/readHelmetOptions.test.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/readHelmetOptions.test.ts @@ -18,6 +18,30 @@ import { ConfigReader } from '@backstage/config'; import { readHelmetOptions } from './readHelmetOptions'; describe('readHelmetOptions', () => { + it('should return defaults', () => { + expect(readHelmetOptions()).toEqual({ + contentSecurityPolicy: { + useDefaults: false, + directives: { + 'default-src': ["'self'"], + 'base-uri': ["'self'"], + 'font-src': ["'self'", 'https:', 'data:'], + 'frame-ancestors': ["'self'"], + 'img-src': ["'self'", 'data:'], + 'object-src': ["'none'"], + 'script-src': ["'self'", "'unsafe-eval'"], + 'style-src': ["'self'", 'https:', "'unsafe-inline'"], + 'script-src-attr': ["'none'"], + 'upgrade-insecure-requests': [], + }, + }, + crossOriginEmbedderPolicy: false, + crossOriginOpenerPolicy: false, + crossOriginResourcePolicy: false, + originAgentCluster: false, + }); + }); + it('should add additional directives', () => { const config = new ConfigReader({ csp: { @@ -34,7 +58,6 @@ describe('readHelmetOptions', () => { 'base-uri': ["'self'"], 'font-src': ["'self'", 'https:', 'data:'], 'frame-ancestors': ["'self'"], - // 'img-src': ["'self'", 'data:'], 'object-src': ["'none'"], 'script-src': ["'self'", "'unsafe-eval'"], 'style-src': ["'self'", 'https:', "'unsafe-inline'"], diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/readHelmetOptions.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/readHelmetOptions.ts index e86997d685..9cdf339844 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/readHelmetOptions.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/readHelmetOptions.ts @@ -30,7 +30,7 @@ import { ContentSecurityPolicyOptions } from 'helmet/dist/types/middlewares/cont * const helmetOptions = readHelmetOptions(config.getConfig('backend')); * ``` */ -export function readHelmetOptions(config: Config): HelmetOptions { +export function readHelmetOptions(config?: Config): HelmetOptions { const cspOptions = readCspDirectives(config); return { contentSecurityPolicy: { @@ -61,8 +61,8 @@ type CspDirectives = Record | undefined; * upgrade-insecure-requests: false * ``` */ -function readCspDirectives(config: Config): CspDirectives { - const cc = config.getOptionalConfig('csp'); +function readCspDirectives(config?: Config): CspDirectives { + const cc = config?.getOptionalConfig('csp'); if (!cc) { return undefined; }