From ab7448926f8a22bd2dbab0dee2bf1b5d6a7cd18e Mon Sep 17 00:00:00 2001 From: Girish Ramakrishnan Date: Wed, 31 Jan 2018 18:20:29 -0800 Subject: [PATCH] Fix use of fallback certs We used to always use nginx cert dir. When custom fallback certs were set, we used to copy it in boxdata cert dir and then nginx cert dir. The issue is then that we have to copy all certs to nginx cert dir on cloudron restore. To fix this, we simply give priority to nginx cert dir and not copy around certs anymore. caas cert will reside in nginx cert dir and not get backed up, as expected. --- src/domains.js | 6 +++--- src/mail.js | 9 ++++++--- src/reverseproxy.js | 35 +++++++++++++++-------------------- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/domains.js b/src/domains.js index 950109ca1..4ce30b250 100644 --- a/src/domains.js +++ b/src/domains.js @@ -158,11 +158,11 @@ function get(domain, callback) { if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new DomainError(DomainError.NOT_FOUND)); if (error) return callback(new DomainError(DomainError.INTERNAL_ERROR, error)); - reverseProxy.getFallbackCertificate(domain, function (error, certFilePath, keyFilePath) { + reverseProxy.getFallbackCertificate(domain, function (error, bundle) { if (error && error.reason !== ReverseProxyError.NOT_FOUND) return callback(new DomainError(DomainError.INTERNAL_ERROR, error)); - var cert = safe.fs.readFileSync(certFilePath, 'utf-8'); - var key = safe.fs.readFileSync(keyFilePath, 'utf-8'); + var cert = safe.fs.readFileSync(bundle.certFilePath, 'utf-8'); + var key = safe.fs.readFileSync(bundle.keyFilePath, 'utf-8'); if (!cert || !key) return callback(new DomainError(DomainError.INTERNAL_ERROR, error)); diff --git a/src/mail.js b/src/mail.js index dd91e2f5b..cfa322c70 100644 --- a/src/mail.js +++ b/src/mail.js @@ -524,12 +524,15 @@ function restartMail(callback) { const memoryLimit = Math.max((1 + Math.round(os.totalmem()/(1024*1024*1024)/4)) * 128, 256); // admin and mail share the same certificate - reverseProxy.getCertificate({ intrinsicFqdn: config.adminFqdn(), domain: config.adminDomain() }, function (error, cert, key) { + reverseProxy.getCertificate({ intrinsicFqdn: config.adminFqdn(), domain: config.adminDomain() }, function (error, bundle) { if (error) return callback(error); // the setup script copies dhparams.pem to /addons/mail - if (!safe.fs.writeFileSync(paths.ADDON_CONFIG_DIR + '/mail/tls_cert.pem', cert)) return callback(new Error('Could not create cert file:' + safe.error.message)); - if (!safe.fs.writeFileSync(paths.ADDON_CONFIG_DIR + '/mail/tls_key.pem', key)) return callback(new Error('Could not create key file:' + safe.error.message)); + const mailCertFilePath = path.join(paths.ADDON_CONFIG_DIR, 'mail/tls_cert.pem'); + const mailKeyFilePath = path.join(paths.ADDON_CONFIG_DIR, 'mail/tls_cert.pem'); + + if (!safe.child_process.execSync(`cp ${bundle.certFilePath} ${mailCertFilePath}`)) return callback(new Error('Could not create cert file:' + safe.error.message)); + if (!safe.child_process.execSync(`cp ${bundle.keyFilePath} ${mailKeyFilePath}`)) return callback(new Error('Could not create key file:' + safe.error.message)); shell.execSync('startMail', 'docker rm -f mail || true'); diff --git a/src/reverseproxy.js b/src/reverseproxy.js index 00644d7ae..c8edd6019 100644 --- a/src/reverseproxy.js +++ b/src/reverseproxy.js @@ -172,8 +172,6 @@ function reload(callback) { shell.sudo('reload', [ RELOAD_NGINX_CMD ], callback); } -// We configure nginx to always use the fallback cert from the runtime directory (NGINX_CERT_DIR) -// This is done because Caas wildcard certs should not be part of the backup function setFallbackCertificate(domain, fallback, callback) { assert.strictEqual(typeof domain, 'string'); assert.strictEqual(typeof fallback, 'object'); @@ -191,13 +189,6 @@ function setFallbackCertificate(domain, fallback, callback) { if (!safe.child_process.execSync(certCommand)) return callback(new ReverseProxyError(ReverseProxyError.INTERNAL_ERROR, safe.error.message)); } - // copy over fallback cert - var fallbackCertFilePath = path.join(paths.NGINX_CERT_DIR, `${domain}.host.cert`); - var fallbackKeyFilePath = path.join(paths.NGINX_CERT_DIR, `${domain}.host.key`); - - if (!safe.child_process.execSync(`cp ${certFilePath} ${fallbackCertFilePath}`)) return callback(new ReverseProxyError(ReverseProxyError.INTERNAL_ERROR, safe.error.message)); - if (!safe.child_process.execSync(`cp ${keyFilePath} ${fallbackKeyFilePath}`)) return callback(new ReverseProxyError(ReverseProxyError.INTERNAL_ERROR, safe.error.message)); - platform.handleCertChanged('*.' + domain); reload(function (error) { @@ -211,7 +202,17 @@ function getFallbackCertificate(domain, callback) { assert.strictEqual(typeof domain, 'string'); assert.strictEqual(typeof callback, 'function'); - callback(null, path.join(paths.NGINX_CERT_DIR, `${domain}.host.cert`), path.join(paths.NGINX_CERT_DIR, `${domain}.host.key`)); + // check for any pre-provisioned (caas) certs. they get first priority + var certFilePath = path.join(paths.NGINX_CERT_DIR, `${domain}.host.cert`); + var keyFilePath = path.join(paths.NGINX_CERT_DIR, `${domain}.host.key`); + + if (fs.existsSync(certFilePath) && fs.existsSync(keyFilePath)) return callback(null, { certFilePath, keyFilePath }); + + // check for auto-generated or user set fallback certs + certFilePath = path.join(paths.APP_CERTS_DIR, `${domain}.host.cert`); + keyFilePath = path.join(paths.APP_CERTS_DIR, `${domain}.host.key`); + + callback(null, { certFilePath, keyFilePath }); } function getCertificate(app, callback) { @@ -223,15 +224,14 @@ function getCertificate(app, callback) { var certFilePath = path.join(paths.APP_CERTS_DIR, `${vhost}.user.cert`); var keyFilePath = path.join(paths.APP_CERTS_DIR, `${vhost}.user.key`); - if (fs.existsSync(certFilePath) && fs.existsSync(keyFilePath)) return callback(null, certFilePath, keyFilePath); + if (fs.existsSync(certFilePath) && fs.existsSync(keyFilePath)) return callback(null, { certFilePath, keyFilePath }); certFilePath = path.join(paths.APP_CERTS_DIR, `${vhost}.cert`); keyFilePath = path.join(paths.APP_CERTS_DIR, `${vhost}.key`); - if (fs.existsSync(certFilePath) && fs.existsSync(keyFilePath)) return callback(null, certFilePath, keyFilePath); + if (fs.existsSync(certFilePath) && fs.existsSync(keyFilePath)) return callback(null, { certFilePath, keyFilePath }); - // any user fallback cert is always copied over to nginx cert dir - callback(null, path.join(paths.NGINX_CERT_DIR, `${app.domain}.host.cert`), path.join(paths.NGINX_CERT_DIR, `${app.domain}.host.key`)); + return getFallbackCertificate(app.domain, callback); } function ensureCertificate(app, auditSource, callback) { @@ -276,12 +276,7 @@ function ensureCertificate(app, auditSource, callback) { eventlog.add(eventlog.ACTION_CERTIFICATE_RENEWAL, auditSource, { domain: vhost, errorMessage: errorMessage }); // if no cert was returned use fallback. the fallback/caas provider will not provide any for example - if (!certFilePath || !keyFilePath) { - certFilePath = path.join(paths.NGINX_CERT_DIR, `${app.domain}.host.cert`); - keyFilePath = path.join(paths.NGINX_CERT_DIR, `${app.domain}.host.key`); - - return callback(null, { certFilePath, keyFilePath, reason: 'fallback' }); - } + if (!certFilePath || !keyFilePath) return getFallbackCertificate(app.domain, callback); callback(null, { certFilePath, keyFilePath, reason: 'new-le' }); });