feat: added encrypt/decrypt with key for kms service and changed kms encrytion to hoc to avoid back to back db calls

This commit is contained in:
=
2024-07-10 15:23:02 +05:30
parent 08f0bf9c67
commit 5d4c7c2cbf
9 changed files with 139 additions and 121 deletions

View File

@@ -17,7 +17,7 @@ type TCertificateAuthorityCrlServiceFactoryDep = {
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">; certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">;
certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "findOne">; certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "findOne">;
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">; projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
kmsService: Pick<TKmsServiceFactory, "decrypt" | "generateKmsKey">; kmsService: Pick<TKmsServiceFactory, "decryptWithKmsKey" | "generateKmsKey">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">; permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">; licenseService: Pick<TLicenseServiceFactory, "getPlan">;
}; };
@@ -68,11 +68,11 @@ export const certificateAuthorityCrlServiceFactory = ({
kmsService kmsService
}); });
const decryptedCrl = await kmsService.decrypt({ const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: keyId, kmsId: keyId
cipherTextBlob: caCrl.encryptedCrl
}); });
const decryptedCrl = kmsDecryptor({ cipherTextBlob: caCrl.encryptedCrl });
const crl = new x509.X509Crl(decryptedCrl); const crl = new x509.X509Crl(decryptedCrl);
const base64crl = crl.toString("base64"); const base64crl = crl.toString("base64");

View File

