Files
nginx-proxy-manager/src/backend/internal/ssl.js
2018-08-02 19:48:47 +10:00

165 lines
5.0 KiB
JavaScript

'use strict';
const fs = require('fs');
const Liquid = require('liquidjs');
const timestamp = require('unix-timestamp');
const internalNginx = require('./nginx');
const logger = require('../logger').ssl;
const utils = require('../lib/utils');
const error = require('../lib/error');
timestamp.round = true;
const internalSsl = {
interval_timeout: 1000 * 60 * 60 * 12, // 12 hours
interval: null,
interval_processing: false,
initTimer: () => {
logger.info('Let\'s Encrypt Renewal Timer initialized');
internalSsl.interval = setInterval(internalSsl.processExpiringHosts, internalSsl.interval_timeout);
},
/**
* Triggered by a timer, this will check for expiring hosts and renew their ssl certs if required
*/
processExpiringHosts: () => {
if (!internalSsl.interval_processing) {
logger.info('Renewing SSL certs close to expiry...');
return utils.exec('/usr/bin/certbot renew -q')
.then(result => {
logger.info(result);
internalSsl.interval_processing = false;
return internalNginx.reload()
.then(() => {
logger.info('Renew Complete');
return result;
});
})
.catch(err => {
logger.error(err);
internalSsl.interval_processing = false;
});
}
},
/**
* @param {String} host_type
* @param {Object} host
* @returns {Boolean}
*/
hasValidSslCerts: (host_type, host) => {
host_type = host_type.replace(new RegExp('-', 'g'), '_');
let le_path = '/etc/letsencrypt/live/' + host_type + '-' + host.id;
return fs.existsSync(le_path + '/fullchain.pem') && fs.existsSync(le_path + '/privkey.pem');
},
/**
* @param {String} host_type
* @param {Object} host
* @returns {Promise}
*/
requestSsl: (host_type, host) => {
logger.info('Requesting SSL certificates for ' + host_type + ' #' + host.id);
// TODO
return utils.exec('/usr/bin/letsencrypt certonly --agree-tos --email "' + host.letsencrypt_email + '" -n -a webroot -d "' + host.hostname + '"')
.then(result => {
logger.info(result);
return result;
});
},
/**
* @param {String} host_type
* @param {Object} host
* @returns {Promise}
*/
renewSsl: (host_type, host) => {
logger.info('Renewing SSL certificates for ' + host_type + ' #' + host.id);
// TODO
return utils.exec('/usr/bin/certbot renew --force-renewal --disable-hook-validation --cert-name "' + host.hostname + '"')
.then(result => {
logger.info(result);
return result;
});
},
/**
* @param {String} host_type
* @param {Object} host
* @returns {Promise}
*/
deleteCerts: (host_type, host) => {
logger.info('Deleting SSL certificates for ' + host_type + ' #' + host.id);
// TODO
return utils.exec('/usr/bin/certbot delete -n --cert-name "' + host.hostname + '"')
.then(result => {
logger.info(result);
})
.catch(err => {
logger.error(err);
});
},
/**
* @param {String} host_type
* @param {Object} host
* @returns {Promise}
*/
generateSslSetupConfig: (host_type, host) => {
host_type = host_type.replace(new RegExp('-', 'g'), '_');
let renderEngine = Liquid();
let template = null;
let filename = internalNginx.getConfigName(host_type, host);
return new Promise((resolve, reject) => {
try {
template = fs.readFileSync(__dirname + '/../templates/letsencrypt.conf', {encoding: 'utf8'});
} catch (err) {
reject(new error.ConfigurationError(err.message));
return;
}
return renderEngine
.parseAndRender(template, host)
.then(config_text => {
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
return template_data;
})
.catch(err => {
throw new error.ConfigurationError(err.message);
});
});
},
/**
* @param {String} host_type
* @param {Object} host
* @returns {Promise}
*/
configureSsl: (host_type, host) => {
// TODO
return internalSsl.generateSslSetupConfig(host)
.then(data => {
return internalNginx.reload()
.then(() => {
return internalSsl.requestSsl(data);
});
});
}
};
module.exports = internalSsl;