diff --git a/migrations/20230309095335-blobs-rename-sftp-key-names.js b/migrations/20230309095335-blobs-rename-sftp-key-names.js new file mode 100644 index 000000000..97bef158d --- /dev/null +++ b/migrations/20230309095335-blobs-rename-sftp-key-names.js @@ -0,0 +1,9 @@ +'use strict'; + +exports.up = async function (db) { + await db.runSql('UPDATE blobs SET id = ? WHERE id = ?', [ 'sftp_rsa_private_key', 'sftp_private_key' ]); + await db.runSql('UPDATE blobs SET id = ? WHERE id = ?', [ 'sftp_rsa_public_key', 'sftp_public_key' ]); +}; + +exports.down = async function () { +}; diff --git a/src/blobs.js b/src/blobs.js index 1152e6f45..2e1550dba 100644 --- a/src/blobs.js +++ b/src/blobs.js @@ -13,8 +13,13 @@ exports = module.exports = { ACME_ACCOUNT_KEY: 'acme_account_key', ADDON_TURN_SECRET: 'addon_turn_secret', - SFTP_RSA_PUBLIC_KEY: 'sftp_public_key', - SFTP_RSA_PRIVATE_KEY: 'sftp_private_key', + + // the code relies on sftp__* pattern + SFTP_RSA_PUBLIC_KEY: 'sftp_rsa_public_key', + SFTP_RSA_PRIVATE_KEY: 'sftp_rsa_private_key', + SFTP_ED25519_PUBLIC_KEY: 'sftp_ed25519_public_key', + SFTP_ED25519_PRIVATE_KEY: 'sftp_ed25519_private_key', + PROXY_AUTH_TOKEN_SECRET: 'proxy_auth_token_secret', CERT_PREFIX: 'cert', diff --git a/src/infra_version.js b/src/infra_version.js index d5e98b4c1..5157e8579 100644 --- a/src/infra_version.js +++ b/src/infra_version.js @@ -22,6 +22,6 @@ exports = module.exports = { 'redis': { repo: 'cloudron/redis', tag: 'cloudron/redis:3.4.0@sha256:19680fcf9b36720468674e85b2d9ad085da759dc08811ee547474c32ce70bf99' }, 'mail': { repo: 'cloudron/mail', tag: 'cloudron/mail:3.8.3@sha256:877a1afb99e8cae8c82d5a2fca77840425eb7fafc24360fdd1c9c299e41bcfeb' }, 'graphite': { repo: 'cloudron/graphite', tag: 'cloudron/graphite:3.3.0@sha256:005addac7e7576f3960b562404ce59442bc861626af0ae0f5122484f5bfcbbc1' }, - 'sftp': { repo: 'cloudron/sftp', tag: 'cloudron/sftp:3.7.0@sha256:4f8968a55b949bbe34ddd0a83cfc5f84235bf91a41d834e5e852246f280ea5e8' } + 'sftp': { repo: 'cloudron/sftp', tag: 'cloudron/sftp:3.7.1@sha256:e2eb96516379d07548ac5a758a1f57a54772493174de3096705397b34e42de1a' } } }; diff --git a/src/paths.js b/src/paths.js index 00c09eaba..eaba4da71 100644 --- a/src/paths.js +++ b/src/paths.js @@ -47,8 +47,6 @@ exports = module.exports = { CIFS_CREDENTIALS_DIR: path.join(baseDir(), 'platformdata/cifs'), SSHFS_KEYS_DIR: path.join(baseDir(), 'platformdata/sshfs'), SFTP_KEYS_DIR: path.join(baseDir(), 'platformdata/sftp/ssh'), - SFTP_RSA_PUBLIC_KEY_FILE: path.join(baseDir(), 'platformdata/sftp/ssh/ssh_host_rsa_key.pub'), - SFTP_RSA_PRIVATE_KEY_FILE: path.join(baseDir(), 'platformdata/sftp/ssh/ssh_host_rsa_key'), FIREWALL_BLOCKLIST_FILE: path.join(baseDir(), 'platformdata/firewall/blocklist.txt'), LDAP_ALLOWLIST_FILE: path.join(baseDir(), 'platformdata/firewall/ldap_allowlist.txt'), REVERSE_PROXY_REBUILD_FILE: path.join(baseDir(), 'platformdata/nginx/rebuild-needed'), diff --git a/src/sftp.js b/src/sftp.js index 7f10ffa84..ca22eae87 100644 --- a/src/sftp.js +++ b/src/sftp.js @@ -15,6 +15,7 @@ const apps = require('./apps.js'), docker = require('./docker.js'), hat = require('./hat.js'), infra = require('./infra_version.js'), + path = require('path'), paths = require('./paths.js'), safe = require('safetydance'), settings = require('./settings.js'), @@ -24,19 +25,23 @@ const apps = require('./apps.js'), volumes = require('./volumes.js'); async function ensureKeys() { - const sftpRsaPrivateKey = await blobs.get(blobs.SFTP_RSA_PRIVATE_KEY); - const sftpRsaPublicKey = await blobs.get(blobs.SFTP_RSA_PUBLIC_KEY); + for (const keyType of [ 'rsa', 'ed25519' ]) { + const privateKey = await blobs.get(`sftp_${keyType}_private_key`); + const publicKey = await blobs.get(`sftp_${keyType}_public_key`); + const publicKeyFile = path.join(paths.SFTP_KEYS_DIR, `ssh_host_${keyType}_key.pub`); + const privateKeyFile = path.join(paths.SFTP_KEYS_DIR, `ssh_host_${keyType}_key`); - if (!sftpRsaPrivateKey || !sftpRsaPublicKey) { - debug('ensureSecrets: generating new 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 newSftpPublicKey = safe.fs.readFileSync(paths.SFTP_RSA_PUBLIC_KEY_FILE); - await blobs.set(blobs.SFTP_RSA_PUBLIC_KEY, newSftpPublicKey); - const newSftpPrivateKey = safe.fs.readFileSync(paths.SFTP_RSA_PRIVATE_KEY_FILE); - await blobs.set(blobs.SFTP_RSA_PRIVATE_KEY, newSftpPrivateKey); - } else { - if (!safe.fs.writeFileSync(paths.SFTP_RSA_PUBLIC_KEY_FILE, sftpRsaPublicKey)) throw new BoxError(BoxError.FS_ERROR, `Could not save sftp public key: ${safe.error.message}`); - if (!safe.fs.writeFileSync(paths.SFTP_RSA_PRIVATE_KEY_FILE, sftpRsaPrivateKey, { mode: 0o600 })) throw new BoxError(BoxError.FS_ERROR, `Could not save sftp private key: ${safe.error.message}`); + if (!privateKey || !publicKey) { + debug(`ensureSecrets: generating new sftp keys of type ${keyType}`); + if (!safe.child_process.execSync(`ssh-keygen -m PEM -t ${keyType} -f "${paths.SFTP_KEYS_DIR}/ssh_host_${keyType}_key" -q -N ""`)) throw new BoxError(BoxError.OPENSSL_ERROR, `Could not generate sftp ${keyType} keys: ${safe.error.message}`); + const newPublicKey = safe.fs.readFileSync(publicKeyFile); + await blobs.set(`sftp_${keyType}_public_key`, newPublicKey); + const newPrivateKey = safe.fs.readFileSync(privateKeyFile); + await blobs.set(`sftp_${keyType}_private_key`, newPrivateKey); + } else { + if (!safe.fs.writeFileSync(publicKeyFile, publicKey)) throw new BoxError(BoxError.FS_ERROR, `Could not save sftp public ${keyType} key: ${safe.error.message}`); + if (!safe.fs.writeFileSync(privateKeyFile, privateKey, { mode: 0o600 })) throw new BoxError(BoxError.FS_ERROR, `Could not save sftp private ${keyType} key: ${safe.error.message}`); + } } }