@@ -22,7 +22,7 @@ import { ExternalKmsAwsSchema, KmsProviders } from "./providers/model";
type TExternalKmsServiceFactoryDep = { type TExternalKmsServiceFactoryDep = {
externalKmsDAL: TExternalKmsDALFactory; externalKmsDAL: TExternalKmsDALFactory;
kmsService: Pick<TKmsServiceFactory, "getOrgKmsKeyId" | "encrypt" | "decrypt">; kmsService: Pick<TKmsServiceFactory, "getOrgKmsKeyId" | "encryptWithKmsKey" | "decryptWithKmsKey">;
kmsDAL: Pick<TKmsKeyDALFactory, "create" | "updateById" | "findById" | "deleteById" | "findOne">; kmsDAL: Pick<TKmsKeyDALFactory, "create" | "updateById" | "findById" | "deleteById" | "findOne">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">; permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
}; };
@@ -70,8 +70,10 @@ export const externalKmsServiceFactory = ({
} }
const orgKmsKeyId = await kmsService.getOrgKmsKeyId(actorOrgId); const orgKmsKeyId = await kmsService.getOrgKmsKeyId(actorOrgId);
const { cipherTextBlob: encryptedProviderInputs } = await kmsService.encrypt({ const kmsEncryptor = await kmsService.encryptWithKmsKey({
kmsId: orgKmsKeyId, kmsId: orgKmsKeyId
});
const { cipherTextBlob: encryptedProviderInputs } = kmsEncryptor({
plainText: Buffer.from(sanitizedProviderInput, "utf8") plainText: Buffer.from(sanitizedProviderInput, "utf8")
}); });
@@ -126,8 +128,10 @@ export const externalKmsServiceFactory = ({
const orgDefaultKmsId = await kmsService.getOrgKmsKeyId(kmsDoc.orgId); const orgDefaultKmsId = await kmsService.getOrgKmsKeyId(kmsDoc.orgId);
let sanitizedProviderInput = ""; let sanitizedProviderInput = "";
if (provider) { if (provider) {
const decryptedProviderInputBlob = await kmsService.decrypt({ const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: orgDefaultKmsId, kmsId: orgDefaultKmsId
});
const decryptedProviderInputBlob = kmsDecryptor({
cipherTextBlob: externalKmsDoc.encryptedProviderInputs cipherTextBlob: externalKmsDoc.encryptedProviderInputs
}); });
@@ -150,8 +154,10 @@ export const externalKmsServiceFactory = ({
let encryptedProviderInputs: Buffer | undefined; let encryptedProviderInputs: Buffer | undefined;
if (sanitizedProviderInput) { if (sanitizedProviderInput) {
const { cipherTextBlob } = await kmsService.encrypt({ const kmsEncryptor = await kmsService.encryptWithKmsKey({
kmsId: orgDefaultKmsId, kmsId: orgDefaultKmsId
});
const { cipherTextBlob } = kmsEncryptor({
plainText: Buffer.from(sanitizedProviderInput, "utf8") plainText: Buffer.from(sanitizedProviderInput, "utf8")
}); });
encryptedProviderInputs = cipherTextBlob; encryptedProviderInputs = cipherTextBlob;
@@ -234,8 +240,10 @@ export const externalKmsServiceFactory = ({
if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" }); if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" });
const orgDefaultKmsId = await kmsService.getOrgKmsKeyId(kmsDoc.orgId); const orgDefaultKmsId = await kmsService.getOrgKmsKeyId(kmsDoc.orgId);
const decryptedProviderInputBlob = await kmsService.decrypt({ const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: orgDefaultKmsId, kmsId: orgDefaultKmsId
});
const decryptedProviderInputBlob = kmsDecryptor({
cipherTextBlob: externalKmsDoc.encryptedProviderInputs cipherTextBlob: externalKmsDoc.encryptedProviderInputs
}); });
switch (externalKmsDoc.provider) { switch (externalKmsDoc.provider) {
@@ -271,10 +279,13 @@ export const externalKmsServiceFactory = ({
if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" }); if (!externalKmsDoc) throw new BadRequestError({ message: "External kms not found" });
const orgDefaultKmsId = await kmsService.getOrgKmsKeyId(kmsDoc.orgId); const orgDefaultKmsId = await kmsService.getOrgKmsKeyId(kmsDoc.orgId);
const decryptedProviderInputBlob = await kmsService.decrypt({ const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: orgDefaultKmsId, kmsId: orgDefaultKmsId
});
const decryptedProviderInputBlob = kmsDecryptor({
cipherTextBlob: externalKmsDoc.encryptedProviderInputs cipherTextBlob: externalKmsDoc.encryptedProviderInputs
}); });
switch (externalKmsDoc.provider) { switch (externalKmsDoc.provider) {
case KmsProviders.Aws: { case KmsProviders.Aws: {
const decryptedProviderInput = await ExternalKmsAwsSchema.parseAsync( const decryptedProviderInput = await ExternalKmsAwsSchema.parseAsync(

View File

@@ -75,8 +75,10 @@ export const getCaCredentials = async ({
kmsService kmsService
}); });
const decryptedPrivateKey = await kmsService.decrypt({ const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: keyId, kmsId: keyId
});
const decryptedPrivateKey = kmsDecryptor({
cipherTextBlob: caSecret.encryptedPrivateKey cipherTextBlob: caSecret.encryptedPrivateKey
}); });
@@ -123,15 +125,17 @@ export const getCaCertChain = async ({
kmsService kmsService
}); });
const decryptedCaCert = await kmsService.decrypt({ const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: keyId, kmsId: keyId
});
const decryptedCaCert = kmsDecryptor({
cipherTextBlob: caCert.encryptedCertificate cipherTextBlob: caCert.encryptedCertificate
}); });
const caCertObj = new x509.X509Certificate(decryptedCaCert); const caCertObj = new x509.X509Certificate(decryptedCaCert);
const decryptedChain = await kmsService.decrypt({ const decryptedChain = kmsDecryptor({
kmsId: keyId,
cipherTextBlob: caCert.encryptedCertificateChain cipherTextBlob: caCert.encryptedCertificateChain
}); });
@@ -168,8 +172,11 @@ export const rebuildCaCrl = async ({
kmsService kmsService
}); });
const privateKey = await kmsService.decrypt({ const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: keyId, kmsId: keyId
});
const privateKey = kmsDecryptor({
cipherTextBlob: caSecret.encryptedPrivateKey cipherTextBlob: caSecret.encryptedPrivateKey
}); });
@@ -200,8 +207,10 @@ export const rebuildCaCrl = async ({
signingKey: sk signingKey: sk
}); });
const { cipherTextBlob: encryptedCrl } = await kmsService.encrypt({ const kmsEncryptor = await kmsService.encryptWithKmsKey({
kmsId: keyId, kmsId: keyId
});
const { cipherTextBlob: encryptedCrl } = kmsEncryptor({
plainText: Buffer.from(new Uint8Array(crl.rawData)) plainText: Buffer.from(new Uint8Array(crl.rawData))
}); });

