diff --git a/src/routes/settings.js b/src/routes/settings.js index 87ef49851..3320c0898 100644 --- a/src/routes/settings.js +++ b/src/routes/settings.js @@ -15,7 +15,8 @@ exports = module.exports = { getDnsConfig: getDnsConfig, setDnsConfig: setDnsConfig, - setCertificate: setCertificate + setCertificate: setCertificate, + setAdminCertificate: setAdminCertificate }; var assert = require('assert'), @@ -112,6 +113,7 @@ function setDnsConfig(req, res, next) { }); } +// default fallback cert function setCertificate(req, res, next) { assert.strictEqual(typeof req.body, 'object'); @@ -119,7 +121,22 @@ function setCertificate(req, res, next) { if (!req.body.key || typeof req.body.key !== 'string') return next(new HttpError(400, 'key must be a string')); settings.setCertificate(req.body.cert, req.body.key, function (error) { - if (error && error.reason === SettingsError.INVALID_CERT) return next(new HttpError(400, 'cert not applicable')) + if (error && error.reason === SettingsError.INVALID_CERT) return next(new HttpError(400, 'cert not applicable')); + if (error) return next(new HttpError(500, error)); + + next(new HttpSuccess(202, {})); + }); +} + +// only webadmin cert, until it can be treated just like a normal app +function setAdminCertificate(req, res, next) { + assert.strictEqual(typeof req.body, 'object'); + + if (!req.body.cert || typeof req.body.cert !== 'string') return next(new HttpError(400, 'cert must be a string')); + if (!req.body.key || typeof req.body.key !== 'string') return next(new HttpError(400, 'key must be a string')); + + settings.setAdminCertificate(req.body.cert, req.body.key, function (error) { + if (error && error.reason === SettingsError.INVALID_CERT) return next(new HttpError(400, 'cert not applicable')); if (error) return next(new HttpError(500, error)); next(new HttpSuccess(202, {})); diff --git a/src/server.js b/src/server.js index 40a8f5f8a..7aa2a0207 100644 --- a/src/server.js +++ b/src/server.js @@ -163,6 +163,7 @@ function initializeExpressSync() { router.get ('/api/v1/settings/dns_config', settingsScope, routes.settings.getDnsConfig); router.post('/api/v1/settings/dns_config', settingsScope, routes.settings.setDnsConfig); router.post('/api/v1/settings/certificate', settingsScope, routes.settings.setCertificate); + router.post('/api/v1/settings/admin_certificate', settingsScope, routes.settings.setAdminCertificate); // backup routes router.get ('/api/v1/backups', settingsScope, routes.backups.get); diff --git a/src/settings.js b/src/settings.js index a0bbb22f5..3cf13724c 100644 --- a/src/settings.js +++ b/src/settings.js @@ -28,6 +28,7 @@ exports = module.exports = { validateCertificate: validateCertificate, setCertificate: setCertificate, + setAdminCertificate: setAdminCertificate, AUTOUPDATE_PATTERN_KEY: 'autoupdate_pattern', TIME_ZONE_KEY: 'time_zone', @@ -40,8 +41,11 @@ exports = module.exports = { var assert = require('assert'), config = require('./config.js'), + constants = require('./constants.js'), CronJob = require('cron').CronJob, DatabaseError = require('./databaseerror.js'), + ejs = require('ejs'), + fs = require('fs'), path = require('path'), paths = require('./paths.js'), safe = require('safetydance'), @@ -62,7 +66,8 @@ var gDefaults = (function () { return result; })(); -var RELOAD_NGINX_CMD = path.join(__dirname, 'scripts/reloadnginx.sh'); +var NGINX_APPCONFIG_EJS = fs.readFileSync(__dirname + '/../setup/start/nginx/appconfig.ejs', { encoding: 'utf8' }), + RELOAD_NGINX_CMD = path.join(__dirname, 'scripts/reloadnginx.sh'); if (config.TEST) { // avoid noisy warnings during npm test @@ -334,3 +339,40 @@ function setCertificate(cert, key, callback) { return callback(null); }); } + +function setAdminCertificate(cert, key, callback) { + assert.strictEqual(typeof cert, 'string'); + assert.strictEqual(typeof key, 'string'); + assert.strictEqual(typeof callback, 'function'); + + var sourceDir = path.resolve(__dirname, '..'); + var endpoint = 'admin'; + var vhost = config.appFqdn(constants.ADMIN_LOCATION); + var certFilePath = path.join(paths.APP_CERTS_DIR, 'admin.cert'); + var keyFilePath = path.join(paths.APP_CERTS_DIR, 'admin.key'); + + var error = validateCertificate(cert, key, vhost); + if (error) return callback(new SettingsError(SettingsError.INVALID_CERT, error.message)); + + if (!safe.fs.writeFileSync(certFilePath, cert)) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, safe.error.message)); + if (!safe.fs.writeFileSync(keyFilePath, key)) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, safe.error.message)); + + var data = { + sourceDir: sourceDir, + adminOrigin: config.adminOrigin(), + vhost: vhost, + endpoint: endpoint, + certFilePath: certFilePath, + keyFilePath: keyFilePath + }; + var nginxConf = ejs.render(NGINX_APPCONFIG_EJS, data); + var nginxConfigFilename = path.join(paths.NGINX_APPCONFIG_DIR, 'admin.conf'); + + if (!safe.fs.writeFileSync(nginxConfigFilename, nginxConf)) return callback(safe.error); + + shell.sudo('setAdminCertificate', [ RELOAD_NGINX_CMD ], function (error) { + if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error)); + + return callback(null); + }); +}