backend-common: replace generated cert params with a simple bool switch, and fix certificate generation

This commit is contained in:
Patrik Oldsberg
2020-12-30 12:14:41 +01:00
parent 0e97202824
commit 751f58ff7c
3 changed files with 115 additions and 30 deletions
+35 -20
View File
@@ -32,26 +32,41 @@ export interface Config {
port?: string | number;
};
/** HTTPS configuration for the backend. If omitted the backend will serve HTTP */
https?: {
/** Certificate configuration or parameters for generating a self-signed certificate */
certificate?:
| {
/** Algorithm to use to generate a self-signed certificate */
algorithm: string;
keySize?: number;
days?: number;
}
| {
/** PEM encoded certificate. Use $file to load in a file */
cert: string;
/**
* PEM encoded certificate key. Use $file to load in a file.
* @visibility secret
*/
key: string;
};
};
/**
* HTTPS configuration for the backend. If omitted the backend will serve HTTP.
*
* Setting this to `true` will cause self-signed certificates to be generated, which
* can be useful for local development or other non-production scenarios.
*/
https?:
| true
| {
/**
* Certificate configuration or parameters for generating a self-signed certificate
*
* Setting parameters for self-signed certificates is deprecated and will be removed in
* the future, set `backend.https = true` instead.
*/
certificate?:
| {
/** Algorithm to use to generate a self-signed certificate */
algorithm?: string;
keySize?: number;
days?: number;
attributes: {
commonName: string;
};
}
| {
/** PEM encoded certificate. Use $file to load in a file */
cert: string;
/**
* PEM encoded certificate key. Use $file to load in a file.
* @visibility secret
*/
key: string;
};
};
/** Database connection configuration, select database type using the `client` field */
database:
@@ -47,14 +47,14 @@ export type CertificateReferenceOptions = {
};
export type CertificateSigningOptions = {
algorithm: string;
algorithm?: string;
size?: number;
days?: number;
attributes?: CertificateAttributes;
attributes: CertificateAttributes;
};
export type CertificateAttributes = {
commonName?: string;
commonName: string;
};
/**
@@ -193,8 +193,26 @@ export function readCspOptions(
* ```
*/
export function readHttpsSettings(config: Config): HttpsSettings | undefined {
const cc = config.getOptionalConfig('https');
const https = config.get('https');
if (https === true) {
const baseUrl = config.getString('baseUrl');
let commonName;
try {
commonName = new URL(baseUrl).hostname;
} catch (error) {
throw new Error(`Invalid backend.baseUrl "${baseUrl}"`);
}
return {
certificate: {
attributes: {
commonName,
},
},
};
}
const cc = config.getOptionalConfig('https');
if (!cc) {
return undefined;
}
@@ -59,26 +59,78 @@ export function createHttpsServer(
const signingOptions: any = httpsSettings?.certificate;
if (signingOptions?.algorithm !== undefined) {
if (signingOptions?.attributes) {
logger?.info('Generating self-signed certificate with attributes');
if (signingOptions?.algorithm) {
logger?.warn(
'Certificate generation configuration with parameters in backend.https.certificate is deprecated, set backend.https = true instead',
);
}
const certificateAttributes: Array<any> = 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,
algorithm: signingOptions?.algorithm || 'sha256',
keySize: signingOptions?.size || 2048,
days: signingOptions?.days || 30,
extensions: [
{
name: 'keyUsage',
keyCertSign: true,
digitalSignature: true,
nonRepudiation: true,
keyEncipherment: true,
dataEncipherment: true,
},
{
name: 'extKeyUsage',
serverAuth: true,
clientAuth: true,
codeSigning: true,
timeStamping: true,
},
{
name: 'subjectAltName',
altNames: [
{
type: 2, // DNS
value: 'localhost',
},
{
type: 2,
value: 'localhost.localdomain',
},
{
type: 2,
value: '[::1]',
},
{
type: 7, // IP
ip: '127.0.0.1',
},
{
type: 7,
ip: 'fe80::1',
},
...(signingOptions.attributes.commonName
? [
{
type: 2, // DNS
value: signingOptions.attributes.commonName,
},
]
: []),
],
},
],
});
logger?.info('Bootstrapping self-signed certificate');
credentials.key = signatures.private;
credentials.cert = signatures.cert;
} else {
logger?.info('Bootstrapping cert from config');
logger?.info('Loading certificate from config');
credentials.key = signingOptions?.key;
credentials.cert = signingOptions?.cert;