From 62f92b0bfac9df97b7db6d006cce024259cd6da0 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 5 Jun 2024 23:58:45 +0530 Subject: [PATCH] feat: resolved root key failing for base64 and also added projectid and orgid field --- backend/src/db/migrations/20240603075514_kms.ts | 5 +++++ backend/src/db/schemas/kms-keys.ts | 5 ++++- backend/src/services/kms/kms-service.ts | 16 +++++++++++----- backend/src/services/kms/kms-types.ts | 6 ++++++ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/backend/src/db/migrations/20240603075514_kms.ts b/backend/src/db/migrations/20240603075514_kms.ts index 928d8c95c4..3531682d5d 100644 --- a/backend/src/db/migrations/20240603075514_kms.ts +++ b/backend/src/db/migrations/20240603075514_kms.ts @@ -21,6 +21,11 @@ export async function up(knex: Knex): Promise { t.integer("version").defaultTo(1).notNullable(); t.string("description"); t.boolean("isDisabled").defaultTo(false); + t.boolean("isReserved").defaultTo(true); + t.string("projectId"); + t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE"); + t.uuid("orgId"); + t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE"); }); } diff --git a/backend/src/db/schemas/kms-keys.ts b/backend/src/db/schemas/kms-keys.ts index be6fc45859..503c270d9a 100644 --- a/backend/src/db/schemas/kms-keys.ts +++ b/backend/src/db/schemas/kms-keys.ts @@ -15,7 +15,10 @@ export const KmsKeysSchema = z.object({ encryptionAlgorithm: z.string(), version: z.number().default(1), description: z.string().nullable().optional(), - isDisabled: z.boolean().default(false).nullable().optional() + isDisabled: z.boolean().default(false).nullable().optional(), + isReserved: z.boolean().default(true).nullable().optional(), + projectId: z.string().nullable().optional(), + orgId: z.string().uuid().nullable().optional() }); export type TKmsKeys = z.infer; diff --git a/backend/src/services/kms/kms-service.ts b/backend/src/services/kms/kms-service.ts index 93613c58d6..24d9018677 100644 --- a/backend/src/services/kms/kms-service.ts +++ b/backend/src/services/kms/kms-service.ts @@ -7,7 +7,7 @@ import { logger } from "@app/lib/logger"; import { TKmsDALFactory } from "./kms-dal"; import { TKmsRootConfigDALFactory } from "./kms-root-config-dal"; -import { TDecryptWithKmsDTO, TEncryptWithKmsDTO } from "./kms-types"; +import { TDecryptWithKmsDTO, TEncryptWithKmsDTO, TGenerateKMSDTO } from "./kms-types"; type TKmsServiceFactoryDep = { kmsDAL: TKmsDALFactory; @@ -29,7 +29,7 @@ export const kmsServiceFactory = ({ kmsDAL, kmsRootConfigDAL, keyStore }: TKmsSe let ROOT_ENCRYPTION_KEY = Buffer.alloc(0); // this is used symmetric encryption - const generateKmsKey = async () => { + const generateKmsKey = async ({ scopeId, scopeType, isReserved = true }: TGenerateKMSDTO) => { const cipher = symmetricCipherService(SymmetricEncryption.AES_GCM_256); const kmsKeyMaterial = randomSecureBytes(32); const encryptedKeyMaterial = cipher.encrypt(kmsKeyMaterial, ROOT_ENCRYPTION_KEY); @@ -37,7 +37,10 @@ export const kmsServiceFactory = ({ kmsDAL, kmsRootConfigDAL, keyStore }: TKmsSe const { encryptedKey, ...doc } = await kmsDAL.create({ version: 1, encryptedKey: encryptedKeyMaterial, - encryptionAlgorithm: SymmetricEncryption.AES_GCM_256 + encryptionAlgorithm: SymmetricEncryption.AES_GCM_256, + isReserved, + orgId: scopeType === "org" ? scopeId : undefined, + projectId: scopeType === "project" ? scopeId : undefined }); return doc; }; @@ -73,7 +76,10 @@ export const kmsServiceFactory = ({ kmsDAL, kmsRootConfigDAL, keyStore }: TKmsSe const appCfg = getConfig(); // This will switch to a seal process and HMS flow in future const encryptionKey = appCfg.ENCRYPTION_KEY || appCfg.ROOT_ENCRYPTION_KEY; + // if root key its base64 encoded + const isBase64 = Boolean(appCfg.ROOT_ENCRYPTION_KEY); if (!encryptionKey) throw new Error("Root encryption key not found for KMS service."); + const encryptionKeyBuffer = Buffer.from(encryptionKey, isBase64 ? "base64" : "utf8"); const lock = await keyStore.acquireLock([`KMS_ROOT_CFG_LOCK`], 3000, { retryCount: 3 }).catch(() => null); if (!lock) { @@ -90,7 +96,7 @@ export const kmsServiceFactory = ({ kmsDAL, kmsRootConfigDAL, keyStore }: TKmsSe if (kmsRootConfig) { if (lock) await lock.release(); logger.info("KMS: Encrypted ROOT Key found from DB. Decrypting."); - const decryptedRootKey = cipher.decrypt(kmsRootConfig.encryptedRootKey, Buffer.from(encryptionKey, "utf8")); + const decryptedRootKey = cipher.decrypt(kmsRootConfig.encryptedRootKey, encryptionKeyBuffer); // set the flag so that other instancen nodes can start await keyStore.setItemWithExpiry(KMS_ROOT_CREATION_WAIT_KEY, KMS_ROOT_CREATION_WAIT_TIME, "true"); logger.info("KMS: Loading ROOT Key into Memory."); @@ -100,7 +106,7 @@ export const kmsServiceFactory = ({ kmsDAL, kmsRootConfigDAL, keyStore }: TKmsSe logger.info("KMS: Generating ROOT Key"); const newRootKey = randomSecureBytes(32); - const encryptedRootKey = cipher.encrypt(newRootKey, Buffer.from(encryptionKey, "utf8")); + const encryptedRootKey = cipher.encrypt(newRootKey, encryptionKeyBuffer); // @ts-expect-error id is kept as fixed for idempotence and to avoid race condition await kmsRootConfigDAL.create({ encryptedRootKey, id: KMS_ROOT_CONFIG_UUID }); diff --git a/backend/src/services/kms/kms-types.ts b/backend/src/services/kms/kms-types.ts index 6aa5300fee..96ad25f6e0 100644 --- a/backend/src/services/kms/kms-types.ts +++ b/backend/src/services/kms/kms-types.ts @@ -1,3 +1,9 @@ +export type TGenerateKMSDTO = { + scopeType: "project" | "org"; + scopeId: string; + isReserved?: boolean; +}; + export type TEncryptWithKmsDTO = { kmsId: string; plainText: Buffer;