From 2de898fdbd891d32c3e477e10fc197b183960b81 Mon Sep 17 00:00:00 2001 From: Akhil Mohan Date: Mon, 30 Oct 2023 22:19:12 +0530 Subject: [PATCH] feat: backward compatiable enc key --- backend/src/ee/secretRotation/queue.ts | 34 +++++++++++++----- backend/src/ee/secretRotation/service.ts | 44 ++++++++++++++++++------ 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/backend/src/ee/secretRotation/queue.ts b/backend/src/ee/secretRotation/queue.ts index c545a9ac2..501e4d748 100644 --- a/backend/src/ee/secretRotation/queue.ts +++ b/backend/src/ee/secretRotation/queue.ts @@ -5,7 +5,7 @@ import { customAlphabet } from "nanoid"; import { Client as PgClient } from "pg"; import mysql from "mysql"; -import { client, getRootEncryptionKey } from "../../config"; +import { client, getEncryptionKey, getRootEncryptionKey } from "../../config"; import { BotService, EventService, TelemetryService } from "../../services"; import { SecretRotation } from "./models"; import { rotationTemplates } from "./templates"; @@ -21,9 +21,12 @@ import { TProviderFunction, TProviderFunctionTypes } from "./types"; -import { encryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto"; +import { + decryptSymmetric128BitHexKeyUTF8, + encryptSymmetric128BitHexKeyUTF8 +} from "../../utils/crypto"; import { ISecret, Secret } from "../../models"; -import { SECRET_SHARED } from "../../variables"; +import { ENCODING_SCHEME_BASE64, ENCODING_SCHEME_UTF8, SECRET_SHARED } from "../../variables"; import { EESecretService } from "../services"; import { SecretVersion } from "../models"; import { eventPushSecrets } from "../../events"; @@ -215,13 +218,26 @@ secretRotationQueue.process(async (job: Job) => { ) as ISecretRotationProviderTemplate; // decrypt user provided inputs for secret rotation + const encryptionKey = await getEncryptionKey(); const rootEncryptionKey = await getRootEncryptionKey(); - const decryptedData = client.decryptSymmetric( - secretRotation.encryptedData, - rootEncryptionKey, - secretRotation.encryptedDataIV, - secretRotation.encryptedDataTag - ); + let decryptedData = ""; + if (rootEncryptionKey && secretRotation.keyEncoding === ENCODING_SCHEME_BASE64) { + // case: encoding scheme is base64 + decryptedData = client.decryptSymmetric( + secretRotation.encryptedData, + rootEncryptionKey, + secretRotation.encryptedDataIV, + secretRotation.encryptedDataTag + ); + } else if (encryptionKey && secretRotation.keyEncoding === ENCODING_SCHEME_UTF8) { + // case: encoding scheme is utf8 + decryptedData = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: secretRotation.encryptedData, + iv: secretRotation.encryptedDataIV, + tag: secretRotation.encryptedDataTag, + key: encryptionKey + }); + } const variables = JSON.parse(decryptedData) as ISecretRotationEncData; diff --git a/backend/src/ee/secretRotation/service.ts b/backend/src/ee/secretRotation/service.ts index 8476dcbb8..2ed68d646 100644 --- a/backend/src/ee/secretRotation/service.ts +++ b/backend/src/ee/secretRotation/service.ts @@ -1,10 +1,16 @@ import { ISecretRotationEncData, TCreateSecretRotation, TGetProviderTemplates } from "./types"; import { rotationTemplates } from "./templates"; import { SecretRotation } from "./models"; -import { client, getRootEncryptionKey } from "../../config"; +import { client, getEncryptionKey, getRootEncryptionKey } from "../../config"; import { BadRequestError } from "../../utils/errors"; import Ajv from "ajv"; import { removeSecretRotationQueue, startSecretRotationQueue } from "./queue"; +import { + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_BASE64, + ENCODING_SCHEME_UTF8 +} from "../../variables"; +import { encryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto"; const ajv = new Ajv(); @@ -51,24 +57,40 @@ export const createSecretRotation = async ({ creds: [] }; - const rootEncryptionKey = await getRootEncryptionKey(); - const { ciphertext, iv, tag } = client.encryptSymmetric( - JSON.stringify(encData), - rootEncryptionKey - ); - const secretRotation = new SecretRotation({ workspace: workspaceId, provider, environment, secretPath, interval, - outputs: Object.entries(outputs).map(([key, secret]) => ({ key, secret })), - encryptedData: ciphertext, - encryptedDataIV: iv, - encryptedDataTag: tag + outputs: Object.entries(outputs).map(([key, secret]) => ({ key, secret })) }); + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + if (rootEncryptionKey) { + const { ciphertext, iv, tag } = client.encryptSymmetric( + JSON.stringify(encData), + rootEncryptionKey + ); + secretRotation.encryptedDataIV = iv; + secretRotation.encryptedDataTag = tag; + secretRotation.encryptedData = ciphertext; + secretRotation.algorithm = ALGORITHM_AES_256_GCM; + secretRotation.keyEncoding = ENCODING_SCHEME_BASE64; + } else if (encryptionKey) { + const { ciphertext, iv, tag } = encryptSymmetric128BitHexKeyUTF8({ + plaintext: JSON.stringify(encData), + key: encryptionKey + }); + secretRotation.encryptedDataIV = iv; + secretRotation.encryptedDataTag = tag; + secretRotation.encryptedData = ciphertext; + secretRotation.algorithm = ALGORITHM_AES_256_GCM; + secretRotation.keyEncoding = ENCODING_SCHEME_UTF8; + } + await secretRotation.save(); await startSecretRotationQueue(secretRotation._id.toString(), interval);