diff --git a/packages/backend-core/src/security/encryption.ts b/packages/backend-core/src/security/encryption.ts index ac8589ddf3..0cc52d6210 100644 --- a/packages/backend-core/src/security/encryption.ts +++ b/packages/backend-core/src/security/encryption.ts @@ -2,6 +2,7 @@ import crypto from "crypto" import fs from "fs" import zlib from "zlib" import env from "../environment" +import { join } from "path" const ALGO = "aes-256-ctr" const SEPARATOR = "-" @@ -63,11 +64,15 @@ export function decrypt( return Buffer.concat([base, final]).toString() } -export async function encryptFile(filePath: string, secret: string) { - const outputFilePath = `${filePath}.enc` +export async function encryptFile( + { dir, filename }: { dir: string; filename: string }, + secret: string +) { + const outputFileName = `${filename}.enc` + const filePath = join(dir, filename) const inputFile = fs.createReadStream(filePath) - const outputFile = fs.createWriteStream(outputFilePath) + const outputFile = fs.createWriteStream(join(dir, outputFileName)) const salt = crypto.randomBytes(RANDOM_BYTES) const stretched = stretchString(secret, salt) @@ -77,9 +82,12 @@ export async function encryptFile(filePath: string, secret: string) { encrypted.pipe(outputFile) - return new Promise(r => { + return new Promise<{ filename: string; dir: string }>(r => { outputFile.on("finish", () => { - r(outputFilePath) + r({ + filename: outputFileName, + dir, + }) }) }) } diff --git a/packages/server/src/api/controllers/backup.ts b/packages/server/src/api/controllers/backup.ts index 716f5298dd..4c267d5c77 100644 --- a/packages/server/src/api/controllers/backup.ts +++ b/packages/server/src/api/controllers/backup.ts @@ -9,7 +9,7 @@ export async function exportAppDump(ctx: any) { ctx.req.setTimeout(0) const appName = decodeURI(ctx.query.appname) excludeRows = isQsTrue(excludeRows) - const extension = encryptPassword ? "data" : "tar.gz" + const extension = encryptPassword ? "enc.tar.gz" : "tar.gz" const backupIdentifier = `${appName}-export-${new Date().getTime()}.${extension}` ctx.attachment(backupIdentifier) ctx.body = await sdk.backups.streamExportApp({ diff --git a/packages/server/src/sdk/app/backups/exports.ts b/packages/server/src/sdk/app/backups/exports.ts index 6bce7eed5c..0f629630e2 100644 --- a/packages/server/src/sdk/app/backups/exports.ts +++ b/packages/server/src/sdk/app/backups/exports.ts @@ -145,21 +145,28 @@ export async function exportApp(appId: string, config?: ExportOpts) { filter: defineFilter(config?.excludeRows, config?.excludeLogs), exportPath: dbPath, }) + + if (config?.encryptPassword) { + for (let file of fs.readdirSync(tmpPath)) { + const path = join(tmpPath, file) + + await encryption.encryptFile( + { dir: tmpPath, filename: file }, + config.encryptPassword + ) + + fs.rmSync(path) + } + } + // if tar requested, return where the tarball is if (config?.tar) { // now the tmpPath contains both the DB export and attachments, tar this const tarPath = tarFilesToTmp(tmpPath, fs.readdirSync(tmpPath)) // cleanup the tmp export files as tarball returned fs.rmSync(tmpPath, { recursive: true, force: true }) - if (!config.encryptPassword) { - return tarPath - } - const encryptedTarPath = await encryption.encryptFile( - tarPath, - config.encryptPassword - ) - return encryptedTarPath + return tarPath } // tar not requested, turn the directory where export is else {