diff --git a/src/blobs.js b/src/blobs.js index 58c2d3520..ed1874acf 100644 --- a/src/blobs.js +++ b/src/blobs.js @@ -5,6 +5,7 @@ exports = module.exports = { get, set, + del, initSecrets, @@ -45,6 +46,10 @@ async function set(id, value) { await database.query('INSERT INTO blobs (id, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value=VALUES(value)', [ id, value ]); } +async function del(id) { + await database.query('DELETE FROM blobs WHERE id=?', [ id ]); +} + async function clear() { await database.query('DELETE FROM blobs'); } diff --git a/src/cloudron.js b/src/cloudron.js index 4271a60c7..07e33d431 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -367,7 +367,7 @@ function renewCerts(options, auditSource, callback) { assert.strictEqual(typeof auditSource, 'object'); assert.strictEqual(typeof callback, 'function'); - tasks.add(tasks.TASK_RENEW_CERTS, [ options, auditSource ], function (error, taskId) { + tasks.add(tasks.TASK_CHECK_CERTS, [ options, auditSource ], function (error, taskId) { if (error) return callback(error); tasks.startTask(taskId, {}, NOOP_CALLBACK); diff --git a/src/cron.js b/src/cron.js index 5a1fd2eb0..bdf9bb5f6 100644 --- a/src/cron.js +++ b/src/cron.js @@ -16,7 +16,7 @@ exports = module.exports = { DEFAULT_AUTOUPDATE_PATTERN, }; -var appHealthMonitor = require('./apphealthmonitor.js'), +const appHealthMonitor = require('./apphealthmonitor.js'), apps = require('./apps.js'), assert = require('assert'), async = require('async'), diff --git a/src/reverseproxy.js b/src/reverseproxy.js index b726b8764..e5fcd8d1f 100644 --- a/src/reverseproxy.js +++ b/src/reverseproxy.js @@ -11,7 +11,7 @@ exports = module.exports = { getCertificatePath, ensureCertificate, - renewCerts, + checkCerts, // the 'configure' ensure a certificate and generate nginx config configureApp, @@ -102,7 +102,7 @@ function isExpiringSync(certFilePath, hours) { if (!fs.existsSync(certFilePath)) return 2; // not found - var result = safe.child_process.spawnSync('/usr/bin/openssl', [ 'x509', '-checkend', String(60 * 60 * hours), '-in', certFilePath ]); + const result = safe.child_process.spawnSync('/usr/bin/openssl', [ 'x509', '-checkend', String(60 * 60 * hours), '-in', certFilePath ]); if (!result) return 3; // some error @@ -746,6 +746,39 @@ function renewCerts(options, auditSource, progressCallback, callback) { }); } +async function cleanupCerts() { + const filenames = await fs.promises.readdir(paths.NGINX_CERT_DIR); + const certFilenames = filenames.filter(f => f.endsWith('.cert')); + + for (const certFilename of certFilenames) { + const certFilePath = path.join(paths.NGINX_CERT_DIR, certFilename); + if (isExpiringSync(certFilePath, - 24 * 30 * 6)) { // expired 6 months ago + const fqdn = certFilename.replace(/\.cert$/, ''); + debug(`cleanupCerts: deleting certs of ${fqdn}`); + + safe.fs.unlinkSync(certFilePath); + safe.fs.unlinkSync(path.join(paths.NGINX_CERT_DIR, `${fqdn}.key`)); + safe.fs.unlinkSync(path.join(paths.NGINX_CERT_DIR, `${fqdn}.csr`)); + + await blobs.del(`${blobs.CERT_PREFIX}-${fqdn}.key`); + await blobs.del(`${blobs.CERT_PREFIX}-${fqdn}.cert`); + await blobs.del(`${blobs.CERT_PREFIX}-${fqdn}.csr`); + } + } +} + +function checkCerts(options, auditSource, progressCallback, callback) { + assert.strictEqual(typeof options, 'object'); + assert.strictEqual(typeof auditSource, 'object'); + assert.strictEqual(typeof progressCallback, 'function'); + assert.strictEqual(typeof callback, 'function'); + + async.series([ + renewCerts.bind(null, options, auditSource, progressCallback), + cleanupCerts + ], callback); +} + function removeAppConfigs() { for (let appConfigFile of fs.readdirSync(paths.NGINX_APPCONFIG_DIR)) { if (appConfigFile !== constants.NGINX_DEFAULT_CONFIG_FILE_NAME && !appConfigFile.startsWith(constants.DASHBOARD_LOCATION)) { diff --git a/src/tasks.js b/src/tasks.js index 4497c44c9..66f43b973 100644 --- a/src/tasks.js +++ b/src/tasks.js @@ -20,7 +20,7 @@ exports = module.exports = { TASK_APP: 'app', TASK_BACKUP: 'backup', TASK_UPDATE: 'update', - TASK_RENEW_CERTS: 'renewcerts', + TASK_CHECK_CERTS: 'checkCerts', TASK_SETUP_DNS_AND_CERT: 'setupDnsAndCert', TASK_CLEAN_BACKUPS: 'cleanBackups', TASK_SYNC_EXTERNAL_LDAP: 'syncExternalLdap', @@ -39,7 +39,7 @@ exports = module.exports = { _TASK_SLEEP: '_sleep' }; -let assert = require('assert'), +const assert = require('assert'), BoxError = require('./boxerror.js'), debug = require('debug')('box:tasks'), path = require('path'), diff --git a/src/taskworker.js b/src/taskworker.js index 318651430..eaf99aab8 100755 --- a/src/taskworker.js +++ b/src/taskworker.js @@ -2,7 +2,7 @@ 'use strict'; -var apptask = require('./apptask.js'), +const apptask = require('./apptask.js'), async = require('async'), backups = require('./backups.js'), cloudron = require('./cloudron.js'), @@ -20,7 +20,7 @@ const TASKS = { // indexed by task type app: apptask.run, backup: backups.backupBoxAndApps, update: updater.update, - renewcerts: reverseProxy.renewCerts, + checkCerts: reverseProxy.checkCerts, setupDnsAndCert: cloudron.setupDnsAndCert, cleanBackups: backups.cleanup, syncExternalLdap: externalLdap.sync,