Merge pull request #3501 from Infisical/fix-kms-memory-leak

Fix KMS memory leak
This commit is contained in:
Maidul Islam
2025-04-28 05:02:26 -07:00
committed by GitHub
5 changed files with 64 additions and 19 deletions
@@ -83,18 +83,26 @@ export const externalKmsServiceFactory = ({
throw error; throw error;
}); });
// if missing kms key this generate a new kms key id and returns new provider input try {
const newProviderInput = await externalKms.generateInputKmsKey(); // if missing kms key this generate a new kms key id and returns new provider input
sanitizedProviderInput = JSON.stringify(newProviderInput); const newProviderInput = await externalKms.generateInputKmsKey();
sanitizedProviderInput = JSON.stringify(newProviderInput);
await externalKms.validateConnection(); await externalKms.validateConnection();
} finally {
await externalKms.cleanup();
}
} }
break; break;
case KmsProviders.Gcp: case KmsProviders.Gcp:
{ {
const externalKms = await GcpKmsProviderFactory({ inputs: provider.inputs }); const externalKms = await GcpKmsProviderFactory({ inputs: provider.inputs });
await externalKms.validateConnection(); try {
sanitizedProviderInput = JSON.stringify(provider.inputs); await externalKms.validateConnection();
sanitizedProviderInput = JSON.stringify(provider.inputs);
} finally {
await externalKms.cleanup();
}
} }
break; break;
default: default:
@@ -186,8 +194,12 @@ export const externalKmsServiceFactory = ({
); );
const updatedProviderInput = { ...decryptedProviderInput, ...provider.inputs }; const updatedProviderInput = { ...decryptedProviderInput, ...provider.inputs };
const externalKms = await AwsKmsProviderFactory({ inputs: updatedProviderInput }); const externalKms = await AwsKmsProviderFactory({ inputs: updatedProviderInput });
await externalKms.validateConnection(); try {
sanitizedProviderInput = JSON.stringify(updatedProviderInput); await externalKms.validateConnection();
sanitizedProviderInput = JSON.stringify(updatedProviderInput);
} finally {
await externalKms.cleanup();
}
} }
break; break;
case KmsProviders.Gcp: case KmsProviders.Gcp:
@@ -197,8 +209,12 @@ export const externalKmsServiceFactory = ({
); );
const updatedProviderInput = { ...decryptedProviderInput, ...provider.inputs }; const updatedProviderInput = { ...decryptedProviderInput, ...provider.inputs };
const externalKms = await GcpKmsProviderFactory({ inputs: updatedProviderInput }); const externalKms = await GcpKmsProviderFactory({ inputs: updatedProviderInput });
await externalKms.validateConnection(); try {
sanitizedProviderInput = JSON.stringify(updatedProviderInput); await externalKms.validateConnection();
sanitizedProviderInput = JSON.stringify(updatedProviderInput);
} finally {
await externalKms.cleanup();
}
} }
break; break;
default: default:
@@ -368,7 +384,11 @@ export const externalKmsServiceFactory = ({
const fetchGcpKeys = async ({ credential, gcpRegion }: Pick<TExternalKmsGcpSchema, "credential" | "gcpRegion">) => { const fetchGcpKeys = async ({ credential, gcpRegion }: Pick<TExternalKmsGcpSchema, "credential" | "gcpRegion">) => {
const externalKms = await GcpKmsProviderFactory({ inputs: { credential, gcpRegion, keyName: "" } }); const externalKms = await GcpKmsProviderFactory({ inputs: { credential, gcpRegion, keyName: "" } });
return externalKms.getKeysList(); try {
return await externalKms.getKeysList();
} finally {
await externalKms.cleanup();
}
}; };
return { return {
@@ -102,10 +102,19 @@ export const AwsKmsProviderFactory = async ({ inputs }: AwsKmsProviderArgs): Pro
return { data: Buffer.from(decryptionCommand.Plaintext) }; 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 { return {
generateInputKmsKey, generateInputKmsKey,
validateConnection, validateConnection,
encrypt, encrypt,
decrypt decrypt,
cleanup
}; };
}; };
@@ -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 // Used when adding the KMS to fetch the list of keys in specified region
const getKeysList = async () => { const getKeysList = async () => {
try { try {
@@ -108,6 +116,7 @@ export const GcpKmsProviderFactory = async ({ inputs }: GcpKmsProviderArgs): Pro
validateConnection, validateConnection,
getKeysList, getKeysList,
encrypt, encrypt,
decrypt decrypt,
cleanup
}; };
}; };
@@ -98,4 +98,5 @@ export type TExternalKmsProviderFns = {
validateConnection: () => Promise<boolean>; validateConnection: () => Promise<boolean>;
encrypt: (data: Buffer) => Promise<{ encryptedBlob: Buffer }>; encrypt: (data: Buffer) => Promise<{ encryptedBlob: Buffer }>;
decrypt: (encryptedBlob: Buffer) => Promise<{ data: Buffer }>; decrypt: (encryptedBlob: Buffer) => Promise<{ data: Buffer }>;
cleanup: () => Promise<void>;
}; };
+12 -6
View File
@@ -342,9 +342,12 @@ export const kmsServiceFactory = ({
} }
return async ({ cipherTextBlob }: Pick<TDecryptWithKmsDTO, "cipherTextBlob">) => { return async ({ cipherTextBlob }: Pick<TDecryptWithKmsDTO, "cipherTextBlob">) => {
const { data } = await externalKms.decrypt(cipherTextBlob); try {
const { data } = await externalKms.decrypt(cipherTextBlob);
return data; return data;
} finally {
await externalKms.cleanup();
}
}; };
} }
@@ -557,9 +560,12 @@ export const kmsServiceFactory = ({
} }
return async ({ plainText }: Pick<TEncryptWithKmsDTO, "plainText">) => { return async ({ plainText }: Pick<TEncryptWithKmsDTO, "plainText">) => {
const { encryptedBlob } = await externalKms.encrypt(plainText); try {
const { encryptedBlob } = await externalKms.encrypt(plainText);
return { cipherTextBlob: encryptedBlob }; return { cipherTextBlob: encryptedBlob };
} finally {
await externalKms.cleanup();
}
}; };
} }