View File

@@ -25,7 +25,7 @@ type TCertificateAuthorityQueueFactoryDep = {
certificateAuthoritySecretDAL: TCertificateAuthoritySecretDALFactory; certificateAuthoritySecretDAL: TCertificateAuthoritySecretDALFactory;
certificateDAL: TCertificateDALFactory; certificateDAL: TCertificateDALFactory;
projectDAL: Pick<TProjectDALFactory, "findProjectBySlug" | "findOne" | "updateById" | "findById" | "transaction">; projectDAL: Pick<TProjectDALFactory, "findProjectBySlug" | "findOne" | "updateById" | "findById" | "transaction">;
kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "encrypt" | "decrypt">; kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "encryptWithKmsKey" | "decryptWithKmsKey">;
queueService: TQueueServiceFactory; queueService: TQueueServiceFactory;
}; };
export type TCertificateAuthorityQueueFactory = ReturnType<typeof certificateAuthorityQueueFactory>; export type TCertificateAuthorityQueueFactory = ReturnType<typeof certificateAuthorityQueueFactory>;
@@ -88,8 +88,10 @@ export const certificateAuthorityQueueFactory = ({
kmsService kmsService
}); });
const privateKey = await kmsService.decrypt({ const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: keyId, kmsId: keyId
});
const privateKey = kmsDecryptor({
cipherTextBlob: caSecret.encryptedPrivateKey cipherTextBlob: caSecret.encryptedPrivateKey
}); });
@@ -120,8 +122,10 @@ export const certificateAuthorityQueueFactory = ({
signingKey: sk signingKey: sk
}); });
const { cipherTextBlob: encryptedCrl } = await kmsService.encrypt({ const kmsEncryptor = await kmsService.encryptWithKmsKey({
kmsId: keyId, kmsId: keyId
});
const { cipherTextBlob: encryptedCrl } = kmsEncryptor({
plainText: Buffer.from(new Uint8Array(crl.rawData)) plainText: Buffer.from(new Uint8Array(crl.rawData))
}); });

View File

