From b349720c7507d611aea7239d55cc220a3d20f325 Mon Sep 17 00:00:00 2001 From: "toban@dfds.com" Date: Mon, 17 Aug 2020 17:06:28 +0200 Subject: [PATCH 01/10] =migrations https logic to new branch --- microsite/i18n/en.json | 3 + microsite/pages/en/background.js | 2 +- packages/backend-common/package.json | 3 +- .../src/service/lib/ServiceBuilderImpl.ts | 120 ++++++++++++++++-- .../backend-common/src/service/lib/config.ts | 70 ++++++++++ packages/backend-common/src/service/types.ts | 19 +++ yarn.lock | 2 +- 7 files changed, 204 insertions(+), 15 deletions(-) diff --git a/microsite/i18n/en.json b/microsite/i18n/en.json index af891426db..5ddede3d97 100644 --- a/microsite/i18n/en.json +++ b/microsite/i18n/en.json @@ -50,6 +50,9 @@ "auth/add-auth-provider": { "title": "Adding authentication providers" }, + "auth/auth-backend-classes": { + "title": "auth/auth-backend-classes" + }, "auth/auth-backend": { "title": "Auth backend" }, diff --git a/microsite/pages/en/background.js b/microsite/pages/en/background.js index 70a15421ab..c5bf9bee94 100644 --- a/microsite/pages/en/background.js +++ b/microsite/pages/en/background.js @@ -112,7 +112,7 @@ const Background = props => { left: 0, right: 0, bottom: 0, - backgroundImage: `linear-gradient( to bottom, rgb(18, 18, 18), rgba(0, 0, 0, 0) ), url(../img/dot.svg);`, + backgroundImage: `linear-gradient( to bottom, rgb(18, 18, 18), rgba(0, 0, 0, 0) ), url(../img/dot.svg)`, }} /> diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 5cf2ee95e5..8d932cfd49 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -43,7 +43,8 @@ "lodash": "^4.17.15", "morgan": "^1.10.0", "stoppable": "^1.1.0", - "winston": "^3.2.1" + "winston": "^3.2.1", + "selfsigned": "^1.10.7" }, "peerDependencies": { "pg-connection-string": "^2.3.0" diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index cd8e445dd8..1182cc6388 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -19,7 +19,9 @@ import compression from 'compression'; import cors from 'cors'; import express, { Router } from 'express'; import helmet from 'helmet'; -import { Server } from 'http'; +import * as http from 'http'; +import * as https from 'https'; +import * as fs from 'fs'; import stoppable from 'stoppable'; import { Logger } from 'winston'; import { useHotCleanup } from '../../hot'; @@ -30,7 +32,12 @@ import { requestLoggingHandler, } from '../../middleware'; import { ServiceBuilder } from '../types'; -import { readBaseOptions, readCorsOptions } from './config'; +import { + readBaseOptions, + readCorsOptions, + readHttpsSettings, + HttpsSettings, +} from './config'; const DEFAULT_PORT = 7000; // '' is express default, which listens to all interfaces @@ -41,6 +48,7 @@ export class ServiceBuilderImpl implements ServiceBuilder { private host: string | undefined; private logger: Logger | undefined; private corsOptions: cors.CorsOptions | undefined; + private httpsSettings: HttpsSettings | undefined; private routers: [string, Router][]; // Reference to the module where builder is created - needed for hot module // reloading @@ -70,6 +78,11 @@ export class ServiceBuilderImpl implements ServiceBuilder { this.corsOptions = corsOptions; } + const httpsSettings = readHttpsSettings(backendConfig); + if (httpsSettings) { + this.httpsSettings = httpsSettings; + } + return this; } @@ -88,6 +101,11 @@ export class ServiceBuilderImpl implements ServiceBuilder { return this; } + setHttpsSettings(settings: HttpsSettings): ServiceBuilder { + this.httpsSettings = settings; + return this; + } + enableCors(options: cors.CorsOptions): ServiceBuilder { this.corsOptions = options; return this; @@ -98,9 +116,15 @@ export class ServiceBuilderImpl implements ServiceBuilder { return this; } - start(): Promise { + start(): Promise { const app = express(); - const { port, host, logger, corsOptions } = this.getOptions(); + const { + port, + host, + logger, + corsOptions, + httpsSettings, + } = this.getOptions(); app.use(helmet()); if (corsOptions) { @@ -121,20 +145,90 @@ export class ServiceBuilderImpl implements ServiceBuilder { reject(e); }); - const server = stoppable( - app.listen(port, host, () => { - logger.info(`Listening on ${host}:${port}`); - }), - 0, - ); + let server: http.Server; + + if (httpsSettings) { + logger.info('Initializing https server'); + + const credentials: { key: string; cert: string } = { + key: '', + cert: '', + }; + const signingOptions: any = httpsSettings?.certificate; + + if (signingOptions?.algorithm !== undefined) { + logger.info('Generating self-signed certificate with attributes'); + + const certificateAttributes: Array = Object.entries( + signingOptions.attributes, + ).map(([name, value]) => ({ name, value })); + + // TODO: Create a type def for selfsigned. + const signatures = require('selfsigned').generate( + certificateAttributes, + { + algorithm: signingOptions?.algorithm, + keySize: signingOptions?.size || 2048, + days: signingOptions?.days || 30, + }, + ); + + logger.info( + 'Bootstrapping key and cert from self-signed certificate', + ); + + credentials.key = signatures.private; + credentials.cert = signatures.cert; + } else { + if (fs.existsSync(signingOptions?.key)) { + if (fs.lstatSync(signingOptions?.key).isFile()) { + logger.info('Bootstrapping key from file'); + + credentials.key = fs.readFileSync(signingOptions?.key).toString(); + } + } else { + logger.info('Bootstrapping key from config'); + + credentials.key = signingOptions?.key; + } + + if (fs.existsSync(signingOptions?.cert)) { + if (fs.lstatSync(signingOptions?.cert).isFile()) { + logger.info('Bootstrapping cert from file'); + + credentials.cert = fs + .readFileSync(signingOptions?.cert) + .toString(); + } + } else { + logger.info('Bootstrapping cert from config'); + + credentials.cert = signingOptions?.cert; + } + } + + if (credentials.key === '' || credentials.cert === '') { + throw new Error('Invalid credentials'); + } + + server = https.createServer(credentials, app) as http.Server; + } else { + logger.info('Initializing http server'); + + server = http.createServer(app); + } + + const stoppableServer = stoppable(server, 0); + + stoppableServer.listen(port, host); useHotCleanup(this.module, () => - server.stop((e: any) => { + stoppableServer.stop((e: any) => { if (e) console.error(e); }), ); - resolve(server); + resolve(stoppableServer); }); } @@ -143,12 +237,14 @@ export class ServiceBuilderImpl implements ServiceBuilder { host: string; logger: Logger; corsOptions?: cors.CorsOptions; + httpsSettings?: HttpsSettings; } { return { port: this.port ?? DEFAULT_PORT, host: this.host ?? DEFAULT_HOST, logger: this.logger ?? getRootLogger(), corsOptions: this.corsOptions, + httpsSettings: this.httpsSettings, }; } } diff --git a/packages/backend-common/src/service/lib/config.ts b/packages/backend-common/src/service/lib/config.ts index 49f8dc4f04..e257bd4111 100644 --- a/packages/backend-common/src/service/lib/config.ts +++ b/packages/backend-common/src/service/lib/config.ts @@ -22,6 +22,41 @@ export type BaseOptions = { listenHost?: string; }; +export type CertificateOptions = { + key?: CertificateKeyOptions; + attributes?: CertificateAttributeOptions; +}; + +export type CertificateKeyOptions = { + size?: number; + algorithm?: string; + days?: number; +}; + +export type CertificateAttributeOptions = { + commonName?: string; +}; + +export type HttpsSettings = { + certificate: CertificateSigningOptions | CertificateReferenceOptions; +}; + +export type CertificateReferenceOptions = { + key: string; + cert: string; +}; + +export type CertificateSigningOptions = { + algorithm: string; + size?: number; + days?: number; + attributes?: CertificateAttributes; +}; + +export type CertificateAttributes = { + commonName?: string; +}; + /** * Reads some base options out of a config object. * @@ -40,6 +75,7 @@ export function readBaseOptions(config: ConfigReader): BaseOptions { if (typeof config.get('listen') === 'string') { // TODO(freben): Expand this to support more addresses and perhaps optional const { host, port } = parseListenAddress(config.getString('listen')); + return removeUnknown({ listenPort: port, listenHost: host, @@ -49,6 +85,7 @@ export function readBaseOptions(config: ConfigReader): BaseOptions { return removeUnknown({ listenPort: config.getOptionalNumber('listen.port'), listenHost: config.getOptionalString('listen.host'), + baseUrl: config.getOptionalString('baseUrl'), }); } @@ -86,6 +123,39 @@ export function readCorsOptions(config: ConfigReader): CorsOptions | undefined { }); } +/** + * Attempts to read a https settings object from the root of a config object. + * + * @param config The root of a backend config object + * @returns A https settings object, or undefined if not specified + * + * @example + * ```json + * { + * https: { + * certificate: ... + * } + * } + * ``` + */ +export function readHttpsSettings( + config: ConfigReader, +): HttpsSettings | undefined { + const cc = config.getOptionalConfig('https'); + + if (!cc) { + return undefined; + } + + const certificateConfig = cc.get('certificate'); + + const cfg = { + certificate: certificateConfig, + }; + + return removeUnknown(cfg as HttpsSettings); +} + function getOptionalStringOrStrings( config: ConfigReader, key: string, diff --git a/packages/backend-common/src/service/types.ts b/packages/backend-common/src/service/types.ts index 070794969f..d389f4b5ff 100644 --- a/packages/backend-common/src/service/types.ts +++ b/packages/backend-common/src/service/types.ts @@ -19,6 +19,7 @@ import cors from 'cors'; import { Router, RequestHandler } from 'express'; import { Server } from 'http'; import { Logger } from 'winston'; +import { HttpsSettings } from './lib/config'; export type ServiceBuilder = { /** @@ -39,6 +40,15 @@ export type ServiceBuilder = { */ setPort(port: number): ServiceBuilder; + /** + * Sets the host to listen on. + * + * '' is express default, which listens to all interfaces. + * + * @param host The host to listen on + */ + setHost(host: string): ServiceBuilder; + /** * Sets the logger to use for service-specific logging. * @@ -58,6 +68,15 @@ export type ServiceBuilder = { */ enableCors(options: cors.CorsOptions): ServiceBuilder; + /** + * Configure self-signed certificate generation options. + * + * If this method is not called, the resulting service will use sensible defaults + * + * @param options Standard certificate options + */ + setHttpsSettings(settings: HttpsSettings): ServiceBuilder; + /** * Adds a router (similar to the express .use call) to the service. * diff --git a/yarn.lock b/yarn.lock index 6a63b34141..9ab7af396b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9349,7 +9349,7 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -docusaurus@2.0.0-alpha.61: +docusaurus@^2.0.0-alpha.61: version "2.0.0-alpha.61" resolved "https://registry.npmjs.org/docusaurus/-/docusaurus-2.0.0-alpha.61.tgz#f347b81c98c66f1de3ecfccf63fa421ddff52fbb" integrity sha512-qDU3nOA4Xs95tIjjSETnEuRmTukTzgxyTZ5MgMyuG7y6h4oDHtpLcYf8F+xlXuuWHKv3VSxRJNzV8fZHPgnK3g== From d982278fc34450f59c5f237502413ae92c3cb4bc Mon Sep 17 00:00:00 2001 From: "toban@dfds.com" Date: Tue, 18 Aug 2020 10:27:48 +0200 Subject: [PATCH 02/10] =fixed broken microsite --- microsite/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/package.json b/microsite/package.json index 6a10628b5a..dd8957245a 100644 --- a/microsite/package.json +++ b/microsite/package.json @@ -6,7 +6,7 @@ "scripts": { "examples": "docusaurus-examples", "start": "docusaurus-start", - "build": "docusaurus-build && cp static/img/*.svg build/backstage/img/", + "build": "docusaurus-build", "publish-gh-pages": "docusaurus-publish", "write-translations": "docusaurus-write-translations", "version": "docusaurus-version", From 44e09bd980afb1cf936ddbe6679eb7f34239dde9 Mon Sep 17 00:00:00 2001 From: "toban@dfds.com" Date: Tue, 18 Aug 2020 10:37:38 +0200 Subject: [PATCH 03/10] =added disabled config for https w. self-signed cert --- app-config.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app-config.yaml b/app-config.yaml index a0233991f8..f3b3b8d00c 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -13,6 +13,13 @@ backend: database: client: sqlite3 connection: ':memory:' + # https: + # certificate: + # size: 2048 + # algorithm: sha256 + # days: 30 + # attributes: + # commonName: 'contoso.com' proxy: '/circleci/api': From 141bb0b9ab3c902b0c7715e606b251a2fd4ac7ef Mon Sep 17 00:00:00 2001 From: "toban@dfds.com" Date: Tue, 18 Aug 2020 16:53:37 +0200 Subject: [PATCH 04/10] =triggering checks to see why CLI tests timed out --- app-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-config.yaml b/app-config.yaml index f3b3b8d00c..0e94367aa1 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -19,7 +19,7 @@ backend: # algorithm: sha256 # days: 30 # attributes: - # commonName: 'contoso.com' + # commonName: 'dfds.com' proxy: '/circleci/api': From 0ee6ba404905cce6ddcfcd052dbcb7b56704333d Mon Sep 17 00:00:00 2001 From: Tobias Andersen Date: Thu, 20 Aug 2020 11:11:53 +0200 Subject: [PATCH 05/10] =Fixed problem with the stoppable wrapper not triggering the listen method on the http server object --- .../backend-common/src/service/lib/ServiceBuilderImpl.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index 1182cc6388..806096915b 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -218,9 +218,12 @@ export class ServiceBuilderImpl implements ServiceBuilder { server = http.createServer(app); } - const stoppableServer = stoppable(server, 0); + const stoppableServer = stoppable( + server.listen(port, host, () => { + logger.info(`Listening on ${host}:${port}`); + }), 0); - stoppableServer.listen(port, host); + //stoppableServer.listen(port, host); useHotCleanup(this.module, () => stoppableServer.stop((e: any) => { From d263219c2b8aa55a82ead09c2adf2a79cc28678f Mon Sep 17 00:00:00 2001 From: Tobias Andersen Date: Thu, 20 Aug 2020 11:12:16 +0200 Subject: [PATCH 06/10] =Fixed problem with the stoppable wrapper not triggering the listen method on the http server object --- packages/backend-common/src/service/lib/ServiceBuilderImpl.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index 806096915b..0e0feb6a37 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -223,8 +223,6 @@ export class ServiceBuilderImpl implements ServiceBuilder { logger.info(`Listening on ${host}:${port}`); }), 0); - //stoppableServer.listen(port, host); - useHotCleanup(this.module, () => stoppableServer.stop((e: any) => { if (e) console.error(e); From 17233abfcbc37915b0d9158c3284811ef49c243a Mon Sep 17 00:00:00 2001 From: Tobias Andersen Date: Thu, 20 Aug 2020 14:55:42 +0200 Subject: [PATCH 07/10] =Partial commit, have to go home --- .../src/service/lib/ServiceBuilderImpl.ts | 6 ++- .../src/service/lib/hostFactory.ts | 41 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 packages/backend-common/src/service/lib/hostFactory.ts diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index 0e0feb6a37..e75ae8069f 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -38,6 +38,10 @@ import { readHttpsSettings, HttpsSettings, } from './config'; +import { + createHttpServer, + createHttpsServer, +} from './hostFactory'; const DEFAULT_PORT = 7000; // '' is express default, which listens to all interfaces @@ -215,7 +219,7 @@ export class ServiceBuilderImpl implements ServiceBuilder { } else { logger.info('Initializing http server'); - server = http.createServer(app); + server = createHttpServer(app); } const stoppableServer = stoppable( diff --git a/packages/backend-common/src/service/lib/hostFactory.ts b/packages/backend-common/src/service/lib/hostFactory.ts new file mode 100644 index 0000000000..9b850431fb --- /dev/null +++ b/packages/backend-common/src/service/lib/hostFactory.ts @@ -0,0 +1,41 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import express from 'express'; +import * as http from 'http'; +import * as https from 'https'; + +/** + * Reads some base options out of a config object. + * + * @param config The root of a backend config object + * @returns A base options object + * + * @example + * ```json + * { + * baseUrl: "http://localhost:7000", + * listen: "0.0.0.0:7000" + * } + * ``` + */ +export function createHttpServer(app: express.Express): http.Server { + return http.createServer(app); +} + + +export function createHttpsServer(app: express.Express): http.Server { + return https.createServer(app); +} \ No newline at end of file From 6e3cb6c874b66f30c22b019fef6b0cb8f1ded953 Mon Sep 17 00:00:00 2001 From: "toban@dfds.com" Date: Fri, 21 Aug 2020 10:51:37 +0200 Subject: [PATCH 08/10] =removing support for loading certs via file paths, adding host factory module, removing config section --- app-config.yaml | 7 -- .../src/service/lib/ServiceBuilderImpl.ts | 87 ++----------------- .../src/service/lib/hostFactory.ts | 56 +++++++++++- 3 files changed, 60 insertions(+), 90 deletions(-) diff --git a/app-config.yaml b/app-config.yaml index 0e94367aa1..a0233991f8 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -13,13 +13,6 @@ backend: database: client: sqlite3 connection: ':memory:' - # https: - # certificate: - # size: 2048 - # algorithm: sha256 - # days: 30 - # attributes: - # commonName: 'dfds.com' proxy: '/circleci/api': diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index e75ae8069f..899db248d6 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -21,7 +21,6 @@ import express, { Router } from 'express'; import helmet from 'helmet'; import * as http from 'http'; import * as https from 'https'; -import * as fs from 'fs'; import stoppable from 'stoppable'; import { Logger } from 'winston'; import { useHotCleanup } from '../../hot'; @@ -38,10 +37,7 @@ import { readHttpsSettings, HttpsSettings, } from './config'; -import { - createHttpServer, - createHttpsServer, -} from './hostFactory'; +import { createHttpServer, createHttpsServer } from './hostFactory'; const DEFAULT_PORT = 7000; // '' is express default, which listens to all interfaces @@ -149,83 +145,16 @@ export class ServiceBuilderImpl implements ServiceBuilder { reject(e); }); - let server: http.Server; - - if (httpsSettings) { - logger.info('Initializing https server'); - - const credentials: { key: string; cert: string } = { - key: '', - cert: '', - }; - const signingOptions: any = httpsSettings?.certificate; - - if (signingOptions?.algorithm !== undefined) { - logger.info('Generating self-signed certificate with attributes'); - - const certificateAttributes: Array = Object.entries( - signingOptions.attributes, - ).map(([name, value]) => ({ name, value })); - - // TODO: Create a type def for selfsigned. - const signatures = require('selfsigned').generate( - certificateAttributes, - { - algorithm: signingOptions?.algorithm, - keySize: signingOptions?.size || 2048, - days: signingOptions?.days || 30, - }, - ); - - logger.info( - 'Bootstrapping key and cert from self-signed certificate', - ); - - credentials.key = signatures.private; - credentials.cert = signatures.cert; - } else { - if (fs.existsSync(signingOptions?.key)) { - if (fs.lstatSync(signingOptions?.key).isFile()) { - logger.info('Bootstrapping key from file'); - - credentials.key = fs.readFileSync(signingOptions?.key).toString(); - } - } else { - logger.info('Bootstrapping key from config'); - - credentials.key = signingOptions?.key; - } - - if (fs.existsSync(signingOptions?.cert)) { - if (fs.lstatSync(signingOptions?.cert).isFile()) { - logger.info('Bootstrapping cert from file'); - - credentials.cert = fs - .readFileSync(signingOptions?.cert) - .toString(); - } - } else { - logger.info('Bootstrapping cert from config'); - - credentials.cert = signingOptions?.cert; - } - } - - if (credentials.key === '' || credentials.cert === '') { - throw new Error('Invalid credentials'); - } - - server = https.createServer(credentials, app) as http.Server; - } else { - logger.info('Initializing http server'); - - server = createHttpServer(app); - } + const server: http.Server = httpsSettings + ? createHttpsServer(app, httpsSettings, logger) + : createHttpServer(app, logger); const stoppableServer = stoppable( server.listen(port, host, () => { - logger.info(`Listening on ${host}:${port}`); - }), 0); + logger.info(`Listening on ${host}:${port}`); + }), + 0, + ); useHotCleanup(this.module, () => stoppableServer.stop((e: any) => { diff --git a/packages/backend-common/src/service/lib/hostFactory.ts b/packages/backend-common/src/service/lib/hostFactory.ts index 9b850431fb..778601e3c4 100644 --- a/packages/backend-common/src/service/lib/hostFactory.ts +++ b/packages/backend-common/src/service/lib/hostFactory.ts @@ -16,6 +16,8 @@ import express from 'express'; import * as http from 'http'; import * as https from 'https'; +import { Logger } from 'winston'; +import { HttpsSettings } from './config'; /** * Reads some base options out of a config object. @@ -31,11 +33,57 @@ import * as https from 'https'; * } * ``` */ -export function createHttpServer(app: express.Express): http.Server { +export function createHttpServer( + app: express.Express, + logger: Logger, +): http.Server { + logger.info('Initializing http server'); + return http.createServer(app); } +export function createHttpsServer( + app: express.Express, + httpsSettings: HttpsSettings, + logger: Logger, +): http.Server { + logger.info('Initializing https server'); -export function createHttpsServer(app: express.Express): http.Server { - return https.createServer(app); -} \ No newline at end of file + const credentials: { key: string; cert: string } = { + key: '', + cert: '', + }; + + const signingOptions: any = httpsSettings?.certificate; + + if (signingOptions?.algorithm !== undefined) { + logger.info('Generating self-signed certificate with attributes'); + + const certificateAttributes: Array = Object.entries( + signingOptions.attributes, + ).map(([name, value]) => ({ name, value })); + + // TODO: Create a type def for selfsigned. + const signatures = require('selfsigned').generate(certificateAttributes, { + algorithm: signingOptions?.algorithm, + keySize: signingOptions?.size || 2048, + days: signingOptions?.days || 30, + }); + + logger.info('Bootstrapping self-signed certificate'); + + credentials.key = signatures.private; + credentials.cert = signatures.cert; + } else { + logger.info('Bootstrapping cert from config'); + + credentials.key = signingOptions?.key; + credentials.cert = signingOptions?.cert; + } + + if (credentials.key === '' || credentials.cert === '') { + throw new Error('Invalid credentials'); + } + + return https.createServer(credentials, app) as http.Server; +} From f66eb57c10bf63bee4eeebd70f89565142c8ece0 Mon Sep 17 00:00:00 2001 From: "toban@dfds.com" Date: Fri, 21 Aug 2020 10:58:17 +0200 Subject: [PATCH 09/10] =add inline documentation --- .../src/service/lib/hostFactory.ts | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/packages/backend-common/src/service/lib/hostFactory.ts b/packages/backend-common/src/service/lib/hostFactory.ts index 778601e3c4..8fab2fd4ab 100644 --- a/packages/backend-common/src/service/lib/hostFactory.ts +++ b/packages/backend-common/src/service/lib/hostFactory.ts @@ -20,34 +20,37 @@ import { Logger } from 'winston'; import { HttpsSettings } from './config'; /** - * Reads some base options out of a config object. + * Creates a Http server instance based on an Express application. * - * @param config The root of a backend config object - * @returns A base options object + * @param app The Express application object + * @param logger Optional Winston logger object + * @returns A Http server instance * - * @example - * ```json - * { - * baseUrl: "http://localhost:7000", - * listen: "0.0.0.0:7000" - * } - * ``` */ export function createHttpServer( app: express.Express, - logger: Logger, + logger?: Logger, ): http.Server { - logger.info('Initializing http server'); + logger?.info('Initializing http server'); return http.createServer(app); } +/** + * Creates a Https server instance based on an Express application. + * + * @param app The Express application object + * @param httpsSettings HttpsSettings for self-signed certificate generation + * @param logger Optional Winston logger object + * @returns A Https server instance + * + */ export function createHttpsServer( app: express.Express, httpsSettings: HttpsSettings, - logger: Logger, + logger?: Logger, ): http.Server { - logger.info('Initializing https server'); + logger?.info('Initializing https server'); const credentials: { key: string; cert: string } = { key: '', @@ -57,7 +60,7 @@ export function createHttpsServer( const signingOptions: any = httpsSettings?.certificate; if (signingOptions?.algorithm !== undefined) { - logger.info('Generating self-signed certificate with attributes'); + logger?.info('Generating self-signed certificate with attributes'); const certificateAttributes: Array = Object.entries( signingOptions.attributes, @@ -70,12 +73,12 @@ export function createHttpsServer( days: signingOptions?.days || 30, }); - logger.info('Bootstrapping self-signed certificate'); + logger?.info('Bootstrapping self-signed certificate'); credentials.key = signatures.private; credentials.cert = signatures.cert; } else { - logger.info('Bootstrapping cert from config'); + logger?.info('Bootstrapping cert from config'); credentials.key = signingOptions?.key; credentials.cert = signingOptions?.cert; From 5bffcb108d36939fe43e54f9330ab560702b4e5f Mon Sep 17 00:00:00 2001 From: "toban@dfds.com" Date: Fri, 21 Aug 2020 11:03:07 +0200 Subject: [PATCH 10/10] =removing unused imports --- packages/backend-common/src/service/lib/ServiceBuilderImpl.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index 899db248d6..4669c00e68 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -20,7 +20,6 @@ import cors from 'cors'; import express, { Router } from 'express'; import helmet from 'helmet'; import * as http from 'http'; -import * as https from 'https'; import stoppable from 'stoppable'; import { Logger } from 'winston'; import { useHotCleanup } from '../../hot';