diff --git a/src/blobs.js b/src/blobs.js index ace3c84e0..c16b26890 100644 --- a/src/blobs.js +++ b/src/blobs.js @@ -7,7 +7,8 @@ exports = module.exports = { set, del, - initSecrets, + generateSecrets, + restoreSecrets, ACME_ACCOUNT_KEY: 'acme_account_key', ADDON_TURN_SECRET: 'addon_turn_secret', @@ -22,7 +23,6 @@ exports = module.exports = { const assert = require('assert'), BoxError = require('./boxerror.js'), - constants = require('./constants.js'), crypto = require('crypto'), database = require('./database.js'), debug = require('debug')('box:blobs'), @@ -54,51 +54,40 @@ async function clear() { await database.query('DELETE FROM blobs'); } -async function initSecrets() { - let acmeAccountKey = await get(exports.ACME_ACCOUNT_KEY); - if (!acmeAccountKey) { - acmeAccountKey = safe.child_process.execSync('openssl genrsa 4096'); - if (!acmeAccountKey) throw new BoxError(BoxError.OPENSSL_ERROR, `Could not generate acme account key: ${safe.error.message}`); - await set(exports.ACME_ACCOUNT_KEY, acmeAccountKey); - } +async function generateSecrets() { + const acmeAccountKey = safe.child_process.execSync('openssl genrsa 4096'); + if (!acmeAccountKey) throw new BoxError(BoxError.OPENSSL_ERROR, `Could not generate acme account key: ${safe.error.message}`); + await set(exports.ACME_ACCOUNT_KEY, acmeAccountKey); - let turnSecret = await get(exports.ADDON_TURN_SECRET); - if (!turnSecret) { - turnSecret = 'a' + crypto.randomBytes(15).toString('hex'); // prefix with a to ensure string starts with a letter - await set(exports.ADDON_TURN_SECRET, Buffer.from(turnSecret)); - } + const turnSecret = 'a' + crypto.randomBytes(15).toString('hex'); // prefix with a to ensure string starts with a letter + await set(exports.ADDON_TURN_SECRET, Buffer.from(turnSecret)); - // TODO maybe skip this in tests if possible again - let dhparams = await get(exports.DHPARAMS); - if (!dhparams) { - debug('initSecrets: generating dhparams.pem'); - if (constants.TEST) dhparams = safe.fs.readFileSync('/tmp/dhparams.pem'); - // https://security.stackexchange.com/questions/95178/diffie-hellman-parameters-still-calculating-after-24-hours - if (!dhparams) dhparams = safe.child_process.execSync('openssl dhparam -dsaparam 2048'); - if (!dhparams) throw new BoxError(BoxError.OPENSSL_ERROR, safe.error); - if (constants.TEST) safe.fs.writeFileSync('/tmp/dhparams.pem', dhparams); - if (!safe.fs.writeFileSync(paths.DHPARAMS_FILE, dhparams)) throw new BoxError(BoxError.FS_ERROR, `Could not save dhparams.pem: ${safe.error.message}`); - await set(exports.DHPARAMS, dhparams); - } else if (!safe.fs.existsSync(paths.DHPARAMS_FILE)) { - if (!safe.fs.writeFileSync(paths.DHPARAMS_FILE, dhparams)) throw new BoxError(BoxError.FS_ERROR, `Could not save dhparams.pem: ${safe.error.message}`); - } + debug('generateSecrets: generating dhparams.pem'); + // https://security.stackexchange.com/questions/95178/diffie-hellman-parameters-still-calculating-after-24-hours + const dhparams = safe.child_process.execSync('openssl dhparam -dsaparam 2048'); + if (!dhparams) throw new BoxError(BoxError.OPENSSL_ERROR, safe.error); + if (!safe.fs.writeFileSync(paths.DHPARAMS_FILE, dhparams)) throw new BoxError(BoxError.FS_ERROR, `Could not save dhparams.pem: ${safe.error.message}`); + await set(exports.DHPARAMS, dhparams); - let sftpPrivateKey = await get(exports.SFTP_PRIVATE_KEY); - let sftpPublicKey = await get(exports.SFTP_PUBLIC_KEY); - - if (!sftpPrivateKey || !sftpPublicKey) { - debug('initSecrets: generate sftp keys'); - if (constants.TEST) { - safe.fs.unlinkSync(paths.SFTP_PUBLIC_KEY_FILE); - safe.fs.unlinkSync(paths.SFTP_PRIVATE_KEY_FILE); - } - if (!safe.child_process.execSync(`ssh-keygen -m PEM -t rsa -f "${paths.SFTP_KEYS_DIR}/ssh_host_rsa_key" -q -N ""`)) throw new BoxError(BoxError.OPENSSL_ERROR, `Could not generate sftp ssh keys: ${safe.error.message}`); - sftpPublicKey = safe.fs.readFileSync(paths.SFTP_PUBLIC_KEY_FILE); - await set(exports.SFTP_PUBLIC_KEY, sftpPublicKey); - sftpPrivateKey = safe.fs.readFileSync(paths.SFTP_PRIVATE_KEY_FILE); - await set(exports.SFTP_PRIVATE_KEY, sftpPrivateKey); - } else if (!safe.fs.existsSync(paths.SFTP_PUBLIC_KEY_FILE) || !safe.fs.existsSync(paths.SFTP_PRIVATE_KEY_FILE)) { - if (!safe.fs.writeFileSync(paths.SFTP_PUBLIC_KEY_FILE, sftpPublicKey)) throw new BoxError(BoxError.FS_ERROR, `Could not save sftp public key: ${safe.error.message}`); - if (!safe.fs.writeFileSync(paths.SFTP_PRIVATE_KEY_FILE, sftpPrivateKey)) throw new BoxError(BoxError.FS_ERROR, `Could not save sftp private key: ${safe.error.message}`); - } + debug('generateSecrets: generate sftp keys'); + if (!safe.child_process.execSync(`ssh-keygen -m PEM -t rsa -f "${paths.SFTP_KEYS_DIR}/ssh_host_rsa_key" -q -N ""`)) throw new BoxError(BoxError.OPENSSL_ERROR, `Could not generate sftp ssh keys: ${safe.error.message}`); + const sftpPublicKey = safe.fs.readFileSync(paths.SFTP_PUBLIC_KEY_FILE); + await set(exports.SFTP_PUBLIC_KEY, sftpPublicKey); + const sftpPrivateKey = safe.fs.readFileSync(paths.SFTP_PRIVATE_KEY_FILE); + await set(exports.SFTP_PRIVATE_KEY, sftpPrivateKey); + if (!safe.fs.writeFileSync(paths.SFTP_PUBLIC_KEY_FILE, sftpPublicKey)) throw new BoxError(BoxError.FS_ERROR, `Could not save sftp public key: ${safe.error.message}`); + if (!safe.fs.writeFileSync(paths.SFTP_PRIVATE_KEY_FILE, sftpPrivateKey)) throw new BoxError(BoxError.FS_ERROR, `Could not save sftp private key: ${safe.error.message}`); +} + +async function restoreSecrets() { + const dhparams = await get(exports.DHPARAMS); + if (!dhparams) throw new BoxError(BoxError.NOT_FOUND, 'dhparams not found'); + if (!safe.fs.writeFileSync(paths.DHPARAMS_FILE, dhparams)) throw new BoxError(BoxError.FS_ERROR, `Could not save dhparams.pem: ${safe.error.message}`); + + const sftpPrivateKey = await get(exports.SFTP_PRIVATE_KEY); + const sftpPublicKey = await get(exports.SFTP_PUBLIC_KEY); + + if (!sftpPrivateKey || !sftpPublicKey) throw new BoxError(BoxError.NOT_FOUND, 'SFTP keys not found'); + if (!safe.fs.writeFileSync(paths.SFTP_PUBLIC_KEY_FILE, sftpPublicKey)) throw new BoxError(BoxError.FS_ERROR, `Could not save sftp public key: ${safe.error.message}`); + if (!safe.fs.writeFileSync(paths.SFTP_PRIVATE_KEY_FILE, sftpPrivateKey)) throw new BoxError(BoxError.FS_ERROR, `Could not save sftp private key: ${safe.error.message}`); } diff --git a/src/provision.js b/src/provision.js index 9a15a941e..3db191f02 100644 --- a/src/provision.js +++ b/src/provision.js @@ -62,7 +62,7 @@ async function setupTask(domain, auditSource) { assert.strictEqual(typeof auditSource, 'object'); try { - await blobs.initSecrets(); + await blobs.generateSecrets(); await cloudron.setupDnsAndCert(constants.DASHBOARD_LOCATION, domain, auditSource, (progress) => setProgress('setup', progress.message)); await cloudron.setDashboardDomain(domain, auditSource); setProgress('setup', 'Done'), @@ -154,6 +154,7 @@ async function restoreTask(backupConfig, backupId, sysinfoConfig, options, audit try { setProgress('restore', 'Downloading box backup'); await backuptask.restore(backupConfig, backupId, (progress) => setProgress('restore', progress.message)); + await blobs.restoreSecrets(); setProgress('restore', 'Downloading mail backup'); const mailBackups = await backups.getByIdentifierAndStatePaged(backups.BACKUP_IDENTIFIER_MAIL, backups.BACKUP_STATE_NORMAL, 1, 1);