diff --git a/backend/src/ee/services/external-kms/external-kms-service.ts b/backend/src/ee/services/external-kms/external-kms-service.ts index 49ac293ed..4d7b1a5b5 100644 --- a/backend/src/ee/services/external-kms/external-kms-service.ts +++ b/backend/src/ee/services/external-kms/external-kms-service.ts @@ -83,18 +83,26 @@ export const externalKmsServiceFactory = ({ throw error; }); - // if missing kms key this generate a new kms key id and returns new provider input - const newProviderInput = await externalKms.generateInputKmsKey(); - sanitizedProviderInput = JSON.stringify(newProviderInput); + try { + // if missing kms key this generate a new kms key id and returns new provider input + const newProviderInput = await externalKms.generateInputKmsKey(); + sanitizedProviderInput = JSON.stringify(newProviderInput); - await externalKms.validateConnection(); + await externalKms.validateConnection(); + } finally { + await externalKms.cleanup(); + } } break; case KmsProviders.Gcp: { const externalKms = await GcpKmsProviderFactory({ inputs: provider.inputs }); - await externalKms.validateConnection(); - sanitizedProviderInput = JSON.stringify(provider.inputs); + try { + await externalKms.validateConnection(); + sanitizedProviderInput = JSON.stringify(provider.inputs); + } finally { + await externalKms.cleanup(); + } } break; default: @@ -186,8 +194,12 @@ export const externalKmsServiceFactory = ({ ); const updatedProviderInput = { ...decryptedProviderInput, ...provider.inputs }; const externalKms = await AwsKmsProviderFactory({ inputs: updatedProviderInput }); - await externalKms.validateConnection(); - sanitizedProviderInput = JSON.stringify(updatedProviderInput); + try { + await externalKms.validateConnection(); + sanitizedProviderInput = JSON.stringify(updatedProviderInput); + } finally { + await externalKms.cleanup(); + } } break; case KmsProviders.Gcp: @@ -197,8 +209,12 @@ export const externalKmsServiceFactory = ({ ); const updatedProviderInput = { ...decryptedProviderInput, ...provider.inputs }; const externalKms = await GcpKmsProviderFactory({ inputs: updatedProviderInput }); - await externalKms.validateConnection(); - sanitizedProviderInput = JSON.stringify(updatedProviderInput); + try { + await externalKms.validateConnection(); + sanitizedProviderInput = JSON.stringify(updatedProviderInput); + } finally { + await externalKms.cleanup(); + } } break; default: @@ -368,7 +384,11 @@ export const externalKmsServiceFactory = ({ const fetchGcpKeys = async ({ credential, gcpRegion }: Pick) => { const externalKms = await GcpKmsProviderFactory({ inputs: { credential, gcpRegion, keyName: "" } }); - return externalKms.getKeysList(); + try { + return await externalKms.getKeysList(); + } finally { + await externalKms.cleanup(); + } }; return { diff --git a/backend/src/ee/services/external-kms/providers/aws-kms.ts b/backend/src/ee/services/external-kms/providers/aws-kms.ts index 6d9166a3a..2bda9c75e 100644 --- a/backend/src/ee/services/external-kms/providers/aws-kms.ts +++ b/backend/src/ee/services/external-kms/providers/aws-kms.ts @@ -102,10 +102,19 @@ export const AwsKmsProviderFactory = async ({ inputs }: AwsKmsProviderArgs): Pro return { data: Buffer.from(decryptionCommand.Plaintext) }; }; + const cleanup = async () => { + try { + awsClient.destroy(); + } catch (error) { + throw new Error("Failed to cleanup AWS KMS client", { cause: error }); + } + }; + return { generateInputKmsKey, validateConnection, encrypt, - decrypt + decrypt, + cleanup }; }; diff --git a/backend/src/ee/services/external-kms/providers/gcp-kms.ts b/backend/src/ee/services/external-kms/providers/gcp-kms.ts index bee1eb24b..ff2820fe8 100644 --- a/backend/src/ee/services/external-kms/providers/gcp-kms.ts +++ b/backend/src/ee/services/external-kms/providers/gcp-kms.ts @@ -45,6 +45,14 @@ export const GcpKmsProviderFactory = async ({ inputs }: GcpKmsProviderArgs): Pro } }; + const cleanup = async () => { + try { + await gcpKmsClient.close(); + } catch (error) { + throw new Error("Failed to cleanup GCP KMS client", { cause: error }); + } + }; + // Used when adding the KMS to fetch the list of keys in specified region const getKeysList = async () => { try { @@ -108,6 +116,7 @@ export const GcpKmsProviderFactory = async ({ inputs }: GcpKmsProviderArgs): Pro validateConnection, getKeysList, encrypt, - decrypt + decrypt, + cleanup }; }; diff --git a/backend/src/ee/services/external-kms/providers/model.ts b/backend/src/ee/services/external-kms/providers/model.ts index 436b39423..6cb78a34e 100644 --- a/backend/src/ee/services/external-kms/providers/model.ts +++ b/backend/src/ee/services/external-kms/providers/model.ts @@ -98,4 +98,5 @@ export type TExternalKmsProviderFns = { validateConnection: () => Promise; encrypt: (data: Buffer) => Promise<{ encryptedBlob: Buffer }>; decrypt: (encryptedBlob: Buffer) => Promise<{ data: Buffer }>; + cleanup: () => Promise; }; diff --git a/backend/src/services/kms/kms-service.ts b/backend/src/services/kms/kms-service.ts index 8bfa50b64..196c18356 100644 --- a/backend/src/services/kms/kms-service.ts +++ b/backend/src/services/kms/kms-service.ts @@ -342,9 +342,12 @@ export const kmsServiceFactory = ({ } return async ({ cipherTextBlob }: Pick) => { - const { data } = await externalKms.decrypt(cipherTextBlob); - - return data; + try { + const { data } = await externalKms.decrypt(cipherTextBlob); + return data; + } finally { + await externalKms.cleanup(); + } }; } @@ -557,9 +560,12 @@ export const kmsServiceFactory = ({ } return async ({ plainText }: Pick) => { - const { encryptedBlob } = await externalKms.encrypt(plainText); - - return { cipherTextBlob: encryptedBlob }; + try { + const { encryptedBlob } = await externalKms.encrypt(plainText); + return { cipherTextBlob: encryptedBlob }; + } finally { + await externalKms.cleanup(); + } }; }