Skip to content

Commit

Permalink
feat(tls): Allow to set TLS settings for API server
Browse files Browse the repository at this point in the history
  • Loading branch information
andris9 committed Nov 6, 2023
1 parent eff7f3a commit 67f5aa3
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ yarn.lock
swagger.json
version-info.json
ee-dist/
config/development.toml
config/development*
.vscode
.okta.env
system.env
Expand Down
15 changes: 14 additions & 1 deletion lib/imapproxy/imap-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@ const config = require('wild-config');
const logger = require('../logger');
const { oauth2Apps, oauth2ProviderData } = require('../oauth2-apps');

const { getDuration, getBoolean, resolveCredentials, hasEnvValue, readEnvValue, emitChangeEvent, matchIp, getLocalAddress } = require('../tools');
const {
getDuration,
getBoolean,
resolveCredentials,
hasEnvValue,
readEnvValue,
emitChangeEvent,
matchIp,
getLocalAddress,
loadTlsConfig
} = require('../tools');

const { redis } = require('../db');
const { Account } = require('../account');
Expand Down Expand Up @@ -522,6 +532,9 @@ module.exports.run = async () => {
// load certificates
let serviceUrl = await settings.get('serviceUrl');
let hostname = (new URL(serviceUrl).hostname || '').toString().toLowerCase().trim();

loadTlsConfig(serverOptions, 'EENGINE_IMAPPROXY_TLS_');

if (hostname) {
let certificateData = await certs.getCertificate(hostname, true);
if (certificateData && certificateData.status === 'valid') {
Expand Down
47 changes: 44 additions & 3 deletions lib/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -1515,10 +1515,10 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEV3QUiYsp13nD9suD1/ZkEXnuMoSg
if (typeof process.env[`${key}_FILE`] === 'string' && process.env[`${key}_FILE`]) {
try {
// try to load from file
process.env[key] = Fs.readFileSync(process.env[`${key}_FILE`], 'utf-8').replace(/\r?\n$/, '');
process.env[key] = Fs.readFileSync(process.env[`${key}_FILE`], 'utf-8').replace(/\r?\n/g, '\n').trim();
logger.trace({ msg: 'Loaded environment value from file', key, file: process.env[`${key}_FILE`] });
} catch (err) {
logger.error({ msg: 'Failed to load environment value from file', key, file: process.env[`${key}_FILE`], err });
logger.fatal({ msg: 'Failed to load environment value from file', key, file: process.env[`${key}_FILE`], err });
process.env[key] = '';
}
return process.env[key];
Expand Down Expand Up @@ -1625,5 +1625,46 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEV3QUiYsp13nD9suD1/ZkEXnuMoSg
return false;
},

pfStructuredClone: typeof structuredClone === 'function' ? structuredClone : data => JSON.parse(JSON.stringify(data))
pfStructuredClone: typeof structuredClone === 'function' ? structuredClone : data => JSON.parse(JSON.stringify(data)),

loadTlsConfig(ref, envPrefix) {
if (!ref || typeof ref !== 'object') {
return false;
}

for (let key of ['ca', 'cert', 'key', 'dhparam']) {
let path = `${key}Path`;
if (ref[path] && typeof ref[path] === 'string') {
// read value from file
try {
ref[key] = Fs.readFileSync(ref[path], 'utf-8').replace(/\r?\n/g, '\n').trim();
logger.trace({ msg: 'Loaded environment TLS value from file', path, file: ref[path] });
delete ref[path];
} catch (err) {
logger.fatal({ msg: 'Failed to load TLS value from file', path, file: ref[path], err });
ref[key] = null;
}
}
}

// string keys for TLS
for (let key of ['ca', 'cert', 'ciphers', 'ecdhCurve', 'key', 'dhparam', 'minVersion', 'maxVersion', 'passphrase']) {
let envKey = `${envPrefix}${key.replace(/[A-Z]/g, c => `_${c}`).toUpperCase()}`;
if (module.exports.hasEnvValue(envKey)) {
ref[key] = module.exports.readEnvValue(envKey);
}
}

// Boolean keys for TLS
for (let key of ['rejectUnauthorized', 'requestCert']) {
if (ref[key] && typeof ref[key] !== 'boolean') {
ref[key] = module.exports.getBoolean(ref[key]);
}

let envKey = `${envPrefix}${key.replace(/[A-Z]/g, c => `_${c}`).toUpperCase()}`;
if (module.exports.hasEnvValue(envKey)) {
ref[key] = module.exports.getBoolean(module.exports.readEnvValue(envKey));
}
}
}
};
2 changes: 1 addition & 1 deletion server.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ config.workers.webhooks = Number(readEnvValue('EENGINE_WORKERS_WEBHOOKS')) || co
config.workers.submit = Number(readEnvValue('EENGINE_WORKERS_SUBMIT')) || config.workers.submit || 1;

config.api.port =
(readEnvValue('EENGINE_PORT') && Number(readEnvValue('EENGINE_PORT'))) || (readEnvValue('PORT') && Number(readEnvValue('PORT'))) || config.api.port;
(hasEnvValue('EENGINE_PORT') && Number(readEnvValue('EENGINE_PORT'))) || (hasEnvValue('PORT') && Number(readEnvValue('PORT'))) || config.api.port;
config.api.host = readEnvValue('EENGINE_HOST') || config.api.host;

config.log.level = readEnvValue('EENGINE_LOG_LEVEL') || config.log.level;
Expand Down
19 changes: 15 additions & 4 deletions workers/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ const {
matchIp,
getSignedFormData,
threadStats,
detectAutomatedRequest
detectAutomatedRequest,
hasEnvValue,
getBoolean,
loadTlsConfig
} = require('../lib/tools');

const Bugsnag = require('@bugsnag/js');
Expand Down Expand Up @@ -160,14 +163,15 @@ const { OUTLOOK_SCOPES } = require('../lib/oauth/outlook');
const { GMAIL_SCOPES } = require('../lib/oauth/gmail');
const { MAIL_RU_SCOPES } = require('../lib/oauth/mail-ru');

const REDACTED_KEYS = ['req.headers.authorization', 'req.headers.cookie'];
const REDACTED_KEYS = ['req.headers.authorization', 'req.headers.cookie', 'err.rawPacket'];

const SMTP_TEST_HOST = 'https://api.nodemailer.com';

config.api = config.api || {
port: 3000,
host: '127.0.0.1',
proxy: false
proxy: false,
tls: false
};

config.service = config.service || {};
Expand All @@ -183,9 +187,15 @@ const EENGINE_TIMEOUT = getDuration(readEnvValue('EENGINE_TIMEOUT') || config.se
const MAX_ATTACHMENT_SIZE = getByteSize(readEnvValue('EENGINE_MAX_SIZE') || config.api.maxSize) || DEFAULT_MAX_ATTACHMENT_SIZE;

const API_PORT =
(readEnvValue('EENGINE_PORT') && Number(readEnvValue('EENGINE_PORT'))) || (readEnvValue('PORT') && Number(readEnvValue('PORT'))) || config.api.port;
(hasEnvValue('EENGINE_PORT') && Number(readEnvValue('EENGINE_PORT'))) || (hasEnvValue('PORT') && Number(readEnvValue('PORT'))) || config.api.port;
const API_HOST = readEnvValue('EENGINE_HOST') || config.api.host;

// Either an object (TLS enabled) or `false` (TLS disabled)
const API_TLS = hasEnvValue('EENGINE_API_TLS') ? getBoolean(readEnvValue('EENGINE_API_TLS')) && (config.api.tls || {}) : config.api.tls || false;

// Merge TLS settings from config params and environment
loadTlsConfig(API_TLS, 'EENGINE_API_TLS_');

const IMAP_WORKER_COUNT = getWorkerCount(readEnvValue('EENGINE_WORKERS') || (config.workers && config.workers.imap)) || 4;

// Max POST body size for message uploads
Expand Down Expand Up @@ -464,6 +474,7 @@ const init = async () => {
const server = Hapi.server({
port: API_PORT,
host: API_HOST,
tls: API_TLS,

router: {
stripTrailingSlash: true
Expand Down
4 changes: 3 additions & 1 deletion workers/smtp.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const packageData = require('../package.json');
const config = require('wild-config');
const logger = require('../lib/logger');

const { getDuration, emitChangeEvent, readEnvValue, matchIp, threadStats } = require('../lib/tools');
const { getDuration, emitChangeEvent, readEnvValue, matchIp, threadStats, loadTlsConfig } = require('../lib/tools');

const Bugsnag = require('@bugsnag/js');
if (readEnvValue('BUGSNAG_API_KEY')) {
Expand Down Expand Up @@ -407,6 +407,8 @@ async function init() {
serverOptions.secure = true;
serverOptions.allowInsecureAuth = false;

loadTlsConfig(serverOptions, 'EENGINE_SMTP_TLS_');

// load certificates
let serviceUrl = await settings.get('serviceUrl');
let hostname = (new URL(serviceUrl).hostname || '').toString().toLowerCase().trim();
Expand Down

0 comments on commit 67f5aa3

Please sign in to comment.