wildduck/acme.js
Richard Bateman 8b926d936f Be resilient to missing acme config
In the gitter chat someone with an old config format was having issues
because they didn't have an [acme] section in the config file; there isn't
really any reason you should need that if you don't use it, so this fix
just makes it so it will disable acme if the config isn't present as well
as if it is but it's disabled
2022-02-02 09:35:30 -07:00

119 lines
3.3 KiB
JavaScript

'use strict';
const config = require('wild-config');
const restify = require('restify');
const log = require('npmlog');
const logger = require('restify-logger');
const db = require('./lib/db');
const Gelf = require('gelf');
const os = require('os');
const acmeRoutes = require('./lib/api/acme');
let loggelf;
const serverOptions = {
name: 'WildDuck ACME Agent',
strictRouting: true,
maxParamLength: 196
};
const server = restify.createServer(serverOptions);
server.use(restify.plugins.gzipResponse());
server.use(
restify.plugins.queryParser({
allowDots: true,
mapParams: true
})
);
logger.token('user-ip', req => ((req.params && req.params.ip) || '').toString().substr(0, 40) || '-');
logger.token('user-sess', req => (req.params && req.params.sess) || '-');
logger.token('user', req => (req.user && req.user.toString()) || '-');
logger.token('url', req => {
if (/\baccessToken=/.test(req.url)) {
return req.url.replace(/\baccessToken=[^&]+/g, 'accessToken=' + 'x'.repeat(6));
}
return req.url;
});
server.use(
logger(':remote-addr :user [:user-ip/:user-sess] :method :url :status :time-spent :append', {
stream: {
write: message => {
message = (message || '').toString();
if (message) {
log.http('ACME', message.replace('\n', '').trim());
}
}
}
})
);
module.exports = done => {
if (!config.acme || !config.acme.agent || !config.acme.agent.enabled) {
return setImmediate(() => done(null, false));
}
let started = false;
const component = config.log.gelf.component || 'wildduck';
const hostname = config.log.gelf.hostname || os.hostname();
const gelf =
config.log.gelf && config.log.gelf.enabled
? new Gelf(config.log.gelf.options)
: {
// placeholder
emit: (key, message) => log.info('Gelf', JSON.stringify(message))
};
loggelf = message => {
if (typeof message === 'string') {
message = {
short_message: message
};
}
message = message || {};
if (!message.short_message || message.short_message.indexOf(component.toUpperCase()) !== 0) {
message.short_message = component.toUpperCase() + ' ' + (message.short_message || '');
}
message.facility = component; // facility is deprecated but set by the driver if not provided
message.host = hostname;
message.timestamp = Date.now() / 1000;
message._component = component;
Object.keys(message).forEach(key => {
if (!message[key]) {
delete message[key];
}
});
gelf.emit('gelf.log', message);
};
server.loggelf = message => loggelf(message);
acmeRoutes(db, server);
server.on('error', err => {
if (!started) {
started = true;
return done(err);
}
log.error('ACME', err);
});
server.listen(config.acme.agent.port, config.acme.agent.host, () => {
if (started) {
return server.close();
}
started = true;
log.info('ACME', 'Server listening on %s:%s', config.acme.agent.host || '0.0.0.0', config.acme.agent.port);
done(null, server);
});
};