diff --git a/src/reverseproxy.js b/src/reverseproxy.js index 09d2ab7bd..02bc647fc 100644 --- a/src/reverseproxy.js +++ b/src/reverseproxy.js @@ -11,6 +11,7 @@ exports = module.exports = { getCertificate: getCertificate, renewAll: renewAll, + renewCerts: renewCerts, configureDefaultServer: configureDefaultServer, @@ -420,12 +421,11 @@ function unconfigureApp(app, callback) { }); } -function renewAll(auditSource, callback) { +function renewCerts(options, auditSource, callback) { + assert.strictEqual(typeof options, 'object'); assert.strictEqual(typeof auditSource, 'object'); assert.strictEqual(typeof callback, 'function'); - debug('renewAll: Checking certificates for renewal'); - apps.getAll(function (error, allApps) { if (error) return callback(error); @@ -444,6 +444,8 @@ function renewAll(auditSource, callback) { }); }); + if (options.domain) appDomains = appDomains.filter(function (appDomain) { return appDomain.domain === options.domain; }); + async.eachSeries(appDomains, function (appDomain, iteratorCallback) { ensureCertificate(appDomain.fqdn, appDomain.domain, auditSource, function (error, bundle) { if (error) return iteratorCallback(error); // this can happen if cloudron is not setup yet @@ -471,6 +473,15 @@ function renewAll(auditSource, callback) { }); } +function renewAll(auditSource, callback) { + assert.strictEqual(typeof auditSource, 'object'); + assert.strictEqual(typeof callback, 'function'); + + debug('renewAll: Checking certificates for renewal'); + + renewCerts({}, auditSource, callback); +} + function removeAppConfigs() { for (var appConfigFile of fs.readdirSync(paths.NGINX_APPCONFIG_DIR)) { fs.unlinkSync(path.join(paths.NGINX_APPCONFIG_DIR, appConfigFile)); diff --git a/src/routes/domains.js b/src/routes/domains.js index c63c75d1c..8ddd99602 100644 --- a/src/routes/domains.js +++ b/src/routes/domains.js @@ -7,6 +7,8 @@ exports = module.exports = { update: update, del: del, + renewCerts: renewCerts, + verifyDomainLock: verifyDomainLock }; @@ -14,7 +16,13 @@ var assert = require('assert'), domains = require('../domains.js'), DomainsError = domains.DomainsError, HttpError = require('connect-lastmile').HttpError, - HttpSuccess = require('connect-lastmile').HttpSuccess; + HttpSuccess = require('connect-lastmile').HttpSuccess, + reverseProxy = require('../reverseproxy.js'); + +function auditSource(req) { + var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress || null; + return { ip: ip, username: req.user ? req.user.username : null, userId: req.user ? req.user.id : null }; +} function verifyDomainLock(req, res, next) { assert.strictEqual(typeof req.params.domain, 'string'); @@ -122,3 +130,12 @@ function del(req, res, next) { next(new HttpSuccess(204)); }); } + +function renewCerts(req, res, next) { + assert.strictEqual(typeof req.params.domain, 'string'); + + // trigger renewal in the background + reverseProxy.renewCerts({ domain: req.params.domain }, auditSource(req), function () { }); + + next(new HttpSuccess(202, {})); +} diff --git a/src/server.js b/src/server.js index 028539213..238c6e044 100644 --- a/src/server.js +++ b/src/server.js @@ -277,6 +277,7 @@ function initializeExpressSync() { router.get ('/api/v1/domains', domainsReadScope, routes.domains.getAll); router.get ('/api/v1/domains/:domain', domainsManageScope, verifyDomainLock, routes.domains.get); // this is manage scope because it returns non-restricted fields router.put ('/api/v1/domains/:domain', domainsManageScope, verifyDomainLock, routes.domains.update); + router.post ('/api/v1/domains/:domain/renew_certs', domainsManageScope, verifyDomainLock, routes.domains.renewCerts); router.del ('/api/v1/domains/:domain', domainsManageScope, verifyDomainLock, routes.users.verifyPassword, routes.domains.del); // caas routes