@@ -53,7 +53,7 @@ type TCertificateAuthorityServiceFactoryDep = {
certificateDAL: Pick<TCertificateDALFactory, "transaction" | "create" | "find">; certificateDAL: Pick<TCertificateDALFactory, "transaction" | "create" | "find">;
certificateBodyDAL: Pick<TCertificateBodyDALFactory, "create">; certificateBodyDAL: Pick<TCertificateBodyDALFactory, "create">;
projectDAL: Pick<TProjectDALFactory, "findProjectBySlug" | "findOne" | "updateById" | "findById" | "transaction">; projectDAL: Pick<TProjectDALFactory, "findProjectBySlug" | "findOne" | "updateById" | "findById" | "transaction">;
kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "encrypt" | "decrypt">; kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "encryptWithKmsKey" | "decryptWithKmsKey">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">; permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
}; };
@@ -154,11 +154,14 @@ export const certificateAuthorityServiceFactory = ({
tx tx
); );
const keyId = await getProjectKmsCertificateKeyId({ const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
projectId: project.id, projectId: project.id,
projectDAL, projectDAL,
kmsService kmsService
}); });
const kmsEncryptor = await kmsService.encryptWithKmsKey({
kmsId: certificateManagerKmsId
});
if (type === CaType.ROOT) { if (type === CaType.ROOT) {
// note: create self-signed cert only applicable for root CA // note: create self-signed cert only applicable for root CA
@@ -178,13 +181,11 @@ export const certificateAuthorityServiceFactory = ({
] ]
}); });
const { cipherTextBlob: encryptedCertificate } = await kmsService.encrypt({ const { cipherTextBlob: encryptedCertificate } = kmsEncryptor({
kmsId: keyId,
plainText: Buffer.from(new Uint8Array(cert.rawData)) plainText: Buffer.from(new Uint8Array(cert.rawData))
}); });
const { cipherTextBlob: encryptedCertificateChain } = await kmsService.encrypt({ const { cipherTextBlob: encryptedCertificateChain } = kmsEncryptor({
kmsId: keyId,
plainText: Buffer.alloc(0) plainText: Buffer.alloc(0)
}); });
@@ -208,8 +209,7 @@ export const certificateAuthorityServiceFactory = ({
signingKey: keys.privateKey signingKey: keys.privateKey
}); });
const { cipherTextBlob: encryptedCrl } = await kmsService.encrypt({ const { cipherTextBlob: encryptedCrl } = kmsEncryptor({
kmsId: keyId,
plainText: Buffer.from(new Uint8Array(crl.rawData)) plainText: Buffer.from(new Uint8Array(crl.rawData))
}); });
@@ -224,8 +224,7 @@ export const certificateAuthorityServiceFactory = ({
// https://nodejs.org/api/crypto.html#static-method-keyobjectfromkey // https://nodejs.org/api/crypto.html#static-method-keyobjectfromkey
const skObj = KeyObject.from(keys.privateKey); const skObj = KeyObject.from(keys.privateKey);
const { cipherTextBlob: encryptedPrivateKey } = await kmsService.encrypt({ const { cipherTextBlob: encryptedPrivateKey } = kmsEncryptor({
kmsId: keyId,
plainText: skObj.export({ plainText: skObj.export({
type: "pkcs8", type: "pkcs8",
format: "der" format: "der"
@@ -449,15 +448,17 @@ export const certificateAuthorityServiceFactory = ({
const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm); const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
const keyId = await getProjectKmsCertificateKeyId({ const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
projectId: ca.projectId, projectId: ca.projectId,
projectDAL, projectDAL,
kmsService kmsService
}); });
const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: certificateManagerKmsId
});
const caCert = await certificateAuthorityCertDAL.findOne({ caId: ca.id }); const caCert = await certificateAuthorityCertDAL.findOne({ caId: ca.id });
const decryptedCaCert = await kmsService.decrypt({ const decryptedCaCert = kmsDecryptor({
kmsId: keyId,
cipherTextBlob: caCert.encryptedCertificate cipherTextBlob: caCert.encryptedCertificate
}); });
@@ -605,19 +606,20 @@ export const certificateAuthorityServiceFactory = ({
dn: parentCertSubject dn: parentCertSubject
}); });
const keyId = await getProjectKmsCertificateKeyId({ const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
projectId: ca.projectId, projectId: ca.projectId,
projectDAL, projectDAL,
kmsService kmsService
}); });
const kmsEncryptor = await kmsService.encryptWithKmsKey({
kmsId: certificateManagerKmsId
});
const { cipherTextBlob: encryptedCertificate } = await kmsService.encrypt({ const { cipherTextBlob: encryptedCertificate } = kmsEncryptor({
kmsId: keyId,
plainText: Buffer.from(new Uint8Array(certObj.rawData)) plainText: Buffer.from(new Uint8Array(certObj.rawData))
}); });
const { cipherTextBlob: encryptedCertificateChain } = await kmsService.encrypt({ const { cipherTextBlob: encryptedCertificateChain } = kmsEncryptor({
kmsId: keyId,
plainText: Buffer.from(certificateChain) plainText: Buffer.from(certificateChain)
}); });
@@ -682,14 +684,16 @@ export const certificateAuthorityServiceFactory = ({
const caCert = await certificateAuthorityCertDAL.findOne({ caId: ca.id }); const caCert = await certificateAuthorityCertDAL.findOne({ caId: ca.id });
if (!caCert) throw new BadRequestError({ message: "CA does not have a certificate installed" }); if (!caCert) throw new BadRequestError({ message: "CA does not have a certificate installed" });
const keyId = await getProjectKmsCertificateKeyId({ const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
projectId: ca.projectId, projectId: ca.projectId,
projectDAL, projectDAL,
kmsService kmsService
}); });
const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: certificateManagerKmsId
});
const decryptedCaCert = await kmsService.decrypt({ const decryptedCaCert = kmsDecryptor({
kmsId: keyId,
cipherTextBlob: caCert.encryptedCertificate cipherTextBlob: caCert.encryptedCertificate
}); });
@@ -796,8 +800,10 @@ export const certificateAuthorityServiceFactory = ({
const skLeafObj = KeyObject.from(leafKeys.privateKey); const skLeafObj = KeyObject.from(leafKeys.privateKey);
const skLeaf = skLeafObj.export({ format: "pem", type: "pkcs8" }) as string; const skLeaf = skLeafObj.export({ format: "pem", type: "pkcs8" }) as string;
const { cipherTextBlob: encryptedCertificate } = await kmsService.encrypt({ const kmsEncryptor = await kmsService.encryptWithKmsKey({
kmsId: keyId, kmsId: certificateManagerKmsId
});
const { cipherTextBlob: encryptedCertificate } = kmsEncryptor({
plainText: Buffer.from(new Uint8Array(leafCert.rawData)) plainText: Buffer.from(new Uint8Array(leafCert.rawData))
}); });

View File

@@ -95,7 +95,7 @@ export type TGetCaCredentialsDTO = {
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">; certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">;
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">; certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">; projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
kmsService: Pick<TKmsServiceFactory, "decrypt" | "generateKmsKey">; kmsService: Pick<TKmsServiceFactory, "decryptWithKmsKey" | "generateKmsKey">;
}; };
export type TGetCaCertChainDTO = { export type TGetCaCertChainDTO = {
@@ -103,7 +103,7 @@ export type TGetCaCertChainDTO = {
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">; certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">;
certificateAuthorityCertDAL: Pick<TCertificateAuthorityCertDALFactory, "findOne">; certificateAuthorityCertDAL: Pick<TCertificateAuthorityCertDALFactory, "findOne">;
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">; projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
kmsService: Pick<TKmsServiceFactory, "decrypt" | "generateKmsKey">; kmsService: Pick<TKmsServiceFactory, "decryptWithKmsKey" | "generateKmsKey">;
}; };
export type TRebuildCaCrlDTO = { export type TRebuildCaCrlDTO = {
@@ -113,7 +113,7 @@ export type TRebuildCaCrlDTO = {
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">; certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">; projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
certificateDAL: Pick<TCertificateDALFactory, "find">; certificateDAL: Pick<TCertificateDALFactory, "find">;
kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "decrypt" | "encrypt">; kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "decryptWithKmsKey" | "encryptWithKmsKey">;
}; };
export type TRotateCaCrlTriggerDTO = { export type TRotateCaCrlTriggerDTO = {

View File

@@ -25,7 +25,7 @@ type TCertificateServiceFactoryDep = {
certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "update">; certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "update">;
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">; certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "findById" | "transaction">; projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "findById" | "transaction">;
kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "encrypt" | "decrypt">; kmsService: Pick<TKmsServiceFactory, "generateKmsKey" | "encryptWithKmsKey" | "decryptWithKmsKey">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">; permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
}; };
@@ -164,14 +164,16 @@ export const certificateServiceFactory = ({
const certBody = await certificateBodyDAL.findOne({ certId: cert.id }); const certBody = await certificateBodyDAL.findOne({ certId: cert.id });
const keyId = await getProjectKmsCertificateKeyId({ const certificateManagerKeyId = await getProjectKmsCertificateKeyId({
projectId: ca.projectId, projectId: ca.projectId,
projectDAL, projectDAL,
kmsService kmsService
}); });
const decryptedCert = await kmsService.decrypt({ const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: keyId, kmsId: certificateManagerKeyId
});
const decryptedCert = kmsDecryptor({
cipherTextBlob: certBody.encryptedCertificate cipherTextBlob: certBody.encryptedCertificate
}); });

View File

@@ -14,7 +14,13 @@ import { TProjectDALFactory } from "../project/project-dal";
import { TInternalKmsDALFactory } from "./internal-kms-dal"; import { TInternalKmsDALFactory } from "./internal-kms-dal";
import { TKmsKeyDALFactory } from "./kms-key-dal"; import { TKmsKeyDALFactory } from "./kms-key-dal";
import { TKmsRootConfigDALFactory } from "./kms-root-config-dal"; import { TKmsRootConfigDALFactory } from "./kms-root-config-dal";
import { EncryptionMode, TGenerateKMSDTO, TKmsServiceDecryptionDTO, TKmsServiceEncryptionDTO } from "./kms-types"; import {
TDecryptWithKeyDTO,
TDecryptWithKmsDTO,
TEncryptionWithKeyDTO,
TEncryptWithKmsDTO,
TGenerateKMSDTO
} from "./kms-types";
type TKmsServiceFactoryDep = { type TKmsServiceFactoryDep = {
kmsDAL: TKmsKeyDALFactory; kmsDAL: TKmsKeyDALFactory;
@@ -74,64 +80,55 @@ export const kmsServiceFactory = ({
return doc; return doc;
}; };
/* const encryptWithKmsKey = async ({ kmsId }: Omit<TEncryptWithKmsDTO, "plainText">) => {
* KMS encryption service const kmsDoc = await kmsDAL.findByIdWithAssociatedKms(kmsId);
* Function to handle various kinds of encryption like if (!kmsDoc) throw new BadRequestError({ message: "KMS ID not found" });
* Normal encryption
* Encrypt with KMS key - internal or external
*/
const encrypt = async (encryptionDetails: TKmsServiceEncryptionDTO) => {
// akhilmhdh: as more encryption are added do a check here on kmsDoc.encryptionAlgorithm // akhilmhdh: as more encryption are added do a check here on kmsDoc.encryptionAlgorithm
const cipher = symmetricCipherService(SymmetricEncryption.AES_GCM_256); const cipher = symmetricCipherService(SymmetricEncryption.AES_GCM_256);
// instead of using kms key encrypt with the provided key return ({ plainText }: Pick<TEncryptWithKmsDTO, "plainText">) => {
if (encryptionDetails.type === EncryptionMode.EncryptionKey) { const kmsKey = cipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY);
const { plainText, encryptionKey } = encryptionDetails; const encryptedPlainTextBlob = cipher.encrypt(plainText, kmsKey);
const encryptedPlainTextBlob = cipher.encrypt(plainText, encryptionKey);
// Buffer#1 encrypted text + Buffer#2 version number // Buffer#1 encrypted text + Buffer#2 version number
const versionBlob = Buffer.from(KMS_VERSION, "utf8"); // length is 3 const versionBlob = Buffer.from(KMS_VERSION, "utf8"); // length is 3
const cipherTextBlob = Buffer.concat([encryptedPlainTextBlob, versionBlob]); const cipherTextBlob = Buffer.concat([encryptedPlainTextBlob, versionBlob]);
return { cipherTextBlob }; return { cipherTextBlob };
} };
// this mean use kms to encrypt it
const { plainText, kmsId } = encryptionDetails;
const kmsDoc = await kmsDAL.findByIdWithAssociatedKms(kmsId);
if (!kmsDoc) throw new BadRequestError({ message: "KMS ID not found" });
const kmsKey = cipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY);
const encryptedPlainTextBlob = cipher.encrypt(plainText, kmsKey);
// Buffer#1 encrypted text + Buffer#2 version number
const versionBlob = Buffer.from(KMS_VERSION, "utf8"); // length is 3
const cipherTextBlob = Buffer.concat([encryptedPlainTextBlob, versionBlob]);
return { cipherTextBlob };
}; };
/* const encryptWithInputKey = async ({ key }: Omit<TEncryptionWithKeyDTO, "plainText">) => {
* KMS decryption service
* Function to handle various kinds of decryptionlike
* Normal decryption with a key
* Encrypt with KMS key - internal or external
*/
const decrypt = async (encryptionDetails: TKmsServiceDecryptionDTO) => {
// akhilmhdh: as more encryption are added do a check here on kmsDoc.encryptionAlgorithm // akhilmhdh: as more encryption are added do a check here on kmsDoc.encryptionAlgorithm
const cipher = symmetricCipherService(SymmetricEncryption.AES_GCM_256); const cipher = symmetricCipherService(SymmetricEncryption.AES_GCM_256);
if (encryptionDetails.type === EncryptionMode.EncryptionKey) { return ({ plainText }: Pick<TEncryptWithKmsDTO, "plainText">) => {
const { cipherTextBlob: versionedCipherTextBlob, encryptionKey } = encryptionDetails; const encryptedPlainTextBlob = cipher.encrypt(plainText, key);
const cipherTextBlob = versionedCipherTextBlob.subarray(0, -KMS_VERSION_BLOB_LENGTH); // Buffer#1 encrypted text + Buffer#2 version number
const decryptedBlob = cipher.decrypt(cipherTextBlob, encryptionKey); const versionBlob = Buffer.from(KMS_VERSION, "utf8"); // length is 3
return decryptedBlob; const cipherTextBlob = Buffer.concat([encryptedPlainTextBlob, versionBlob]);
} return { cipherTextBlob };
};
};
const { cipherTextBlob: versionedCipherTextBlob, kmsId } = encryptionDetails; const decryptWithKmsKey = async ({ kmsId }: Omit<TDecryptWithKmsDTO, "cipherTextBlob">) => {
const kmsDoc = await kmsDAL.findByIdWithAssociatedKms(kmsId); const kmsDoc = await kmsDAL.findByIdWithAssociatedKms(kmsId);
if (!kmsDoc) throw new BadRequestError({ message: "KMS ID not found" }); if (!kmsDoc) throw new BadRequestError({ message: "KMS ID not found" });
const cipher = symmetricCipherService(SymmetricEncryption.AES_GCM_256);
const kmsKey = cipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY); const kmsKey = cipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY);
const cipherTextBlob = versionedCipherTextBlob.subarray(0, -KMS_VERSION_BLOB_LENGTH); return ({ cipherTextBlob: versionedCipherTextBlob }: Pick<TDecryptWithKmsDTO, "cipherTextBlob">) => {
const decryptedBlob = cipher.decrypt(cipherTextBlob, kmsKey); const cipherTextBlob = versionedCipherTextBlob.subarray(0, -KMS_VERSION_BLOB_LENGTH);
return decryptedBlob; const decryptedBlob = cipher.decrypt(cipherTextBlob, kmsKey);
return decryptedBlob;
};
};
const decryptWithInputKey = async ({ key }: Omit<TDecryptWithKeyDTO, "cipherTextBlob">) => {
const cipher = symmetricCipherService(SymmetricEncryption.AES_GCM_256);
return ({ cipherTextBlob: versionedCipherTextBlob }: Pick<TDecryptWithKeyDTO, "cipherTextBlob">) => {
const cipherTextBlob = versionedCipherTextBlob.subarray(0, -KMS_VERSION_BLOB_LENGTH);
const decryptedBlob = cipher.decrypt(cipherTextBlob, key);
return decryptedBlob;
};
}; };
const getOrgKmsKeyId = async (orgId: string) => { const getOrgKmsKeyId = async (orgId: string) => {
@@ -246,8 +243,10 @@ export const kmsServiceFactory = ({
return { return {
startService, startService,
generateKmsKey, generateKmsKey,
encrypt, encryptWithKmsKey,
decrypt, encryptWithInputKey,
decryptWithKmsKey,
decryptWithInputKey,
getOrgKmsKeyId, getOrgKmsKeyId,
getProjectSecretManagerKmsKeyId getProjectSecretManagerKmsKeyId
}; };

View File

@@ -7,35 +7,22 @@ export type TGenerateKMSDTO = {
tx?: Knex; tx?: Knex;
}; };
export enum EncryptionMode {
KMS = "kms",
EncryptionKey = "encryption-key"
}
export type TEncryptWithKmsDTO = { export type TEncryptWithKmsDTO = {
type?: EncryptionMode.KMS;
kmsId: string; kmsId: string;
plainText: Buffer; plainText: Buffer;
}; };
export type TEncryptionWithKeyDTO = { export type TEncryptionWithKeyDTO = {
type: EncryptionMode.EncryptionKey; key: Buffer;
encryptionKey: Buffer;
plainText: Buffer; plainText: Buffer;
}; };
export type TKmsServiceEncryptionDTO = TEncryptWithKmsDTO | TEncryptionWithKeyDTO;
export type TDecryptWithKmsDTO = { export type TDecryptWithKmsDTO = {
type?: EncryptionMode.KMS;
kmsId: string; kmsId: string;
cipherTextBlob: Buffer; cipherTextBlob: Buffer;
}; };
export type TDecryptWithEncryptionKeyDTO = { export type TDecryptWithKeyDTO = {
type: EncryptionMode.EncryptionKey; key: Buffer;
encryptionKey: Buffer;
cipherTextBlob: Buffer; cipherTextBlob: Buffer;
}; };
export type TKmsServiceDecryptionDTO = TDecryptWithKmsDTO | TDecryptWithEncryptionKeyDTO;