fix: increase nginx transport security

This commit is contained in:
Rainer Killinger
2019-02-27 16:28:50 +00:00
committed by Rainer Killinger
parent 5f969c53f6
commit 8fe6a2795f
6 changed files with 75 additions and 13 deletions

View File

@@ -19,6 +19,16 @@ import {SMTP} from '@openstapps/logger/lib/SMTP';
// use SMTP as a default monitoring system for logger.error();
export const logger = new Logger(SMTP.getInstance());
/**
* A representation of the file paths of the needed ssl certificates
*/
export interface SSLFilePaths {
certificate: string;
certificateChain: string;
certificateKey: string;
dhparam: string;
}
/**
* A representation of the config file
*/
@@ -27,7 +37,7 @@ export interface ConfigFile {
hiddenRoutes: string[];
outdatedVersions: string[];
output: string;
sslFiles: string[];
sslFilePaths: SSLFilePaths;
visibleRoutes: string[];
}
@@ -41,3 +51,27 @@ export interface TemplateView {
staticRoute: string;
visibleRoutes: string;
}
/**
* Nginx protocol parameters to harden serverside settings
*/
export const protocolHardeningParameters: string = `
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains;";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";`;
// tslint:disable:max-line-length
/**
* Nginx ssl parameters to harden serverside settings
*/
export const sslHardeningParameters: string = `
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
ssl_ecdh_curve X25519:secp384r1;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;`;

View File

@@ -18,7 +18,14 @@ import * as Dockerode from 'dockerode';
import {existsSync, readFile} from 'fs-extra';
import {render} from 'mustache';
import {join} from 'path';
import {ConfigFile, logger, TemplateView} from './common';
import {
ConfigFile,
logger,
protocolHardeningParameters,
SSLFilePaths,
sslHardeningParameters,
TemplateView,
} from './common';
const configFile: ConfigFile = config.util.toObject();
@@ -123,7 +130,7 @@ export function generateUpstreamMap(
* @param sslFiles
* @returns {string}
*/
function generateListener(sslFiles: string[]) {
function generateListener(sslFilePaths: SSLFilePaths) {
function isSSLCert(path: string) {
return existsSync(path) && /.*\.crt$/.test(path);
@@ -133,17 +140,31 @@ function generateListener(sslFiles: string[]) {
return existsSync(path) && /.*\.key$/.test(path);
}
function isPEMFile(path: string) {
return existsSync(path) && /.*\.pem$/.test(path);
}
let listener = '';
if (Array.isArray(sslFiles) && sslFiles.length === 2 && sslFiles.some(isSSLCert) && sslFiles.some(isSSLKey)) {
if (typeof sslFilePaths !== 'undefined' &&
typeof sslFilePaths.certificate === 'string' && isSSLCert(sslFilePaths.certificate) &&
typeof sslFilePaths.certificateChain === 'string' && isSSLCert(sslFilePaths.certificate) &&
typeof sslFilePaths.certificateKey === 'string' && isSSLKey(sslFilePaths.certificate) &&
typeof sslFilePaths.dhparam === 'string' && isPEMFile(sslFilePaths.dhparam)
) {
// https listener
listener = 'listen 443 ssl default_server;\n' +
`ssl_certificate ${sslFiles.find(isSSLCert)};\n` +
`ssl_certificate_key ${sslFiles.find(isSSLKey)};\n`;
`ssl_certificate ${sslFilePaths.certificate};\n` +
`ssl_certificate_key ${sslFilePaths.certificateKey};\n` +
`ssl_trusted_certificate ${sslFilePaths.certificateChain};\n` +
`ssl_dhparam ${sslFilePaths.dhparam};\n` +
`${sslHardeningParameters}`;
} else {
// default http listener
listener = 'listen 80 default_server;';
logger.warn('Https usage is not setup properly, falling back to http!');
}
listener = `${listener}\n${protocolHardeningParameters}\n`;
return listener;
}
@@ -183,7 +204,7 @@ export async function getTemplateView(containers: Dockerode.ContainerInfo[]): Pr
return {
dockerVersionMap: generateUpstreamMap(configFile.activeVersions, configFile.outdatedVersions, containers),
hiddenRoutes: (await Promise.all(hiddenRoutesPromises)).join(''),
listener: generateListener(configFile.sslFiles),
listener: generateListener(configFile.sslFilePaths),
staticRoute: await renderTemplate(join('fixtures', 'staticRoute.template'), {cors}),
visibleRoutes: (await Promise.all(visibleRoutesPromises)).join(''),
};