diff --git a/backend/src/db/migrations/20250402000941_add-type-to-kms-keys.ts b/backend/src/db/migrations/20250402000941_add-type-to-kms-keys.ts index ecc4b9d3b..fd99938db 100644 --- a/backend/src/db/migrations/20250402000941_add-type-to-kms-keys.ts +++ b/backend/src/db/migrations/20250402000941_add-type-to-kms-keys.ts @@ -1,6 +1,6 @@ import { Knex } from "knex"; -import { KmsKeyIntent } from "@app/services/kms/kms-types"; +import { KmsKeyUsage } from "@app/services/kms/kms-types"; import { TableName } from "../schemas"; @@ -8,12 +8,12 @@ export async function up(knex: Knex): Promise { const hasTypeColumn = await knex.schema.hasColumn(TableName.KmsKey, "type"); await knex.schema.alterTable(TableName.KmsKey, (t) => { - if (!hasTypeColumn) t.string("type").notNullable().defaultTo(KmsKeyIntent.ENCRYPT_DECRYPT); + if (!hasTypeColumn) t.string("keyUsage").notNullable().defaultTo(KmsKeyUsage.ENCRYPT_DECRYPT); }); } export async function down(knex: Knex): Promise { await knex.schema.alterTable(TableName.KmsKey, (t) => { - t.dropColumn("type"); + t.dropColumn("keyUsage"); }); } diff --git a/backend/src/db/schemas/kms-keys.ts b/backend/src/db/schemas/kms-keys.ts index a15b12d11..ccb779d57 100644 --- a/backend/src/db/schemas/kms-keys.ts +++ b/backend/src/db/schemas/kms-keys.ts @@ -17,7 +17,7 @@ export const KmsKeysSchema = z.object({ createdAt: z.date(), updatedAt: z.date(), projectId: z.string().nullable().optional(), - type: z.string().default("encrypt-decrypt") + keyUsage: z.string().default("encrypt-decrypt") }); export type TKmsKeys = z.infer; diff --git a/backend/src/ee/routes/v1/kmip-spec-router.ts b/backend/src/ee/routes/v1/kmip-spec-router.ts index 2980f8de9..9a1f4902c 100644 --- a/backend/src/ee/routes/v1/kmip-spec-router.ts +++ b/backend/src/ee/routes/v1/kmip-spec-router.ts @@ -2,7 +2,7 @@ import z from "zod"; import { KmsKeysSchema } from "@app/db/schemas"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; -import { SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; +import { SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher"; import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { writeLimit } from "@app/server/config/rateLimiter"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; @@ -74,7 +74,7 @@ export const registerKmipSpecRouter = async (server: FastifyZodProvider) => { schema: { description: "KMIP endpoint for creating managed objects", body: z.object({ - algorithm: z.nativeEnum(SymmetricKeyEncryptDecrypt) + algorithm: z.nativeEnum(SymmetricKeyAlgorithm) }), response: { 200: KmsKeysSchema @@ -433,7 +433,7 @@ export const registerKmipSpecRouter = async (server: FastifyZodProvider) => { body: z.object({ key: z.string(), name: z.string(), - algorithm: z.nativeEnum(SymmetricKeyEncryptDecrypt) + algorithm: z.nativeEnum(SymmetricKeyAlgorithm) }), response: { 200: z.object({ diff --git a/backend/src/ee/services/audit-log/audit-log-types.ts b/backend/src/ee/services/audit-log/audit-log-types.ts index e1d90e1fa..11904a48b 100644 --- a/backend/src/ee/services/audit-log/audit-log-types.ts +++ b/backend/src/ee/services/audit-log/audit-log-types.ts @@ -4,8 +4,8 @@ import { } from "@app/ee/services/project-template/project-template-types"; import { SshCaStatus, SshCertType } from "@app/ee/services/ssh/ssh-certificate-authority-types"; import { SshCertTemplateStatus } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-types"; -import { SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; -import { AsymmetricKeySignVerify, SigningAlgorithm } from "@app/lib/crypto/sign/types"; +import { SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher"; +import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign/types"; import { TProjectPermission } from "@app/lib/types"; import { AppConnection } from "@app/services/app-connection/app-connection-enums"; import { TCreateAppConnectionDTO, TUpdateAppConnectionDTO } from "@app/services/app-connection/app-connection-types"; @@ -1903,7 +1903,7 @@ interface CreateCmekEvent { keyId: string; name: string; description?: string; - encryptionAlgorithm: SymmetricKeyEncryptDecrypt | AsymmetricKeySignVerify; + encryptionAlgorithm: SymmetricKeyAlgorithm | AsymmetricKeyAlgorithm; }; } 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 d9039a7f0..49ac293ed 100644 --- a/backend/src/ee/services/external-kms/external-kms-service.ts +++ b/backend/src/ee/services/external-kms/external-kms-service.ts @@ -7,7 +7,7 @@ import { BadRequestError, InternalServerError, NotFoundError } from "@app/lib/er import { alphaNumericNanoId } from "@app/lib/nanoid"; import { TKmsKeyDALFactory } from "@app/services/kms/kms-key-dal"; import { TKmsServiceFactory } from "@app/services/kms/kms-service"; -import { KmsDataKey, KmsKeyIntent } from "@app/services/kms/kms-types"; +import { KmsDataKey, KmsKeyUsage } from "@app/services/kms/kms-types"; import { TLicenseServiceFactory } from "../license/license-service"; import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission"; @@ -115,7 +115,7 @@ export const externalKmsServiceFactory = ({ { isReserved: false, description, - type: KmsKeyIntent.ENCRYPT_DECRYPT, + keyUsage: KmsKeyUsage.ENCRYPT_DECRYPT, name: kmsName, orgId: actorOrgId }, diff --git a/backend/src/ee/services/kmip/kmip-operation-service.ts b/backend/src/ee/services/kmip/kmip-operation-service.ts index bf976401c..45f201498 100644 --- a/backend/src/ee/services/kmip/kmip-operation-service.ts +++ b/backend/src/ee/services/kmip/kmip-operation-service.ts @@ -3,7 +3,7 @@ import { ForbiddenError } from "@casl/ability"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { TKmsKeyDALFactory } from "@app/services/kms/kms-key-dal"; import { TKmsServiceFactory } from "@app/services/kms/kms-service"; -import { KmsKeyIntent } from "@app/services/kms/kms-types"; +import { KmsKeyUsage } from "@app/services/kms/kms-types"; import { TProjectDALFactory } from "@app/services/project/project-dal"; import { OrgPermissionKmipActions, OrgPermissionSubjects } from "../permission/org-permission"; @@ -404,7 +404,7 @@ export const kmipOperationServiceFactory = ({ algorithm, isReserved: false, projectId, - type: KmsKeyIntent.ENCRYPT_DECRYPT, + keyUsage: KmsKeyUsage.ENCRYPT_DECRYPT, orgId: project.orgId }); diff --git a/backend/src/ee/services/kmip/kmip-types.ts b/backend/src/ee/services/kmip/kmip-types.ts index 27f9e0bb6..81d0d8766 100644 --- a/backend/src/ee/services/kmip/kmip-types.ts +++ b/backend/src/ee/services/kmip/kmip-types.ts @@ -1,4 +1,4 @@ -import { SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; +import { SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher"; import { OrderByDirection, TOrgPermission, TProjectPermission } from "@app/lib/types"; import { CertKeyAlgorithm } from "@app/services/certificate/certificate-types"; @@ -49,7 +49,7 @@ type KmipOperationBaseDTO = { } & Omit; export type TKmipCreateDTO = { - algorithm: SymmetricKeyEncryptDecrypt; + algorithm: SymmetricKeyAlgorithm; } & KmipOperationBaseDTO; export type TKmipGetDTO = { @@ -77,7 +77,7 @@ export type TKmipLocateDTO = KmipOperationBaseDTO; export type TKmipRegisterDTO = { name: string; key: string; - algorithm: SymmetricKeyEncryptDecrypt; + algorithm: SymmetricKeyAlgorithm; } & KmipOperationBaseDTO; export type TSetupOrgKmipDTO = { diff --git a/backend/src/lib/crypto/cipher/cipher.ts b/backend/src/lib/crypto/cipher/cipher.ts index 82cd9a2d1..718c8ad5e 100644 --- a/backend/src/lib/crypto/cipher/cipher.ts +++ b/backend/src/lib/crypto/cipher/cipher.ts @@ -1,6 +1,6 @@ import crypto from "crypto"; -import { SymmetricKeyEncryptDecrypt, TSymmetricEncryptionFns } from "./types"; +import { SymmetricKeyAlgorithm, TSymmetricEncryptionFns } from "./types"; const getIvLength = () => { return 12; @@ -11,7 +11,7 @@ const getTagLength = () => { }; export const symmetricCipherService = ( - type: SymmetricKeyEncryptDecrypt.AES_GCM_128 | SymmetricKeyEncryptDecrypt.AES_GCM_256 + type: SymmetricKeyAlgorithm.AES_GCM_128 | SymmetricKeyAlgorithm.AES_GCM_256 ): TSymmetricEncryptionFns => { const IV_LENGTH = getIvLength(); const TAG_LENGTH = getTagLength(); diff --git a/backend/src/lib/crypto/cipher/index.ts b/backend/src/lib/crypto/cipher/index.ts index 755f8aa00..27373a009 100644 --- a/backend/src/lib/crypto/cipher/index.ts +++ b/backend/src/lib/crypto/cipher/index.ts @@ -1,2 +1,2 @@ export { symmetricCipherService } from "./cipher"; -export { AllowedEncryptionKeyAlgorithms, SymmetricKeyEncryptDecrypt } from "./types"; +export { AllowedEncryptionKeyAlgorithms, SymmetricKeyAlgorithm } from "./types"; diff --git a/backend/src/lib/crypto/cipher/types.ts b/backend/src/lib/crypto/cipher/types.ts index c8dbf11cd..e2f63ce5e 100644 --- a/backend/src/lib/crypto/cipher/types.ts +++ b/backend/src/lib/crypto/cipher/types.ts @@ -1,19 +1,17 @@ import { z } from "zod"; -import { AsymmetricKeySignVerify } from "../sign/types"; +import { AsymmetricKeyAlgorithm } from "../sign/types"; // Supported symmetric encrypt/decrypt algorithms -export enum SymmetricKeyEncryptDecrypt { +export enum SymmetricKeyAlgorithm { AES_GCM_256 = "aes-256-gcm", AES_GCM_128 = "aes-128-gcm" } -export const SymmetricKeyEncryptDecryptEnum = z.enum( - Object.values(SymmetricKeyEncryptDecrypt) as [string, ...string[]] -).options; +export const SymmetricKeyAlgorithmEnum = z.enum(Object.values(SymmetricKeyAlgorithm) as [string, ...string[]]).options; export const AllowedEncryptionKeyAlgorithms = z.enum([ - ...Object.values(SymmetricKeyEncryptDecrypt), - ...Object.values(AsymmetricKeySignVerify) + ...Object.values(SymmetricKeyAlgorithm), + ...Object.values(AsymmetricKeyAlgorithm) ] as [string, ...string[]]).options; export type TSymmetricEncryptionFns = { diff --git a/backend/src/lib/crypto/sign/index.ts b/backend/src/lib/crypto/sign/index.ts index 372f10c64..5680cd27a 100644 --- a/backend/src/lib/crypto/sign/index.ts +++ b/backend/src/lib/crypto/sign/index.ts @@ -1,2 +1,2 @@ export { signingService } from "./signing"; -export { AsymmetricKeySignVerify, SigningAlgorithm } from "./types"; +export { AsymmetricKeyAlgorithm, SigningAlgorithm } from "./types"; diff --git a/backend/src/lib/crypto/sign/signing.ts b/backend/src/lib/crypto/sign/signing.ts index 5431c28ff..2156d1159 100644 --- a/backend/src/lib/crypto/sign/signing.ts +++ b/backend/src/lib/crypto/sign/signing.ts @@ -3,7 +3,7 @@ import crypto from "crypto"; import { BadRequestError } from "@app/lib/errors"; import { logger } from "@app/lib/logger"; -import { AsymmetricKeySignVerify, SigningAlgorithm, TAsymmetricSignVerifyFns } from "./types"; +import { AsymmetricKeyAlgorithm, SigningAlgorithm, TAsymmetricSignVerifyFns } from "./types"; // Map of signing algorithms to their parameters interface SigningParams { @@ -22,7 +22,7 @@ const SHA512_DIGEST_LENGTH = 64; * @param algorithm The signing algorithm to use * @returns Object with sign and verify functions */ -export const signingService = (algorithm: AsymmetricKeySignVerify): TAsymmetricSignVerifyFns => { +export const signingService = (algorithm: AsymmetricKeyAlgorithm): TAsymmetricSignVerifyFns => { const $getSigningParams = (signingAlgorithm: SigningAlgorithm): SigningParams => { switch (signingAlgorithm) { // RSA PSS @@ -76,10 +76,10 @@ export const signingService = (algorithm: AsymmetricKeySignVerify): TAsymmetricS }; // For ECC key generation, nodejs has some strange and hardly documented curve naming conventions - const $getEcCurveName = (keyAlgorithm: AsymmetricKeySignVerify): string => { + const $getEcCurveName = (keyAlgorithm: AsymmetricKeyAlgorithm): string => { // We will support more in the future switch (keyAlgorithm) { - case AsymmetricKeySignVerify.ECC_NIST_P256: + case AsymmetricKeyAlgorithm.ECC_NIST_P256: return "prime256v1"; default: throw new Error(`Unsupported EC curve: ${keyAlgorithm}`); @@ -172,7 +172,6 @@ export const signingService = (algorithm: AsymmetricKeySignVerify): TAsymmetricS type: "pkcs8" }); - // Return public key in PEM format for both RSA and EC const publicKey = crypto.createPublicKey(privateKeyObj).export({ type: "spki", format: "pem" @@ -210,7 +209,8 @@ export const signingService = (algorithm: AsymmetricKeySignVerify): TAsymmetricS } // For PKCS1 v1.5 padding return signer.sign({ - key: privateKeyObject + key: privateKeyObject, + padding }); } if (signingAlgorithm.startsWith("ECDSA")) { @@ -252,7 +252,8 @@ export const signingService = (algorithm: AsymmetricKeySignVerify): TAsymmetricS // For PKCS1 v1.5 padding return verifier.verify( { - key: publicKey.toString() + key: publicKey.toString(), + padding }, signature ); diff --git a/backend/src/lib/crypto/sign/types.ts b/backend/src/lib/crypto/sign/types.ts index 6f1922d38..2f99f6d70 100644 --- a/backend/src/lib/crypto/sign/types.ts +++ b/backend/src/lib/crypto/sign/types.ts @@ -8,13 +8,13 @@ export type TAsymmetricSignVerifyFns = { }; // Supported asymmetric key types -export enum AsymmetricKeySignVerify { +export enum AsymmetricKeyAlgorithm { RSA_4096 = "rsa-4096", ECC_NIST_P256 = "ecc-nist-p256" } -export const AsymmetricKeySignVerifyEnum = z.enum( - Object.values(AsymmetricKeySignVerify) as [string, ...string[]] +export const AsymmetricKeyAlgorithmEnum = z.enum( + Object.values(AsymmetricKeyAlgorithm) as [string, ...string[]] ).options; export enum SigningAlgorithm { diff --git a/backend/src/server/routes/v1/cmek-router.ts b/backend/src/server/routes/v1/cmek-router.ts index 8d58fc2e1..5de731390 100644 --- a/backend/src/server/routes/v1/cmek-router.ts +++ b/backend/src/server/routes/v1/cmek-router.ts @@ -4,22 +4,20 @@ import { InternalKmsSchema, KmsKeysSchema } from "@app/db/schemas"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { KMS } from "@app/lib/api-docs"; import { getBase64SizeInBytes, isBase64 } from "@app/lib/base64"; -import { AllowedEncryptionKeyAlgorithms, SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; -import { AsymmetricKeySignVerify, SigningAlgorithm } from "@app/lib/crypto/sign"; +import { AllowedEncryptionKeyAlgorithms, SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher"; +import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign"; import { OrderByDirection } from "@app/lib/types"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { slugSchema } from "@app/server/lib/schemas"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; import { CmekOrderBy, TCmekKeyEncryptionAlgorithm } from "@app/services/cmek/cmek-types"; -import { KmsKeyIntent } from "@app/services/kms/kms-types"; +import { KmsKeyUsage } from "@app/services/kms/kms-types"; const keyNameSchema = slugSchema({ min: 1, max: 32, field: "Name" }); const keyDescriptionSchema = z.string().trim().max(500).optional(); -const CmekSchema = KmsKeysSchema.merge( - InternalKmsSchema.pick({ version: true, encryptionAlgorithm: true, type: true }) -).omit({ +const CmekSchema = KmsKeysSchema.merge(InternalKmsSchema.pick({ version: true, encryptionAlgorithm: true })).omit({ isReserved: true }); @@ -54,37 +52,37 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { projectId: z.string().describe(KMS.CREATE_KEY.projectId), name: keyNameSchema.describe(KMS.CREATE_KEY.name), description: keyDescriptionSchema.describe(KMS.CREATE_KEY.description), - type: z - .nativeEnum(KmsKeyIntent) + keyUsage: z + .nativeEnum(KmsKeyUsage) .optional() - .default(KmsKeyIntent.ENCRYPT_DECRYPT) + .default(KmsKeyUsage.ENCRYPT_DECRYPT) .describe(KMS.CREATE_KEY.type), encryptionAlgorithm: z .enum(AllowedEncryptionKeyAlgorithms) .optional() - .default(SymmetricKeyEncryptDecrypt.AES_GCM_256) + .default(SymmetricKeyAlgorithm.AES_GCM_256) .describe(KMS.CREATE_KEY.encryptionAlgorithm) }) .superRefine((data, ctx) => { if ( - data.type === KmsKeyIntent.ENCRYPT_DECRYPT && - !Object.values(SymmetricKeyEncryptDecrypt).includes(data.encryptionAlgorithm as SymmetricKeyEncryptDecrypt) + data.keyUsage === KmsKeyUsage.ENCRYPT_DECRYPT && + !Object.values(SymmetricKeyAlgorithm).includes(data.encryptionAlgorithm as SymmetricKeyAlgorithm) ) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: `encryptionAlgorithm must be a valid symmetric encryption algorithm. Valid options are: ${Object.values( - SymmetricKeyEncryptDecrypt + SymmetricKeyAlgorithm ).join(", ")}` }); } if ( - data.type === KmsKeyIntent.SIGN_VERIFY && - !Object.values(AsymmetricKeySignVerify).includes(data.encryptionAlgorithm as AsymmetricKeySignVerify) + data.keyUsage === KmsKeyUsage.SIGN_VERIFY && + !Object.values(AsymmetricKeyAlgorithm).includes(data.encryptionAlgorithm as AsymmetricKeyAlgorithm) ) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: `encryptionAlgorithm must be a valid asymmetric sign-verify algorithm. Valid options are: ${Object.values( - AsymmetricKeySignVerify + AsymmetricKeyAlgorithm ).join(", ")}` }); } @@ -98,7 +96,7 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { const { - body: { projectId, name, description, encryptionAlgorithm, type }, + body: { projectId, name, description, encryptionAlgorithm, keyUsage }, permission } = req; @@ -109,7 +107,7 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { name, description, encryptionAlgorithm: encryptionAlgorithm as TCmekKeyEncryptionAlgorithm, - type + keyUsage }, permission ); @@ -167,7 +165,7 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, - orgId: permission.orgId, + projectId: cmek.projectId!, event: { type: EventType.UPDATE_CMEK, metadata: { @@ -210,7 +208,7 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, - orgId: permission.orgId, + projectId: cmek.projectId!, event: { type: EventType.DELETE_CMEK, metadata: { @@ -390,11 +388,11 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { permission } = req; - const ciphertext = await server.services.cmek.cmekEncrypt({ keyId, plaintext }, permission); + const { ciphertext, projectId } = await server.services.cmek.cmekEncrypt({ keyId, plaintext }, permission); await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, - orgId: permission.orgId, + projectId, event: { type: EventType.CMEK_ENCRYPT, metadata: { @@ -431,11 +429,11 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { permission } = req; - const publicKey = await server.services.cmek.getPublicKey({ keyId }, permission); + const { publicKey, projectId } = await server.services.cmek.getPublicKey({ keyId }, permission); await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, - orgId: permission.orgId, + projectId, event: { type: EventType.CMEK_GET_PUBLIC_KEY, metadata: { @@ -444,7 +442,7 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { } }); - return publicKey; + return { publicKey }; } }); @@ -469,11 +467,14 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { handler: async (req) => { const { keyId } = req.params; - const result = await server.services.cmek.listSigningAlgorithms({ keyId }, req.permission); + const { signingAlgorithms, projectId } = await server.services.cmek.listSigningAlgorithms( + { keyId }, + req.permission + ); await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, - orgId: req.permission.orgId, + projectId, event: { type: EventType.CMEK_LIST_SIGNING_ALGORITHMS, metadata: { @@ -482,7 +483,7 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { } }); - return result; + return { signingAlgorithms }; } }); @@ -527,11 +528,14 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { permission } = req; - const result = await server.services.cmek.cmekSign({ keyId: inputKeyId, data, signingAlgorithm }, permission); + const { projectId, ...result } = await server.services.cmek.cmekSign( + { keyId: inputKeyId, data, signingAlgorithm }, + permission + ); await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, - orgId: permission.orgId, + projectId, event: { type: EventType.CMEK_SIGN, metadata: { @@ -597,11 +601,14 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { permission } = req; - const result = await server.services.cmek.cmekVerify({ keyId, data, signature, signingAlgorithm }, permission); + const { projectId, ...result } = await server.services.cmek.cmekVerify( + { keyId, data, signature, signingAlgorithm }, + permission + ); await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, - orgId: permission.orgId, + projectId, event: { type: EventType.CMEK_VERIFY, metadata: { @@ -645,11 +652,11 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => { permission } = req; - const plaintext = await server.services.cmek.cmekDecrypt({ keyId, ciphertext }, permission); + const { plaintext, projectId } = await server.services.cmek.cmekDecrypt({ keyId, ciphertext }, permission); await server.services.auditLog.createAuditLog({ ...req.auditLogInfo, - orgId: permission.orgId, + projectId, event: { type: EventType.CMEK_DECRYPT, metadata: { diff --git a/backend/src/services/cmek/cmek-service.ts b/backend/src/services/cmek/cmek-service.ts index 395018e55..a708e8315 100644 --- a/backend/src/services/cmek/cmek-service.ts +++ b/backend/src/services/cmek/cmek-service.ts @@ -22,7 +22,7 @@ import { import { TKmsKeyDALFactory } from "@app/services/kms/kms-key-dal"; import { TKmsServiceFactory } from "@app/services/kms/kms-service"; -import { KmsKeyIntent } from "../kms/kms-types"; +import { KmsKeyUsage } from "../kms/kms-types"; import { TProjectDALFactory } from "../project/project-dal"; type TCmekServiceFactoryDep = { @@ -228,7 +228,10 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj const { cipherTextBlob } = await encrypt({ plainText: Buffer.from(plaintext, "base64") }); - return cipherTextBlob.toString("base64"); + return { + ciphertext: cipherTextBlob.toString("base64"), + projectId: key.projectId + }; }; const listSigningAlgorithms = async ({ keyId }: TCmekListSigningAlgorithmsDTO, actor: OrgServiceActor) => { @@ -249,7 +252,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek); - if (key.type !== KmsKeyIntent.SIGN_VERIFY) { + if (key.keyUsage !== KmsKeyUsage.SIGN_VERIFY) { throw new BadRequestError({ message: `Key with ID '${keyId}' is not intended for signing` }); } @@ -276,7 +279,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj throw new BadRequestError({ message: `Unsupported encryption algorithm: ${encryptionAlgorithm}` }); } - return { signingAlgorithms: selectedAlgorithm.signingAlgorithms }; + return { signingAlgorithms: selectedAlgorithm.signingAlgorithms, projectId: key.projectId }; }; const getPublicKey = async ({ keyId }: TCmekGetPublicKeyDTO, actor: OrgServiceActor) => { @@ -299,7 +302,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj const publicKey = await kmsService.getPublicKey({ kmsId: keyId }); - return { publicKey }; + return { publicKey, projectId: key.projectId }; }; const cmekSign = async ({ keyId, data, signingAlgorithm }: TCmekSignDTO, actor: OrgServiceActor) => { @@ -329,6 +332,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj return { signature: signature.toString("base64"), keyId: key.id, + projectId: key.projectId, signingAlgorithm: algorithm }; }; @@ -363,6 +367,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj return { signatureValid, keyId: key.id, + projectId: key.projectId, signingAlgorithm: algorithm }; }; @@ -391,7 +396,10 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj const plaintextBlob = await decrypt({ cipherTextBlob: Buffer.from(ciphertext, "base64") }); - return plaintextBlob.toString("base64"); + return { + plaintext: plaintextBlob.toString("base64"), + projectId: key.projectId + }; }; return { diff --git a/backend/src/services/cmek/cmek-types.ts b/backend/src/services/cmek/cmek-types.ts index 2d137ba90..6af8c44fc 100644 --- a/backend/src/services/cmek/cmek-types.ts +++ b/backend/src/services/cmek/cmek-types.ts @@ -1,10 +1,10 @@ -import { SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; -import { AsymmetricKeySignVerify, SigningAlgorithm } from "@app/lib/crypto/sign"; +import { SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher"; +import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign"; import { OrderByDirection } from "@app/lib/types"; -import { KmsKeyIntent } from "../kms/kms-types"; +import { KmsKeyUsage } from "../kms/kms-types"; -export type TCmekKeyEncryptionAlgorithm = SymmetricKeyEncryptDecrypt | AsymmetricKeySignVerify; +export type TCmekKeyEncryptionAlgorithm = SymmetricKeyAlgorithm | AsymmetricKeyAlgorithm; export type TCreateCmekDTO = { orgId: string; @@ -12,7 +12,7 @@ export type TCreateCmekDTO = { name: string; description?: string; encryptionAlgorithm: TCmekKeyEncryptionAlgorithm; - type: KmsKeyIntent; + keyUsage: KmsKeyUsage; }; export type TUpdabteCmekByIdDTO = { diff --git a/backend/src/services/kms/kms-fns.ts b/backend/src/services/kms/kms-fns.ts index f0acb8f22..8c7aa13dd 100644 --- a/backend/src/services/kms/kms-fns.ts +++ b/backend/src/services/kms/kms-fns.ts @@ -1,36 +1,36 @@ -import { SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; -import { AsymmetricKeySignVerify } from "@app/lib/crypto/sign"; +import { SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher"; +import { AsymmetricKeyAlgorithm } from "@app/lib/crypto/sign"; import { BadRequestError } from "@app/lib/errors"; -import { KmsKeyIntent } from "./kms-types"; +import { KmsKeyUsage } from "./kms-types"; export const KMS_ROOT_CONFIG_UUID = "00000000-0000-0000-0000-000000000000"; -export const getByteLengthForSymmetricEncryptionAlgorithm = (encryptionAlgorithm: SymmetricKeyEncryptDecrypt) => { +export const getByteLengthForSymmetricEncryptionAlgorithm = (encryptionAlgorithm: SymmetricKeyAlgorithm) => { switch (encryptionAlgorithm) { - case SymmetricKeyEncryptDecrypt.AES_GCM_128: + case SymmetricKeyAlgorithm.AES_GCM_128: return 16; - case SymmetricKeyEncryptDecrypt.AES_GCM_256: + case SymmetricKeyAlgorithm.AES_GCM_256: default: return 32; } }; export const verifyKeyTypeAndAlgorithm = ( - type: KmsKeyIntent, - algorithm: SymmetricKeyEncryptDecrypt | AsymmetricKeySignVerify, + keyUsage: KmsKeyUsage, + algorithm: SymmetricKeyAlgorithm | AsymmetricKeyAlgorithm, extra?: { - forceType?: KmsKeyIntent; + forceType?: KmsKeyUsage; } ) => { - if (extra?.forceType && type !== extra.forceType) { + if (extra?.forceType && keyUsage !== extra.forceType) { throw new BadRequestError({ - message: `Unsupported key type, expected ${extra.forceType} but got ${type}` + message: `Unsupported key type, expected ${extra.forceType} but got ${keyUsage}` }); } - if (type === KmsKeyIntent.ENCRYPT_DECRYPT) { - if (!Object.values(SymmetricKeyEncryptDecrypt).includes(algorithm as SymmetricKeyEncryptDecrypt)) { + if (keyUsage === KmsKeyUsage.ENCRYPT_DECRYPT) { + if (!Object.values(SymmetricKeyAlgorithm).includes(algorithm as SymmetricKeyAlgorithm)) { throw new BadRequestError({ message: `Unsupported encryption algorithm for encrypt/decrypt key: ${algorithm as string}` }); @@ -39,8 +39,8 @@ export const verifyKeyTypeAndAlgorithm = ( return true; } - if (type === KmsKeyIntent.SIGN_VERIFY) { - if (!Object.values(AsymmetricKeySignVerify).includes(algorithm as AsymmetricKeySignVerify)) { + if (keyUsage === KmsKeyUsage.SIGN_VERIFY) { + if (!Object.values(AsymmetricKeyAlgorithm).includes(algorithm as AsymmetricKeyAlgorithm)) { throw new BadRequestError({ message: `Unsupported sign/verify algorithm for sign/verify key: ${algorithm as string}` }); @@ -50,6 +50,6 @@ export const verifyKeyTypeAndAlgorithm = ( } throw new BadRequestError({ - message: `Unsupported key type: ${type as string}` + message: `Unsupported key type: ${keyUsage as string}` }); }; diff --git a/backend/src/services/kms/kms-service.ts b/backend/src/services/kms/kms-service.ts index c7d76d931..dd68bf02e 100644 --- a/backend/src/services/kms/kms-service.ts +++ b/backend/src/services/kms/kms-service.ts @@ -17,9 +17,9 @@ import { THsmServiceFactory } from "@app/ee/services/hsm/hsm-service"; import { KeyStorePrefixes, PgSqlLock, TKeyStoreFactory } from "@app/keystore/keystore"; import { TEnvConfig } from "@app/lib/config/env"; import { randomSecureBytes } from "@app/lib/crypto"; -import { symmetricCipherService, SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; +import { symmetricCipherService, SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher"; import { generateHash } from "@app/lib/crypto/encryption"; -import { AsymmetricKeySignVerify, signingService } from "@app/lib/crypto/sign"; +import { AsymmetricKeyAlgorithm, signingService } from "@app/lib/crypto/sign"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { logger } from "@app/lib/logger"; import { alphaNumericNanoId } from "@app/lib/nanoid"; @@ -36,7 +36,7 @@ import { TKmsKeyDALFactory } from "./kms-key-dal"; import { TKmsRootConfigDALFactory } from "./kms-root-config-dal"; import { KmsDataKey, - KmsKeyIntent, + KmsKeyUsage, KmsType, RootKeyEncryptionStrategy, TDecryptWithKeyDTO, @@ -94,21 +94,21 @@ export const kmsServiceFactory = ({ tx, name, projectId, - encryptionAlgorithm = SymmetricKeyEncryptDecrypt.AES_GCM_256, - type = KmsKeyIntent.ENCRYPT_DECRYPT, + encryptionAlgorithm = SymmetricKeyAlgorithm.AES_GCM_256, + keyUsage = KmsKeyUsage.ENCRYPT_DECRYPT, description }: TGenerateKMSDTO) => { // daniel: ensure that the key type (sign/encrypt) and the encryption algorithm are compatible. - verifyKeyTypeAndAlgorithm(type, encryptionAlgorithm); + verifyKeyTypeAndAlgorithm(keyUsage, encryptionAlgorithm); let kmsKeyMaterial: Buffer | null = null; - if (type === KmsKeyIntent.ENCRYPT_DECRYPT) { + if (keyUsage === KmsKeyUsage.ENCRYPT_DECRYPT) { kmsKeyMaterial = randomSecureBytes( - getByteLengthForSymmetricEncryptionAlgorithm(encryptionAlgorithm as SymmetricKeyEncryptDecrypt) + getByteLengthForSymmetricEncryptionAlgorithm(encryptionAlgorithm as SymmetricKeyAlgorithm) ); - } else if (type === KmsKeyIntent.SIGN_VERIFY) { + } else if (keyUsage === KmsKeyUsage.SIGN_VERIFY) { const { generateAsymmetricPrivateKey, getPublicKeyFromPrivateKey } = signingService( - encryptionAlgorithm as AsymmetricKeySignVerify + encryptionAlgorithm as AsymmetricKeyAlgorithm ); kmsKeyMaterial = await generateAsymmetricPrivateKey(); @@ -118,18 +118,18 @@ export const kmsServiceFactory = ({ if (!kmsKeyMaterial) { throw new BadRequestError({ - message: `Invalid KMS key type. No key material was created for key type '${type}' using algorithm '${encryptionAlgorithm}'` + message: `Invalid KMS key type. No key material was created for key usage '${keyUsage}' using algorithm '${encryptionAlgorithm}'` }); } - const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); const encryptedKeyMaterial = cipher.encrypt(kmsKeyMaterial, ROOT_ENCRYPTION_KEY); const sanitizedName = name ? slugify(name) : slugify(alphaNumericNanoId(8).toLowerCase()); const dbQuery = async (db: Knex) => { const kmsDoc = await kmsDAL.create( { name: sanitizedName, - type, + keyUsage, orgId, isReserved, projectId, @@ -169,7 +169,7 @@ export const kmsServiceFactory = ({ */ const encryptWithInputKey = async ({ key }: Omit) => { // akhilmhdh: as more encryption are added do a check here on kmsDoc.encryptionAlgorithm - const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); return ({ plainText }: Pick) => { const encryptedPlainTextBlob = cipher.encrypt(plainText, key); // Buffer#1 encrypted text + Buffer#2 version number @@ -184,7 +184,7 @@ export const kmsServiceFactory = ({ * This can be even later exposed directly as api for encryption as function */ const decryptWithInputKey = async ({ key }: Omit) => { - const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); return ({ cipherTextBlob: versionedCipherTextBlob }: Pick) => { const cipherTextBlob = versionedCipherTextBlob.subarray(0, -KMS_VERSION_BLOB_LENGTH); @@ -262,7 +262,7 @@ export const kmsServiceFactory = ({ }; const encryptWithRootKey = () => { - const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); return (plainTextBuffer: Buffer) => { const encryptedBuffer = cipher.encrypt(plainTextBuffer, ROOT_ENCRYPTION_KEY); @@ -271,7 +271,7 @@ export const kmsServiceFactory = ({ }; const decryptWithRootKey = () => { - const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); return (cipherTextBuffer: Buffer) => { return cipher.decrypt(cipherTextBuffer, ROOT_ENCRYPTION_KEY); @@ -290,9 +290,9 @@ export const kmsServiceFactory = ({ throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` }); } - const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyEncryptDecrypt; - verifyKeyTypeAndAlgorithm(kmsDoc.type as KmsKeyIntent, encryptionAlgorithm, { - forceType: KmsKeyIntent.ENCRYPT_DECRYPT + const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyAlgorithm; + verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, { + forceType: KmsKeyUsage.ENCRYPT_DECRYPT }); if (kmsDoc.externalKms) { @@ -356,7 +356,7 @@ export const kmsServiceFactory = ({ } // internal KMS - const keyCipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); const dataCipher = symmetricCipherService(encryptionAlgorithm); const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY); @@ -385,22 +385,22 @@ export const kmsServiceFactory = ({ }); } - const keyCipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY); return kmsKey; }; const importKeyMaterial = async ( - { key, algorithm, name, isReserved, projectId, orgId, type }: TImportKeyMaterialDTO, + { key, algorithm, name, isReserved, projectId, orgId, keyUsage }: TImportKeyMaterialDTO, tx?: Knex ) => { // daniel: currently we only support imports for encrypt/decrypt keys - verifyKeyTypeAndAlgorithm(type, algorithm, { forceType: KmsKeyIntent.ENCRYPT_DECRYPT }); + verifyKeyTypeAndAlgorithm(keyUsage, algorithm, { forceType: KmsKeyUsage.ENCRYPT_DECRYPT }); - const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); - const expectedByteLength = getByteLengthForSymmetricEncryptionAlgorithm(algorithm as SymmetricKeyEncryptDecrypt); + const expectedByteLength = getByteLengthForSymmetricEncryptionAlgorithm(algorithm as SymmetricKeyAlgorithm); if (key.byteLength !== expectedByteLength) { throw new BadRequestError({ message: `Invalid key length for ${algorithm}. Expected ${expectedByteLength} bytes but got ${key.byteLength} bytes` @@ -413,7 +413,7 @@ export const kmsServiceFactory = ({ const kmsDoc = await kmsDAL.create( { name: sanitizedName, - type: KmsKeyIntent.ENCRYPT_DECRYPT, + keyUsage: KmsKeyUsage.ENCRYPT_DECRYPT, orgId, isReserved, projectId @@ -443,13 +443,13 @@ export const kmsServiceFactory = ({ throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` }); } - const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as AsymmetricKeySignVerify; + const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as AsymmetricKeyAlgorithm; - verifyKeyTypeAndAlgorithm(kmsDoc.type as KmsKeyIntent, encryptionAlgorithm, { - forceType: KmsKeyIntent.SIGN_VERIFY + verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, { + forceType: KmsKeyUsage.SIGN_VERIFY }); - const keyCipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY); const publicKeyBuffer = signingService(encryptionAlgorithm).getPublicKeyFromPrivateKey(kmsKey); @@ -469,12 +469,12 @@ export const kmsServiceFactory = ({ throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` }); } - const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as AsymmetricKeySignVerify; - verifyKeyTypeAndAlgorithm(kmsDoc.type as KmsKeyIntent, encryptionAlgorithm, { - forceType: KmsKeyIntent.SIGN_VERIFY + const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as AsymmetricKeyAlgorithm; + verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, { + forceType: KmsKeyUsage.SIGN_VERIFY }); - const keyCipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); const { sign } = signingService(encryptionAlgorithm); return ({ data, signingAlgorithm }: Pick) => { const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY); @@ -493,12 +493,12 @@ export const kmsServiceFactory = ({ throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` }); } - const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as AsymmetricKeySignVerify; - verifyKeyTypeAndAlgorithm(kmsDoc.type as KmsKeyIntent, encryptionAlgorithm, { - forceType: KmsKeyIntent.SIGN_VERIFY + const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as AsymmetricKeyAlgorithm; + verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, { + forceType: KmsKeyUsage.SIGN_VERIFY }); - const keyCipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); const { verify, getPublicKeyFromPrivateKey } = signingService(encryptionAlgorithm); return ({ data, signature }: Pick) => { const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY); @@ -515,9 +515,9 @@ export const kmsServiceFactory = ({ throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` }); } - const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyEncryptDecrypt; - verifyKeyTypeAndAlgorithm(kmsDoc.type as KmsKeyIntent, encryptionAlgorithm, { - forceType: KmsKeyIntent.ENCRYPT_DECRYPT + const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyAlgorithm; + verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, { + forceType: KmsKeyUsage.ENCRYPT_DECRYPT }); if (kmsDoc.externalKms) { @@ -575,7 +575,7 @@ export const kmsServiceFactory = ({ } // internal KMS - const keyCipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); const dataCipher = symmetricCipherService(encryptionAlgorithm); return ({ plainText }: Pick) => { const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY); @@ -850,7 +850,7 @@ export const kmsServiceFactory = ({ // case 2: root key is encrypted with software encryption if (kmsRootConfig.encryptionStrategy === RootKeyEncryptionStrategy.Software) { - const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); const encryptionKeyBuffer = $getBasicEncryptionKey(); return cipher.decrypt(kmsRootConfig.encryptedRootKey, encryptionKeyBuffer); @@ -870,7 +870,7 @@ export const kmsServiceFactory = ({ } if (strategy === RootKeyEncryptionStrategy.Software) { - const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); const encryptionKeyBuffer = $getBasicEncryptionKey(); return cipher.encrypt(plainKeyBuffer, encryptionKeyBuffer); @@ -886,7 +886,7 @@ export const kmsServiceFactory = ({ const createCipherPairWithDataKey = async (encryptionContext: TEncryptWithKmsDataKeyDTO, trx?: Knex) => { const dataKey = await $getDataKey(encryptionContext, trx); - const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); + const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256); return { encryptor: ({ plainText }: Pick) => { diff --git a/backend/src/services/kms/kms-types.ts b/backend/src/services/kms/kms-types.ts index 163eedc35..44c1b09c2 100644 --- a/backend/src/services/kms/kms-types.ts +++ b/backend/src/services/kms/kms-types.ts @@ -1,7 +1,7 @@ import { Knex } from "knex"; -import { SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; -import { AsymmetricKeySignVerify, SigningAlgorithm } from "@app/lib/crypto/sign/types"; +import { SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher"; +import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign/types"; export enum KmsDataKey { Organization, @@ -14,7 +14,7 @@ export enum KmsType { Internal = "internal" } -export enum KmsKeyIntent { +export enum KmsKeyUsage { ENCRYPT_DECRYPT = "encrypt-decrypt", SIGN_VERIFY = "sign-verify" } @@ -31,8 +31,8 @@ export type TEncryptWithKmsDataKeyDTO = export type TGenerateKMSDTO = { orgId: string; projectId?: string; - encryptionAlgorithm?: SymmetricKeyEncryptDecrypt | AsymmetricKeySignVerify; - type?: KmsKeyIntent; + encryptionAlgorithm?: SymmetricKeyAlgorithm | AsymmetricKeyAlgorithm; + keyUsage?: KmsKeyUsage; isReserved?: boolean; name?: string; description?: string; @@ -91,10 +91,10 @@ export type TGetKeyMaterialDTO = { export type TImportKeyMaterialDTO = { key: Buffer; - algorithm: SymmetricKeyEncryptDecrypt; + algorithm: SymmetricKeyAlgorithm; name?: string; isReserved: boolean; projectId: string; orgId: string; - type: KmsKeyIntent; + keyUsage: KmsKeyUsage; }; diff --git a/frontend/src/helpers/kms.ts b/frontend/src/helpers/kms.ts index d94434ee8..64b85dc2c 100644 --- a/frontend/src/helpers/kms.ts +++ b/frontend/src/helpers/kms.ts @@ -1,21 +1,17 @@ -import { - AsymmetricKeySignVerify, - KmsKeyIntent, - SymmetricKeyEncryptDecrypt -} from "@app/hooks/api/cmeks"; +import { AsymmetricKeyAlgorithm, KmsKeyUsage, SymmetricKeyAlgorithm } from "@app/hooks/api/cmeks"; export const kmsKeyUsageOptions: Record< - KmsKeyIntent, + KmsKeyUsage, { label: string; tooltip: string; } > = { - [KmsKeyIntent.ENCRYPT_DECRYPT]: { + [KmsKeyUsage.ENCRYPT_DECRYPT]: { label: "Encrypt/Decrypt", tooltip: "Use the key only to encrypt and decrypt data." }, - [KmsKeyIntent.SIGN_VERIFY]: { + [KmsKeyUsage.SIGN_VERIFY]: { label: "Sign/Verify", tooltip: "Key pairs for digital signing. Uses the private key for signing and the public key for verification." @@ -23,9 +19,9 @@ export const kmsKeyUsageOptions: Record< }; export const keyUsageDefaultOption: Record< - KmsKeyIntent, - SymmetricKeyEncryptDecrypt | AsymmetricKeySignVerify + KmsKeyUsage, + SymmetricKeyAlgorithm | AsymmetricKeyAlgorithm > = { - [KmsKeyIntent.ENCRYPT_DECRYPT]: SymmetricKeyEncryptDecrypt.AES_GCM_256, - [KmsKeyIntent.SIGN_VERIFY]: AsymmetricKeySignVerify.RSA_4096 + [KmsKeyUsage.ENCRYPT_DECRYPT]: SymmetricKeyAlgorithm.AES_GCM_256, + [KmsKeyUsage.SIGN_VERIFY]: AsymmetricKeyAlgorithm.RSA_4096 }; diff --git a/frontend/src/hooks/api/cmeks/types.ts b/frontend/src/hooks/api/cmeks/types.ts index 485187613..599249fac 100644 --- a/frontend/src/hooks/api/cmeks/types.ts +++ b/frontend/src/hooks/api/cmeks/types.ts @@ -2,17 +2,17 @@ import { z } from "zod"; import { OrderByDirection } from "@app/hooks/api/generic/types"; -export enum KmsKeyIntent { +export enum KmsKeyUsage { ENCRYPT_DECRYPT = "encrypt-decrypt", SIGN_VERIFY = "sign-verify" } export type TCmek = { id: string; - type: KmsKeyIntent; + keyUsage: KmsKeyUsage; name: string; description?: string; - encryptionAlgorithm: AsymmetricKeySignVerify | SymmetricKeyEncryptDecrypt; + encryptionAlgorithm: AsymmetricKeyAlgorithm | SymmetricKeyAlgorithm; projectId: string; isDisabled: boolean; isReserved: boolean; @@ -25,7 +25,7 @@ export type TCmek = { type ProjectRef = { projectId: string }; type KeyRef = { keyId: string }; -export type TCreateCmek = Pick & +export type TCreateCmek = Pick & ProjectRef; export type TUpdateCmek = KeyRef & Partial> & @@ -80,20 +80,20 @@ export enum CmekOrderBy { Name = "name" } -export enum AsymmetricKeySignVerify { +export enum AsymmetricKeyAlgorithm { RSA_4096 = "rsa-4096", ECC_NIST_P256 = "ecc-nist-p256" } // Supported symmetric encrypt/decrypt algorithms -export enum SymmetricKeyEncryptDecrypt { +export enum SymmetricKeyAlgorithm { AES_GCM_256 = "aes-256-gcm", AES_GCM_128 = "aes-128-gcm" } export const AllowedEncryptionKeyAlgorithms = z.enum([ - ...Object.values(SymmetricKeyEncryptDecrypt), - ...Object.values(AsymmetricKeySignVerify) + ...Object.values(SymmetricKeyAlgorithm), + ...Object.values(AsymmetricKeyAlgorithm) ] as [string, ...string[]]).options; export enum SigningAlgorithm { diff --git a/frontend/src/pages/kms/OverviewPage/components/CmekModal.tsx b/frontend/src/pages/kms/OverviewPage/components/CmekModal.tsx index d7616dfca..c43b6c8d0 100644 --- a/frontend/src/pages/kms/OverviewPage/components/CmekModal.tsx +++ b/frontend/src/pages/kms/OverviewPage/components/CmekModal.tsx @@ -18,9 +18,9 @@ import { useWorkspace } from "@app/context"; import { keyUsageDefaultOption, kmsKeyUsageOptions } from "@app/helpers/kms"; import { AllowedEncryptionKeyAlgorithms, - AsymmetricKeySignVerify, - KmsKeyIntent, - SymmetricKeyEncryptDecrypt, + AsymmetricKeyAlgorithm, + KmsKeyUsage, + SymmetricKeyAlgorithm, TCmek, useCreateCmek, useUpdateCmek @@ -31,7 +31,7 @@ const formSchema = z.object({ name: slugSchema({ min: 1, max: 32, field: "Name" }), description: z.string().max(500).optional(), encryptionAlgorithm: z.enum(AllowedEncryptionKeyAlgorithms), - type: z.nativeEnum(KmsKeyIntent) + keyUsage: z.nativeEnum(KmsKeyUsage) }); export type FormData = z.infer; @@ -65,22 +65,25 @@ const CmekForm = ({ onComplete, cmek }: FormProps) => { defaultValues: { name: cmek?.name, description: cmek?.description, - encryptionAlgorithm: SymmetricKeyEncryptDecrypt.AES_GCM_256, - type: KmsKeyIntent.ENCRYPT_DECRYPT + encryptionAlgorithm: SymmetricKeyAlgorithm.AES_GCM_256, + keyUsage: KmsKeyUsage.ENCRYPT_DECRYPT } }); - const handleCreateCmek = async ({ encryptionAlgorithm, name, description, type }: FormData) => { + const handleCreateCmek = async ({ + encryptionAlgorithm, + name, + description, + keyUsage + }: FormData) => { const mutation = isUpdate ? updateCmek.mutateAsync({ keyId: cmek.id, projectId, name, description }) : createCmek.mutateAsync({ projectId, name, description, - type, - encryptionAlgorithm: encryptionAlgorithm as - | AsymmetricKeySignVerify - | SymmetricKeyEncryptDecrypt + keyUsage, + encryptionAlgorithm: encryptionAlgorithm as AsymmetricKeyAlgorithm | SymmetricKeyAlgorithm }); try { @@ -99,7 +102,7 @@ const CmekForm = ({ onComplete, cmek }: FormProps) => { } }; - const selectedType = watch("type"); + const selectedKeyUsage = watch("keyUsage"); return (
@@ -116,13 +119,13 @@ const CmekForm = ({ onComplete, cmek }: FormProps) => { <> ( - {Object.entries(KmsKeyIntent).map(([key, value]) => ( + {Object.entries(KmsKeyUsage).map(([key, value]) => (

{kmsKeyUsageOptions[value].label}

{kmsKeyUsageOptions[value].tooltip}

@@ -137,8 +140,8 @@ const CmekForm = ({ onComplete, cmek }: FormProps) => {