fix: requested changes

This commit is contained in:
Daniel Hougaard
2025-04-04 04:21:00 +04:00
parent c7416c825c
commit 53b5497271
23 changed files with 222 additions and 202 deletions
@@ -1,6 +1,6 @@
import { Knex } from "knex"; import { Knex } from "knex";
import { KmsKeyIntent } from "@app/services/kms/kms-types"; import { KmsKeyUsage } from "@app/services/kms/kms-types";
import { TableName } from "../schemas"; import { TableName } from "../schemas";
@@ -8,12 +8,12 @@ export async function up(knex: Knex): Promise<void> {
const hasTypeColumn = await knex.schema.hasColumn(TableName.KmsKey, "type"); const hasTypeColumn = await knex.schema.hasColumn(TableName.KmsKey, "type");
await knex.schema.alterTable(TableName.KmsKey, (t) => { 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<void> { export async function down(knex: Knex): Promise<void> {
await knex.schema.alterTable(TableName.KmsKey, (t) => { await knex.schema.alterTable(TableName.KmsKey, (t) => {
t.dropColumn("type"); t.dropColumn("keyUsage");
}); });
} }
+1 -1
View File
@@ -17,7 +17,7 @@ export const KmsKeysSchema = z.object({
createdAt: z.date(), createdAt: z.date(),
updatedAt: z.date(), updatedAt: z.date(),
projectId: z.string().nullable().optional(), projectId: z.string().nullable().optional(),
type: z.string().default("encrypt-decrypt") keyUsage: z.string().default("encrypt-decrypt")
}); });
export type TKmsKeys = z.infer<typeof KmsKeysSchema>; export type TKmsKeys = z.infer<typeof KmsKeysSchema>;
+3 -3
View File
@@ -2,7 +2,7 @@ import z from "zod";
import { KmsKeysSchema } from "@app/db/schemas"; import { KmsKeysSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; 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 { ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { writeLimit } from "@app/server/config/rateLimiter"; import { writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -74,7 +74,7 @@ export const registerKmipSpecRouter = async (server: FastifyZodProvider) => {
schema: { schema: {
description: "KMIP endpoint for creating managed objects", description: "KMIP endpoint for creating managed objects",
body: z.object({ body: z.object({
algorithm: z.nativeEnum(SymmetricKeyEncryptDecrypt) algorithm: z.nativeEnum(SymmetricKeyAlgorithm)
}), }),
response: { response: {
200: KmsKeysSchema 200: KmsKeysSchema
@@ -433,7 +433,7 @@ export const registerKmipSpecRouter = async (server: FastifyZodProvider) => {
body: z.object({ body: z.object({
key: z.string(), key: z.string(),
name: z.string(), name: z.string(),
algorithm: z.nativeEnum(SymmetricKeyEncryptDecrypt) algorithm: z.nativeEnum(SymmetricKeyAlgorithm)
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -4,8 +4,8 @@ import {
} from "@app/ee/services/project-template/project-template-types"; } from "@app/ee/services/project-template/project-template-types";
import { SshCaStatus, SshCertType } from "@app/ee/services/ssh/ssh-certificate-authority-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 { SshCertTemplateStatus } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-types";
import { SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; import { SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher";
import { AsymmetricKeySignVerify, SigningAlgorithm } from "@app/lib/crypto/sign/types"; import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign/types";
import { TProjectPermission } from "@app/lib/types"; import { TProjectPermission } from "@app/lib/types";
import { AppConnection } from "@app/services/app-connection/app-connection-enums"; import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import { TCreateAppConnectionDTO, TUpdateAppConnectionDTO } from "@app/services/app-connection/app-connection-types"; import { TCreateAppConnectionDTO, TUpdateAppConnectionDTO } from "@app/services/app-connection/app-connection-types";
@@ -1903,7 +1903,7 @@ interface CreateCmekEvent {
keyId: string; keyId: string;
name: string; name: string;
description?: string; description?: string;
encryptionAlgorithm: SymmetricKeyEncryptDecrypt | AsymmetricKeySignVerify; encryptionAlgorithm: SymmetricKeyAlgorithm | AsymmetricKeyAlgorithm;
}; };
} }
@@ -7,7 +7,7 @@ import { BadRequestError, InternalServerError, NotFoundError } from "@app/lib/er
import { alphaNumericNanoId } from "@app/lib/nanoid"; import { alphaNumericNanoId } from "@app/lib/nanoid";
import { TKmsKeyDALFactory } from "@app/services/kms/kms-key-dal"; import { TKmsKeyDALFactory } from "@app/services/kms/kms-key-dal";
import { TKmsServiceFactory } from "@app/services/kms/kms-service"; 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 { TLicenseServiceFactory } from "../license/license-service";
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission"; import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
@@ -115,7 +115,7 @@ export const externalKmsServiceFactory = ({
{ {
isReserved: false, isReserved: false,
description, description,
type: KmsKeyIntent.ENCRYPT_DECRYPT, keyUsage: KmsKeyUsage.ENCRYPT_DECRYPT,
name: kmsName, name: kmsName,
orgId: actorOrgId orgId: actorOrgId
}, },
@@ -3,7 +3,7 @@ import { ForbiddenError } from "@casl/ability";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { TKmsKeyDALFactory } from "@app/services/kms/kms-key-dal"; import { TKmsKeyDALFactory } from "@app/services/kms/kms-key-dal";
import { TKmsServiceFactory } from "@app/services/kms/kms-service"; 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 { TProjectDALFactory } from "@app/services/project/project-dal";
import { OrgPermissionKmipActions, OrgPermissionSubjects } from "../permission/org-permission"; import { OrgPermissionKmipActions, OrgPermissionSubjects } from "../permission/org-permission";
@@ -404,7 +404,7 @@ export const kmipOperationServiceFactory = ({
algorithm, algorithm,
isReserved: false, isReserved: false,
projectId, projectId,
type: KmsKeyIntent.ENCRYPT_DECRYPT, keyUsage: KmsKeyUsage.ENCRYPT_DECRYPT,
orgId: project.orgId orgId: project.orgId
}); });
+3 -3
View File
@@ -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 { OrderByDirection, TOrgPermission, TProjectPermission } from "@app/lib/types";
import { CertKeyAlgorithm } from "@app/services/certificate/certificate-types"; import { CertKeyAlgorithm } from "@app/services/certificate/certificate-types";
@@ -49,7 +49,7 @@ type KmipOperationBaseDTO = {
} & Omit<TOrgPermission, "orgId">; } & Omit<TOrgPermission, "orgId">;
export type TKmipCreateDTO = { export type TKmipCreateDTO = {
algorithm: SymmetricKeyEncryptDecrypt; algorithm: SymmetricKeyAlgorithm;
} & KmipOperationBaseDTO; } & KmipOperationBaseDTO;
export type TKmipGetDTO = { export type TKmipGetDTO = {
@@ -77,7 +77,7 @@ export type TKmipLocateDTO = KmipOperationBaseDTO;
export type TKmipRegisterDTO = { export type TKmipRegisterDTO = {
name: string; name: string;
key: string; key: string;
algorithm: SymmetricKeyEncryptDecrypt; algorithm: SymmetricKeyAlgorithm;
} & KmipOperationBaseDTO; } & KmipOperationBaseDTO;
export type TSetupOrgKmipDTO = { export type TSetupOrgKmipDTO = {
+2 -2
View File
@@ -1,6 +1,6 @@
import crypto from "crypto"; import crypto from "crypto";
import { SymmetricKeyEncryptDecrypt, TSymmetricEncryptionFns } from "./types"; import { SymmetricKeyAlgorithm, TSymmetricEncryptionFns } from "./types";
const getIvLength = () => { const getIvLength = () => {
return 12; return 12;
@@ -11,7 +11,7 @@ const getTagLength = () => {
}; };
export const symmetricCipherService = ( export const symmetricCipherService = (
type: SymmetricKeyEncryptDecrypt.AES_GCM_128 | SymmetricKeyEncryptDecrypt.AES_GCM_256 type: SymmetricKeyAlgorithm.AES_GCM_128 | SymmetricKeyAlgorithm.AES_GCM_256
): TSymmetricEncryptionFns => { ): TSymmetricEncryptionFns => {
const IV_LENGTH = getIvLength(); const IV_LENGTH = getIvLength();
const TAG_LENGTH = getTagLength(); const TAG_LENGTH = getTagLength();
+1 -1
View File
@@ -1,2 +1,2 @@
export { symmetricCipherService } from "./cipher"; export { symmetricCipherService } from "./cipher";
export { AllowedEncryptionKeyAlgorithms, SymmetricKeyEncryptDecrypt } from "./types"; export { AllowedEncryptionKeyAlgorithms, SymmetricKeyAlgorithm } from "./types";
+5 -7
View File
@@ -1,19 +1,17 @@
import { z } from "zod"; import { z } from "zod";
import { AsymmetricKeySignVerify } from "../sign/types"; import { AsymmetricKeyAlgorithm } from "../sign/types";
// Supported symmetric encrypt/decrypt algorithms // Supported symmetric encrypt/decrypt algorithms
export enum SymmetricKeyEncryptDecrypt { export enum SymmetricKeyAlgorithm {
AES_GCM_256 = "aes-256-gcm", AES_GCM_256 = "aes-256-gcm",
AES_GCM_128 = "aes-128-gcm" AES_GCM_128 = "aes-128-gcm"
} }
export const SymmetricKeyEncryptDecryptEnum = z.enum( export const SymmetricKeyAlgorithmEnum = z.enum(Object.values(SymmetricKeyAlgorithm) as [string, ...string[]]).options;
Object.values(SymmetricKeyEncryptDecrypt) as [string, ...string[]]
).options;
export const AllowedEncryptionKeyAlgorithms = z.enum([ export const AllowedEncryptionKeyAlgorithms = z.enum([
...Object.values(SymmetricKeyEncryptDecrypt), ...Object.values(SymmetricKeyAlgorithm),
...Object.values(AsymmetricKeySignVerify) ...Object.values(AsymmetricKeyAlgorithm)
] as [string, ...string[]]).options; ] as [string, ...string[]]).options;
export type TSymmetricEncryptionFns = { export type TSymmetricEncryptionFns = {
+1 -1
View File
@@ -1,2 +1,2 @@
export { signingService } from "./signing"; export { signingService } from "./signing";
export { AsymmetricKeySignVerify, SigningAlgorithm } from "./types"; export { AsymmetricKeyAlgorithm, SigningAlgorithm } from "./types";
+8 -7
View File
@@ -3,7 +3,7 @@ import crypto from "crypto";
import { BadRequestError } from "@app/lib/errors"; import { BadRequestError } from "@app/lib/errors";
import { logger } from "@app/lib/logger"; 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 // Map of signing algorithms to their parameters
interface SigningParams { interface SigningParams {
@@ -22,7 +22,7 @@ const SHA512_DIGEST_LENGTH = 64;
* @param algorithm The signing algorithm to use * @param algorithm The signing algorithm to use
* @returns Object with sign and verify functions * @returns Object with sign and verify functions
*/ */
export const signingService = (algorithm: AsymmetricKeySignVerify): TAsymmetricSignVerifyFns => { export const signingService = (algorithm: AsymmetricKeyAlgorithm): TAsymmetricSignVerifyFns => {
const $getSigningParams = (signingAlgorithm: SigningAlgorithm): SigningParams => { const $getSigningParams = (signingAlgorithm: SigningAlgorithm): SigningParams => {
switch (signingAlgorithm) { switch (signingAlgorithm) {
// RSA PSS // 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 // 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 // We will support more in the future
switch (keyAlgorithm) { switch (keyAlgorithm) {
case AsymmetricKeySignVerify.ECC_NIST_P256: case AsymmetricKeyAlgorithm.ECC_NIST_P256:
return "prime256v1"; return "prime256v1";
default: default:
throw new Error(`Unsupported EC curve: ${keyAlgorithm}`); throw new Error(`Unsupported EC curve: ${keyAlgorithm}`);
@@ -172,7 +172,6 @@ export const signingService = (algorithm: AsymmetricKeySignVerify): TAsymmetricS
type: "pkcs8" type: "pkcs8"
}); });
// Return public key in PEM format for both RSA and EC
const publicKey = crypto.createPublicKey(privateKeyObj).export({ const publicKey = crypto.createPublicKey(privateKeyObj).export({
type: "spki", type: "spki",
format: "pem" format: "pem"
@@ -210,7 +209,8 @@ export const signingService = (algorithm: AsymmetricKeySignVerify): TAsymmetricS
} }
// For PKCS1 v1.5 padding // For PKCS1 v1.5 padding
return signer.sign({ return signer.sign({
key: privateKeyObject key: privateKeyObject,
padding
}); });
} }
if (signingAlgorithm.startsWith("ECDSA")) { if (signingAlgorithm.startsWith("ECDSA")) {
@@ -252,7 +252,8 @@ export const signingService = (algorithm: AsymmetricKeySignVerify): TAsymmetricS
// For PKCS1 v1.5 padding // For PKCS1 v1.5 padding
return verifier.verify( return verifier.verify(
{ {
key: publicKey.toString() key: publicKey.toString(),
padding
}, },
signature signature
); );
+3 -3
View File
@@ -8,13 +8,13 @@ export type TAsymmetricSignVerifyFns = {
}; };
// Supported asymmetric key types // Supported asymmetric key types
export enum AsymmetricKeySignVerify { export enum AsymmetricKeyAlgorithm {
RSA_4096 = "rsa-4096", RSA_4096 = "rsa-4096",
ECC_NIST_P256 = "ecc-nist-p256" ECC_NIST_P256 = "ecc-nist-p256"
} }
export const AsymmetricKeySignVerifyEnum = z.enum( export const AsymmetricKeyAlgorithmEnum = z.enum(
Object.values(AsymmetricKeySignVerify) as [string, ...string[]] Object.values(AsymmetricKeyAlgorithm) as [string, ...string[]]
).options; ).options;
export enum SigningAlgorithm { export enum SigningAlgorithm {
+41 -34
View File
@@ -4,22 +4,20 @@ import { InternalKmsSchema, KmsKeysSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { KMS } from "@app/lib/api-docs"; import { KMS } from "@app/lib/api-docs";
import { getBase64SizeInBytes, isBase64 } from "@app/lib/base64"; import { getBase64SizeInBytes, isBase64 } from "@app/lib/base64";
import { AllowedEncryptionKeyAlgorithms, SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; import { AllowedEncryptionKeyAlgorithms, SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher";
import { AsymmetricKeySignVerify, SigningAlgorithm } from "@app/lib/crypto/sign"; import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign";
import { OrderByDirection } from "@app/lib/types"; import { OrderByDirection } from "@app/lib/types";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas"; import { slugSchema } from "@app/server/lib/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type"; import { AuthMode } from "@app/services/auth/auth-type";
import { CmekOrderBy, TCmekKeyEncryptionAlgorithm } from "@app/services/cmek/cmek-types"; 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 keyNameSchema = slugSchema({ min: 1, max: 32, field: "Name" });
const keyDescriptionSchema = z.string().trim().max(500).optional(); const keyDescriptionSchema = z.string().trim().max(500).optional();
const CmekSchema = KmsKeysSchema.merge( const CmekSchema = KmsKeysSchema.merge(InternalKmsSchema.pick({ version: true, encryptionAlgorithm: true })).omit({
InternalKmsSchema.pick({ version: true, encryptionAlgorithm: true, type: true })
).omit({
isReserved: true isReserved: true
}); });
@@ -54,37 +52,37 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
projectId: z.string().describe(KMS.CREATE_KEY.projectId), projectId: z.string().describe(KMS.CREATE_KEY.projectId),
name: keyNameSchema.describe(KMS.CREATE_KEY.name), name: keyNameSchema.describe(KMS.CREATE_KEY.name),
description: keyDescriptionSchema.describe(KMS.CREATE_KEY.description), description: keyDescriptionSchema.describe(KMS.CREATE_KEY.description),
type: z keyUsage: z
.nativeEnum(KmsKeyIntent) .nativeEnum(KmsKeyUsage)
.optional() .optional()
.default(KmsKeyIntent.ENCRYPT_DECRYPT) .default(KmsKeyUsage.ENCRYPT_DECRYPT)
.describe(KMS.CREATE_KEY.type), .describe(KMS.CREATE_KEY.type),
encryptionAlgorithm: z encryptionAlgorithm: z
.enum(AllowedEncryptionKeyAlgorithms) .enum(AllowedEncryptionKeyAlgorithms)
.optional() .optional()
.default(SymmetricKeyEncryptDecrypt.AES_GCM_256) .default(SymmetricKeyAlgorithm.AES_GCM_256)
.describe(KMS.CREATE_KEY.encryptionAlgorithm) .describe(KMS.CREATE_KEY.encryptionAlgorithm)
}) })
.superRefine((data, ctx) => { .superRefine((data, ctx) => {
if ( if (
data.type === KmsKeyIntent.ENCRYPT_DECRYPT && data.keyUsage === KmsKeyUsage.ENCRYPT_DECRYPT &&
!Object.values(SymmetricKeyEncryptDecrypt).includes(data.encryptionAlgorithm as SymmetricKeyEncryptDecrypt) !Object.values(SymmetricKeyAlgorithm).includes(data.encryptionAlgorithm as SymmetricKeyAlgorithm)
) { ) {
ctx.addIssue({ ctx.addIssue({
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,
message: `encryptionAlgorithm must be a valid symmetric encryption algorithm. Valid options are: ${Object.values( message: `encryptionAlgorithm must be a valid symmetric encryption algorithm. Valid options are: ${Object.values(
SymmetricKeyEncryptDecrypt SymmetricKeyAlgorithm
).join(", ")}` ).join(", ")}`
}); });
} }
if ( if (
data.type === KmsKeyIntent.SIGN_VERIFY && data.keyUsage === KmsKeyUsage.SIGN_VERIFY &&
!Object.values(AsymmetricKeySignVerify).includes(data.encryptionAlgorithm as AsymmetricKeySignVerify) !Object.values(AsymmetricKeyAlgorithm).includes(data.encryptionAlgorithm as AsymmetricKeyAlgorithm)
) { ) {
ctx.addIssue({ ctx.addIssue({
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,
message: `encryptionAlgorithm must be a valid asymmetric sign-verify algorithm. Valid options are: ${Object.values( message: `encryptionAlgorithm must be a valid asymmetric sign-verify algorithm. Valid options are: ${Object.values(
AsymmetricKeySignVerify AsymmetricKeyAlgorithm
).join(", ")}` ).join(", ")}`
}); });
} }
@@ -98,7 +96,7 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => { handler: async (req) => {
const { const {
body: { projectId, name, description, encryptionAlgorithm, type }, body: { projectId, name, description, encryptionAlgorithm, keyUsage },
permission permission
} = req; } = req;
@@ -109,7 +107,7 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
name, name,
description, description,
encryptionAlgorithm: encryptionAlgorithm as TCmekKeyEncryptionAlgorithm, encryptionAlgorithm: encryptionAlgorithm as TCmekKeyEncryptionAlgorithm,
type keyUsage
}, },
permission permission
); );
@@ -167,7 +165,7 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
...req.auditLogInfo, ...req.auditLogInfo,
orgId: permission.orgId, projectId: cmek.projectId!,
event: { event: {
type: EventType.UPDATE_CMEK, type: EventType.UPDATE_CMEK,
metadata: { metadata: {
@@ -210,7 +208,7 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
...req.auditLogInfo, ...req.auditLogInfo,
orgId: permission.orgId, projectId: cmek.projectId!,
event: { event: {
type: EventType.DELETE_CMEK, type: EventType.DELETE_CMEK,
metadata: { metadata: {
@@ -390,11 +388,11 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
permission permission
} = req; } = 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({ await server.services.auditLog.createAuditLog({
...req.auditLogInfo, ...req.auditLogInfo,
orgId: permission.orgId, projectId,
event: { event: {
type: EventType.CMEK_ENCRYPT, type: EventType.CMEK_ENCRYPT,
metadata: { metadata: {
@@ -431,11 +429,11 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
permission permission
} = req; } = 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({ await server.services.auditLog.createAuditLog({
...req.auditLogInfo, ...req.auditLogInfo,
orgId: permission.orgId, projectId,
event: { event: {
type: EventType.CMEK_GET_PUBLIC_KEY, type: EventType.CMEK_GET_PUBLIC_KEY,
metadata: { 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) => { handler: async (req) => {
const { keyId } = req.params; 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({ await server.services.auditLog.createAuditLog({
...req.auditLogInfo, ...req.auditLogInfo,
orgId: req.permission.orgId, projectId,
event: { event: {
type: EventType.CMEK_LIST_SIGNING_ALGORITHMS, type: EventType.CMEK_LIST_SIGNING_ALGORITHMS,
metadata: { 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 permission
} = req; } = 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({ await server.services.auditLog.createAuditLog({
...req.auditLogInfo, ...req.auditLogInfo,
orgId: permission.orgId, projectId,
event: { event: {
type: EventType.CMEK_SIGN, type: EventType.CMEK_SIGN,
metadata: { metadata: {
@@ -597,11 +601,14 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
permission permission
} = req; } = 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({ await server.services.auditLog.createAuditLog({
...req.auditLogInfo, ...req.auditLogInfo,
orgId: permission.orgId, projectId,
event: { event: {
type: EventType.CMEK_VERIFY, type: EventType.CMEK_VERIFY,
metadata: { metadata: {
@@ -645,11 +652,11 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
permission permission
} = req; } = 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({ await server.services.auditLog.createAuditLog({
...req.auditLogInfo, ...req.auditLogInfo,
orgId: permission.orgId, projectId,
event: { event: {
type: EventType.CMEK_DECRYPT, type: EventType.CMEK_DECRYPT,
metadata: { metadata: {
+14 -6
View File
@@ -22,7 +22,7 @@ import {
import { TKmsKeyDALFactory } from "@app/services/kms/kms-key-dal"; import { TKmsKeyDALFactory } from "@app/services/kms/kms-key-dal";
import { TKmsServiceFactory } from "@app/services/kms/kms-service"; 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"; import { TProjectDALFactory } from "../project/project-dal";
type TCmekServiceFactoryDep = { type TCmekServiceFactoryDep = {
@@ -228,7 +228,10 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
const { cipherTextBlob } = await encrypt({ plainText: Buffer.from(plaintext, "base64") }); 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) => { 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); 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` }); 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}` }); 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) => { 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 }); const publicKey = await kmsService.getPublicKey({ kmsId: keyId });
return { publicKey }; return { publicKey, projectId: key.projectId };
}; };
const cmekSign = async ({ keyId, data, signingAlgorithm }: TCmekSignDTO, actor: OrgServiceActor) => { const cmekSign = async ({ keyId, data, signingAlgorithm }: TCmekSignDTO, actor: OrgServiceActor) => {
@@ -329,6 +332,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
return { return {
signature: signature.toString("base64"), signature: signature.toString("base64"),
keyId: key.id, keyId: key.id,
projectId: key.projectId,
signingAlgorithm: algorithm signingAlgorithm: algorithm
}; };
}; };
@@ -363,6 +367,7 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
return { return {
signatureValid, signatureValid,
keyId: key.id, keyId: key.id,
projectId: key.projectId,
signingAlgorithm: algorithm signingAlgorithm: algorithm
}; };
}; };
@@ -391,7 +396,10 @@ export const cmekServiceFactory = ({ kmsService, kmsDAL, permissionService, proj
const plaintextBlob = await decrypt({ cipherTextBlob: Buffer.from(ciphertext, "base64") }); const plaintextBlob = await decrypt({ cipherTextBlob: Buffer.from(ciphertext, "base64") });
return plaintextBlob.toString("base64"); return {
plaintext: plaintextBlob.toString("base64"),
projectId: key.projectId
};
}; };
return { return {
+5 -5
View File
@@ -1,10 +1,10 @@
import { SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; import { SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher";
import { AsymmetricKeySignVerify, SigningAlgorithm } from "@app/lib/crypto/sign"; import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign";
import { OrderByDirection } from "@app/lib/types"; 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 = { export type TCreateCmekDTO = {
orgId: string; orgId: string;
@@ -12,7 +12,7 @@ export type TCreateCmekDTO = {
name: string; name: string;
description?: string; description?: string;
encryptionAlgorithm: TCmekKeyEncryptionAlgorithm; encryptionAlgorithm: TCmekKeyEncryptionAlgorithm;
type: KmsKeyIntent; keyUsage: KmsKeyUsage;
}; };
export type TUpdabteCmekByIdDTO = { export type TUpdabteCmekByIdDTO = {
+16 -16
View File
@@ -1,36 +1,36 @@
import { SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; import { SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher";
import { AsymmetricKeySignVerify } from "@app/lib/crypto/sign"; import { AsymmetricKeyAlgorithm } from "@app/lib/crypto/sign";
import { BadRequestError } from "@app/lib/errors"; 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 KMS_ROOT_CONFIG_UUID = "00000000-0000-0000-0000-000000000000";
export const getByteLengthForSymmetricEncryptionAlgorithm = (encryptionAlgorithm: SymmetricKeyEncryptDecrypt) => { export const getByteLengthForSymmetricEncryptionAlgorithm = (encryptionAlgorithm: SymmetricKeyAlgorithm) => {
switch (encryptionAlgorithm) { switch (encryptionAlgorithm) {
case SymmetricKeyEncryptDecrypt.AES_GCM_128: case SymmetricKeyAlgorithm.AES_GCM_128:
return 16; return 16;
case SymmetricKeyEncryptDecrypt.AES_GCM_256: case SymmetricKeyAlgorithm.AES_GCM_256:
default: default:
return 32; return 32;
} }
}; };
export const verifyKeyTypeAndAlgorithm = ( export const verifyKeyTypeAndAlgorithm = (
type: KmsKeyIntent, keyUsage: KmsKeyUsage,
algorithm: SymmetricKeyEncryptDecrypt | AsymmetricKeySignVerify, algorithm: SymmetricKeyAlgorithm | AsymmetricKeyAlgorithm,
extra?: { extra?: {
forceType?: KmsKeyIntent; forceType?: KmsKeyUsage;
} }
) => { ) => {
if (extra?.forceType && type !== extra.forceType) { if (extra?.forceType && keyUsage !== extra.forceType) {
throw new BadRequestError({ 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 (keyUsage === KmsKeyUsage.ENCRYPT_DECRYPT) {
if (!Object.values(SymmetricKeyEncryptDecrypt).includes(algorithm as SymmetricKeyEncryptDecrypt)) { if (!Object.values(SymmetricKeyAlgorithm).includes(algorithm as SymmetricKeyAlgorithm)) {
throw new BadRequestError({ throw new BadRequestError({
message: `Unsupported encryption algorithm for encrypt/decrypt key: ${algorithm as string}` message: `Unsupported encryption algorithm for encrypt/decrypt key: ${algorithm as string}`
}); });
@@ -39,8 +39,8 @@ export const verifyKeyTypeAndAlgorithm = (
return true; return true;
} }
if (type === KmsKeyIntent.SIGN_VERIFY) { if (keyUsage === KmsKeyUsage.SIGN_VERIFY) {
if (!Object.values(AsymmetricKeySignVerify).includes(algorithm as AsymmetricKeySignVerify)) { if (!Object.values(AsymmetricKeyAlgorithm).includes(algorithm as AsymmetricKeyAlgorithm)) {
throw new BadRequestError({ throw new BadRequestError({
message: `Unsupported sign/verify algorithm for sign/verify key: ${algorithm as string}` message: `Unsupported sign/verify algorithm for sign/verify key: ${algorithm as string}`
}); });
@@ -50,6 +50,6 @@ export const verifyKeyTypeAndAlgorithm = (
} }
throw new BadRequestError({ throw new BadRequestError({
message: `Unsupported key type: ${type as string}` message: `Unsupported key type: ${keyUsage as string}`
}); });
}; };
+46 -46
View File
@@ -17,9 +17,9 @@ import { THsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
import { KeyStorePrefixes, PgSqlLock, TKeyStoreFactory } from "@app/keystore/keystore"; import { KeyStorePrefixes, PgSqlLock, TKeyStoreFactory } from "@app/keystore/keystore";
import { TEnvConfig } from "@app/lib/config/env"; import { TEnvConfig } from "@app/lib/config/env";
import { randomSecureBytes } from "@app/lib/crypto"; 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 { 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 { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
import { alphaNumericNanoId } from "@app/lib/nanoid"; import { alphaNumericNanoId } from "@app/lib/nanoid";
@@ -36,7 +36,7 @@ import { TKmsKeyDALFactory } from "./kms-key-dal";
import { TKmsRootConfigDALFactory } from "./kms-root-config-dal"; import { TKmsRootConfigDALFactory } from "./kms-root-config-dal";
import { import {
KmsDataKey, KmsDataKey,
KmsKeyIntent, KmsKeyUsage,
KmsType, KmsType,
RootKeyEncryptionStrategy, RootKeyEncryptionStrategy,
TDecryptWithKeyDTO, TDecryptWithKeyDTO,
@@ -94,21 +94,21 @@ export const kmsServiceFactory = ({
tx, tx,
name, name,
projectId, projectId,
encryptionAlgorithm = SymmetricKeyEncryptDecrypt.AES_GCM_256, encryptionAlgorithm = SymmetricKeyAlgorithm.AES_GCM_256,
type = KmsKeyIntent.ENCRYPT_DECRYPT, keyUsage = KmsKeyUsage.ENCRYPT_DECRYPT,
description description
}: TGenerateKMSDTO) => { }: TGenerateKMSDTO) => {
// daniel: ensure that the key type (sign/encrypt) and the encryption algorithm are compatible. // 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; let kmsKeyMaterial: Buffer | null = null;
if (type === KmsKeyIntent.ENCRYPT_DECRYPT) { if (keyUsage === KmsKeyUsage.ENCRYPT_DECRYPT) {
kmsKeyMaterial = randomSecureBytes( 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( const { generateAsymmetricPrivateKey, getPublicKeyFromPrivateKey } = signingService(
encryptionAlgorithm as AsymmetricKeySignVerify encryptionAlgorithm as AsymmetricKeyAlgorithm
); );
kmsKeyMaterial = await generateAsymmetricPrivateKey(); kmsKeyMaterial = await generateAsymmetricPrivateKey();
@@ -118,18 +118,18 @@ export const kmsServiceFactory = ({
if (!kmsKeyMaterial) { if (!kmsKeyMaterial) {
throw new BadRequestError({ 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 encryptedKeyMaterial = cipher.encrypt(kmsKeyMaterial, ROOT_ENCRYPTION_KEY);
const sanitizedName = name ? slugify(name) : slugify(alphaNumericNanoId(8).toLowerCase()); const sanitizedName = name ? slugify(name) : slugify(alphaNumericNanoId(8).toLowerCase());
const dbQuery = async (db: Knex) => { const dbQuery = async (db: Knex) => {
const kmsDoc = await kmsDAL.create( const kmsDoc = await kmsDAL.create(
{ {
name: sanitizedName, name: sanitizedName,
type, keyUsage,
orgId, orgId,
isReserved, isReserved,
projectId, projectId,
@@ -169,7 +169,7 @@ export const kmsServiceFactory = ({
*/ */
const encryptWithInputKey = async ({ key }: Omit<TEncryptionWithKeyDTO, "plainText">) => { const encryptWithInputKey = async ({ key }: Omit<TEncryptionWithKeyDTO, "plainText">) => {
// 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(SymmetricKeyEncryptDecrypt.AES_GCM_256); const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
return ({ plainText }: Pick<TEncryptWithKmsDTO, "plainText">) => { return ({ plainText }: Pick<TEncryptWithKmsDTO, "plainText">) => {
const encryptedPlainTextBlob = cipher.encrypt(plainText, key); const encryptedPlainTextBlob = cipher.encrypt(plainText, key);
// Buffer#1 encrypted text + Buffer#2 version number // 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 * This can be even later exposed directly as api for encryption as function
*/ */
const decryptWithInputKey = async ({ key }: Omit<TDecryptWithKeyDTO, "cipherTextBlob">) => { const decryptWithInputKey = async ({ key }: Omit<TDecryptWithKeyDTO, "cipherTextBlob">) => {
const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
return ({ cipherTextBlob: versionedCipherTextBlob }: Pick<TDecryptWithKeyDTO, "cipherTextBlob">) => { return ({ cipherTextBlob: versionedCipherTextBlob }: Pick<TDecryptWithKeyDTO, "cipherTextBlob">) => {
const cipherTextBlob = versionedCipherTextBlob.subarray(0, -KMS_VERSION_BLOB_LENGTH); const cipherTextBlob = versionedCipherTextBlob.subarray(0, -KMS_VERSION_BLOB_LENGTH);
@@ -262,7 +262,7 @@ export const kmsServiceFactory = ({
}; };
const encryptWithRootKey = () => { const encryptWithRootKey = () => {
const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
return (plainTextBuffer: Buffer) => { return (plainTextBuffer: Buffer) => {
const encryptedBuffer = cipher.encrypt(plainTextBuffer, ROOT_ENCRYPTION_KEY); const encryptedBuffer = cipher.encrypt(plainTextBuffer, ROOT_ENCRYPTION_KEY);
@@ -271,7 +271,7 @@ export const kmsServiceFactory = ({
}; };
const decryptWithRootKey = () => { const decryptWithRootKey = () => {
const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
return (cipherTextBuffer: Buffer) => { return (cipherTextBuffer: Buffer) => {
return cipher.decrypt(cipherTextBuffer, ROOT_ENCRYPTION_KEY); return cipher.decrypt(cipherTextBuffer, ROOT_ENCRYPTION_KEY);
@@ -290,9 +290,9 @@ export const kmsServiceFactory = ({
throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` }); throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` });
} }
const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyEncryptDecrypt; const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyAlgorithm;
verifyKeyTypeAndAlgorithm(kmsDoc.type as KmsKeyIntent, encryptionAlgorithm, { verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, {
forceType: KmsKeyIntent.ENCRYPT_DECRYPT forceType: KmsKeyUsage.ENCRYPT_DECRYPT
}); });
if (kmsDoc.externalKms) { if (kmsDoc.externalKms) {
@@ -356,7 +356,7 @@ export const kmsServiceFactory = ({
} }
// internal KMS // internal KMS
const keyCipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
const dataCipher = symmetricCipherService(encryptionAlgorithm); const dataCipher = symmetricCipherService(encryptionAlgorithm);
const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY); 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); const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY);
return kmsKey; return kmsKey;
}; };
const importKeyMaterial = async ( const importKeyMaterial = async (
{ key, algorithm, name, isReserved, projectId, orgId, type }: TImportKeyMaterialDTO, { key, algorithm, name, isReserved, projectId, orgId, keyUsage }: TImportKeyMaterialDTO,
tx?: Knex tx?: Knex
) => { ) => {
// daniel: currently we only support imports for encrypt/decrypt keys // 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) { if (key.byteLength !== expectedByteLength) {
throw new BadRequestError({ throw new BadRequestError({
message: `Invalid key length for ${algorithm}. Expected ${expectedByteLength} bytes but got ${key.byteLength} bytes` 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( const kmsDoc = await kmsDAL.create(
{ {
name: sanitizedName, name: sanitizedName,
type: KmsKeyIntent.ENCRYPT_DECRYPT, keyUsage: KmsKeyUsage.ENCRYPT_DECRYPT,
orgId, orgId,
isReserved, isReserved,
projectId projectId
@@ -443,13 +443,13 @@ export const kmsServiceFactory = ({
throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` }); 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, { verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, {
forceType: KmsKeyIntent.SIGN_VERIFY 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 kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY);
const publicKeyBuffer = signingService(encryptionAlgorithm).getPublicKeyFromPrivateKey(kmsKey); const publicKeyBuffer = signingService(encryptionAlgorithm).getPublicKeyFromPrivateKey(kmsKey);
@@ -469,12 +469,12 @@ export const kmsServiceFactory = ({
throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` }); 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, { verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, {
forceType: KmsKeyIntent.SIGN_VERIFY forceType: KmsKeyUsage.SIGN_VERIFY
}); });
const keyCipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
const { sign } = signingService(encryptionAlgorithm); const { sign } = signingService(encryptionAlgorithm);
return ({ data, signingAlgorithm }: Pick<TSignWithKmsDTO, "data" | "signingAlgorithm">) => { return ({ data, signingAlgorithm }: Pick<TSignWithKmsDTO, "data" | "signingAlgorithm">) => {
const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY); 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` }); 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, { verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, {
forceType: KmsKeyIntent.SIGN_VERIFY forceType: KmsKeyUsage.SIGN_VERIFY
}); });
const keyCipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
const { verify, getPublicKeyFromPrivateKey } = signingService(encryptionAlgorithm); const { verify, getPublicKeyFromPrivateKey } = signingService(encryptionAlgorithm);
return ({ data, signature }: Pick<TVerifyWithKmsDTO, "data" | "signature">) => { return ({ data, signature }: Pick<TVerifyWithKmsDTO, "data" | "signature">) => {
const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY); 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` }); throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` });
} }
const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyEncryptDecrypt; const encryptionAlgorithm = kmsDoc.internalKms?.encryptionAlgorithm as SymmetricKeyAlgorithm;
verifyKeyTypeAndAlgorithm(kmsDoc.type as KmsKeyIntent, encryptionAlgorithm, { verifyKeyTypeAndAlgorithm(kmsDoc.keyUsage as KmsKeyUsage, encryptionAlgorithm, {
forceType: KmsKeyIntent.ENCRYPT_DECRYPT forceType: KmsKeyUsage.ENCRYPT_DECRYPT
}); });
if (kmsDoc.externalKms) { if (kmsDoc.externalKms) {
@@ -575,7 +575,7 @@ export const kmsServiceFactory = ({
} }
// internal KMS // internal KMS
const keyCipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); const keyCipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
const dataCipher = symmetricCipherService(encryptionAlgorithm); const dataCipher = symmetricCipherService(encryptionAlgorithm);
return ({ plainText }: Pick<TEncryptWithKmsDTO, "plainText">) => { return ({ plainText }: Pick<TEncryptWithKmsDTO, "plainText">) => {
const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY); 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 // case 2: root key is encrypted with software encryption
if (kmsRootConfig.encryptionStrategy === RootKeyEncryptionStrategy.Software) { if (kmsRootConfig.encryptionStrategy === RootKeyEncryptionStrategy.Software) {
const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
const encryptionKeyBuffer = $getBasicEncryptionKey(); const encryptionKeyBuffer = $getBasicEncryptionKey();
return cipher.decrypt(kmsRootConfig.encryptedRootKey, encryptionKeyBuffer); return cipher.decrypt(kmsRootConfig.encryptedRootKey, encryptionKeyBuffer);
@@ -870,7 +870,7 @@ export const kmsServiceFactory = ({
} }
if (strategy === RootKeyEncryptionStrategy.Software) { if (strategy === RootKeyEncryptionStrategy.Software) {
const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
const encryptionKeyBuffer = $getBasicEncryptionKey(); const encryptionKeyBuffer = $getBasicEncryptionKey();
return cipher.encrypt(plainKeyBuffer, encryptionKeyBuffer); return cipher.encrypt(plainKeyBuffer, encryptionKeyBuffer);
@@ -886,7 +886,7 @@ export const kmsServiceFactory = ({
const createCipherPairWithDataKey = async (encryptionContext: TEncryptWithKmsDataKeyDTO, trx?: Knex) => { const createCipherPairWithDataKey = async (encryptionContext: TEncryptWithKmsDataKeyDTO, trx?: Knex) => {
const dataKey = await $getDataKey(encryptionContext, trx); const dataKey = await $getDataKey(encryptionContext, trx);
const cipher = symmetricCipherService(SymmetricKeyEncryptDecrypt.AES_GCM_256); const cipher = symmetricCipherService(SymmetricKeyAlgorithm.AES_GCM_256);
return { return {
encryptor: ({ plainText }: Pick<TEncryptWithKmsDTO, "plainText">) => { encryptor: ({ plainText }: Pick<TEncryptWithKmsDTO, "plainText">) => {
+7 -7
View File
@@ -1,7 +1,7 @@
import { Knex } from "knex"; import { Knex } from "knex";
import { SymmetricKeyEncryptDecrypt } from "@app/lib/crypto/cipher"; import { SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher";
import { AsymmetricKeySignVerify, SigningAlgorithm } from "@app/lib/crypto/sign/types"; import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign/types";
export enum KmsDataKey { export enum KmsDataKey {
Organization, Organization,
@@ -14,7 +14,7 @@ export enum KmsType {
Internal = "internal" Internal = "internal"
} }
export enum KmsKeyIntent { export enum KmsKeyUsage {
ENCRYPT_DECRYPT = "encrypt-decrypt", ENCRYPT_DECRYPT = "encrypt-decrypt",
SIGN_VERIFY = "sign-verify" SIGN_VERIFY = "sign-verify"
} }
@@ -31,8 +31,8 @@ export type TEncryptWithKmsDataKeyDTO =
export type TGenerateKMSDTO = { export type TGenerateKMSDTO = {
orgId: string; orgId: string;
projectId?: string; projectId?: string;
encryptionAlgorithm?: SymmetricKeyEncryptDecrypt | AsymmetricKeySignVerify; encryptionAlgorithm?: SymmetricKeyAlgorithm | AsymmetricKeyAlgorithm;
type?: KmsKeyIntent; keyUsage?: KmsKeyUsage;
isReserved?: boolean; isReserved?: boolean;
name?: string; name?: string;
description?: string; description?: string;
@@ -91,10 +91,10 @@ export type TGetKeyMaterialDTO = {
export type TImportKeyMaterialDTO = { export type TImportKeyMaterialDTO = {
key: Buffer; key: Buffer;
algorithm: SymmetricKeyEncryptDecrypt; algorithm: SymmetricKeyAlgorithm;
name?: string; name?: string;
isReserved: boolean; isReserved: boolean;
projectId: string; projectId: string;
orgId: string; orgId: string;
type: KmsKeyIntent; keyUsage: KmsKeyUsage;
}; };
+8 -12
View File
@@ -1,21 +1,17 @@
import { import { AsymmetricKeyAlgorithm, KmsKeyUsage, SymmetricKeyAlgorithm } from "@app/hooks/api/cmeks";
AsymmetricKeySignVerify,
KmsKeyIntent,
SymmetricKeyEncryptDecrypt
} from "@app/hooks/api/cmeks";
export const kmsKeyUsageOptions: Record< export const kmsKeyUsageOptions: Record<
KmsKeyIntent, KmsKeyUsage,
{ {
label: string; label: string;
tooltip: string; tooltip: string;
} }
> = { > = {
[KmsKeyIntent.ENCRYPT_DECRYPT]: { [KmsKeyUsage.ENCRYPT_DECRYPT]: {
label: "Encrypt/Decrypt", label: "Encrypt/Decrypt",
tooltip: "Use the key only to encrypt and decrypt data." tooltip: "Use the key only to encrypt and decrypt data."
}, },
[KmsKeyIntent.SIGN_VERIFY]: { [KmsKeyUsage.SIGN_VERIFY]: {
label: "Sign/Verify", label: "Sign/Verify",
tooltip: tooltip:
"Key pairs for digital signing. Uses the private key for signing and the public key for verification." "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< export const keyUsageDefaultOption: Record<
KmsKeyIntent, KmsKeyUsage,
SymmetricKeyEncryptDecrypt | AsymmetricKeySignVerify SymmetricKeyAlgorithm | AsymmetricKeyAlgorithm
> = { > = {
[KmsKeyIntent.ENCRYPT_DECRYPT]: SymmetricKeyEncryptDecrypt.AES_GCM_256, [KmsKeyUsage.ENCRYPT_DECRYPT]: SymmetricKeyAlgorithm.AES_GCM_256,
[KmsKeyIntent.SIGN_VERIFY]: AsymmetricKeySignVerify.RSA_4096 [KmsKeyUsage.SIGN_VERIFY]: AsymmetricKeyAlgorithm.RSA_4096
}; };
+8 -8
View File
@@ -2,17 +2,17 @@ import { z } from "zod";
import { OrderByDirection } from "@app/hooks/api/generic/types"; import { OrderByDirection } from "@app/hooks/api/generic/types";
export enum KmsKeyIntent { export enum KmsKeyUsage {
ENCRYPT_DECRYPT = "encrypt-decrypt", ENCRYPT_DECRYPT = "encrypt-decrypt",
SIGN_VERIFY = "sign-verify" SIGN_VERIFY = "sign-verify"
} }
export type TCmek = { export type TCmek = {
id: string; id: string;
type: KmsKeyIntent; keyUsage: KmsKeyUsage;
name: string; name: string;
description?: string; description?: string;
encryptionAlgorithm: AsymmetricKeySignVerify | SymmetricKeyEncryptDecrypt; encryptionAlgorithm: AsymmetricKeyAlgorithm | SymmetricKeyAlgorithm;
projectId: string; projectId: string;
isDisabled: boolean; isDisabled: boolean;
isReserved: boolean; isReserved: boolean;
@@ -25,7 +25,7 @@ export type TCmek = {
type ProjectRef = { projectId: string }; type ProjectRef = { projectId: string };
type KeyRef = { keyId: string }; type KeyRef = { keyId: string };
export type TCreateCmek = Pick<TCmek, "name" | "description" | "encryptionAlgorithm" | "type"> & export type TCreateCmek = Pick<TCmek, "name" | "description" | "encryptionAlgorithm" | "keyUsage"> &
ProjectRef; ProjectRef;
export type TUpdateCmek = KeyRef & export type TUpdateCmek = KeyRef &
Partial<Pick<TCmek, "name" | "description" | "isDisabled">> & Partial<Pick<TCmek, "name" | "description" | "isDisabled">> &
@@ -80,20 +80,20 @@ export enum CmekOrderBy {
Name = "name" Name = "name"
} }
export enum AsymmetricKeySignVerify { export enum AsymmetricKeyAlgorithm {
RSA_4096 = "rsa-4096", RSA_4096 = "rsa-4096",
ECC_NIST_P256 = "ecc-nist-p256" ECC_NIST_P256 = "ecc-nist-p256"
} }
// Supported symmetric encrypt/decrypt algorithms // Supported symmetric encrypt/decrypt algorithms
export enum SymmetricKeyEncryptDecrypt { export enum SymmetricKeyAlgorithm {
AES_GCM_256 = "aes-256-gcm", AES_GCM_256 = "aes-256-gcm",
AES_GCM_128 = "aes-128-gcm" AES_GCM_128 = "aes-128-gcm"
} }
export const AllowedEncryptionKeyAlgorithms = z.enum([ export const AllowedEncryptionKeyAlgorithms = z.enum([
...Object.values(SymmetricKeyEncryptDecrypt), ...Object.values(SymmetricKeyAlgorithm),
...Object.values(AsymmetricKeySignVerify) ...Object.values(AsymmetricKeyAlgorithm)
] as [string, ...string[]]).options; ] as [string, ...string[]]).options;
export enum SigningAlgorithm { export enum SigningAlgorithm {
@@ -18,9 +18,9 @@ import { useWorkspace } from "@app/context";
import { keyUsageDefaultOption, kmsKeyUsageOptions } from "@app/helpers/kms"; import { keyUsageDefaultOption, kmsKeyUsageOptions } from "@app/helpers/kms";
import { import {
AllowedEncryptionKeyAlgorithms, AllowedEncryptionKeyAlgorithms,
AsymmetricKeySignVerify, AsymmetricKeyAlgorithm,
KmsKeyIntent, KmsKeyUsage,
SymmetricKeyEncryptDecrypt, SymmetricKeyAlgorithm,
TCmek, TCmek,
useCreateCmek, useCreateCmek,
useUpdateCmek useUpdateCmek
@@ -31,7 +31,7 @@ const formSchema = z.object({
name: slugSchema({ min: 1, max: 32, field: "Name" }), name: slugSchema({ min: 1, max: 32, field: "Name" }),
description: z.string().max(500).optional(), description: z.string().max(500).optional(),
encryptionAlgorithm: z.enum(AllowedEncryptionKeyAlgorithms), encryptionAlgorithm: z.enum(AllowedEncryptionKeyAlgorithms),
type: z.nativeEnum(KmsKeyIntent) keyUsage: z.nativeEnum(KmsKeyUsage)
}); });
export type FormData = z.infer<typeof formSchema>; export type FormData = z.infer<typeof formSchema>;
@@ -65,22 +65,25 @@ const CmekForm = ({ onComplete, cmek }: FormProps) => {
defaultValues: { defaultValues: {
name: cmek?.name, name: cmek?.name,
description: cmek?.description, description: cmek?.description,
encryptionAlgorithm: SymmetricKeyEncryptDecrypt.AES_GCM_256, encryptionAlgorithm: SymmetricKeyAlgorithm.AES_GCM_256,
type: KmsKeyIntent.ENCRYPT_DECRYPT keyUsage: KmsKeyUsage.ENCRYPT_DECRYPT
} }
}); });
const handleCreateCmek = async ({ encryptionAlgorithm, name, description, type }: FormData) => { const handleCreateCmek = async ({
encryptionAlgorithm,
name,
description,
keyUsage
}: FormData) => {
const mutation = isUpdate const mutation = isUpdate
? updateCmek.mutateAsync({ keyId: cmek.id, projectId, name, description }) ? updateCmek.mutateAsync({ keyId: cmek.id, projectId, name, description })
: createCmek.mutateAsync({ : createCmek.mutateAsync({
projectId, projectId,
name, name,
description, description,
type, keyUsage,
encryptionAlgorithm: encryptionAlgorithm as encryptionAlgorithm: encryptionAlgorithm as AsymmetricKeyAlgorithm | SymmetricKeyAlgorithm
| AsymmetricKeySignVerify
| SymmetricKeyEncryptDecrypt
}); });
try { try {
@@ -99,7 +102,7 @@ const CmekForm = ({ onComplete, cmek }: FormProps) => {
} }
}; };
const selectedType = watch("type"); const selectedKeyUsage = watch("keyUsage");
return ( return (
<form onSubmit={handleSubmit(handleCreateCmek)}> <form onSubmit={handleSubmit(handleCreateCmek)}>
@@ -116,13 +119,13 @@ const CmekForm = ({ onComplete, cmek }: FormProps) => {
<> <>
<Controller <Controller
control={control} control={control}
name="type" name="keyUsage"
render={({ field: { onChange, ...field }, fieldState: { error } }) => ( render={({ field: { onChange, ...field }, fieldState: { error } }) => (
<FormControl <FormControl
className="w-full" className="w-full"
tooltipText={ tooltipText={
<div className="space-y-4"> <div className="space-y-4">
{Object.entries(KmsKeyIntent).map(([key, value]) => ( {Object.entries(KmsKeyUsage).map(([key, value]) => (
<div key={`key-usage-${key}`}> <div key={`key-usage-${key}`}>
<p className="font-bold">{kmsKeyUsageOptions[value].label}</p> <p className="font-bold">{kmsKeyUsageOptions[value].label}</p>
<p>{kmsKeyUsageOptions[value].tooltip}</p> <p>{kmsKeyUsageOptions[value].tooltip}</p>
@@ -137,8 +140,8 @@ const CmekForm = ({ onComplete, cmek }: FormProps) => {
<Select <Select
defaultValue={field.value} defaultValue={field.value}
onValueChange={(e) => { onValueChange={(e) => {
if (keyUsageDefaultOption[e as KmsKeyIntent]) { if (keyUsageDefaultOption[e as KmsKeyUsage]) {
setValue("encryptionAlgorithm", keyUsageDefaultOption[e as KmsKeyIntent], { setValue("encryptionAlgorithm", keyUsageDefaultOption[e as KmsKeyUsage], {
shouldDirty: true, shouldDirty: true,
shouldValidate: true shouldValidate: true
}); });
@@ -148,7 +151,7 @@ const CmekForm = ({ onComplete, cmek }: FormProps) => {
}} }}
className="w-full" className="w-full"
> >
{Object.entries(KmsKeyIntent)?.map(([key, value]) => ( {Object.entries(KmsKeyUsage)?.map(([key, value]) => (
<SelectItem value={value} key={`key-usage-${key}`}> <SelectItem value={value} key={`key-usage-${key}`}>
{kmsKeyUsageOptions[value].label} {kmsKeyUsageOptions[value].label}
</SelectItem> </SelectItem>
@@ -176,14 +179,14 @@ const CmekForm = ({ onComplete, cmek }: FormProps) => {
{Object.entries(AllowedEncryptionKeyAlgorithms) {Object.entries(AllowedEncryptionKeyAlgorithms)
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
?.filter(([_, value]) => { ?.filter(([_, value]) => {
if (selectedType === KmsKeyIntent.ENCRYPT_DECRYPT) { if (selectedKeyUsage === KmsKeyUsage.ENCRYPT_DECRYPT) {
return Object.values(SymmetricKeyEncryptDecrypt).includes( return Object.values(SymmetricKeyAlgorithm).includes(
value as unknown as SymmetricKeyEncryptDecrypt value as unknown as SymmetricKeyAlgorithm
); );
} }
if (selectedType === KmsKeyIntent.SIGN_VERIFY) { if (selectedKeyUsage === KmsKeyUsage.SIGN_VERIFY) {
return Object.values(AsymmetricKeySignVerify).includes( return Object.values(AsymmetricKeyAlgorithm).includes(
value as unknown as AsymmetricKeySignVerify value as unknown as AsymmetricKeyAlgorithm
); );
} }
@@ -55,7 +55,7 @@ import {
import { kmsKeyUsageOptions } from "@app/helpers/kms"; import { kmsKeyUsageOptions } from "@app/helpers/kms";
import { usePagination, usePopUp, useResetPageHelper, useTimedReset } from "@app/hooks"; import { usePagination, usePopUp, useResetPageHelper, useTimedReset } from "@app/hooks";
import { useGetCmeksByProjectId, useUpdateCmek } from "@app/hooks/api/cmeks"; import { useGetCmeksByProjectId, useUpdateCmek } from "@app/hooks/api/cmeks";
import { CmekOrderBy, KmsKeyIntent, TCmek } from "@app/hooks/api/cmeks/types"; import { CmekOrderBy, KmsKeyUsage, TCmek } from "@app/hooks/api/cmeks/types";
import { OrderByDirection } from "@app/hooks/api/generic/types"; import { OrderByDirection } from "@app/hooks/api/generic/types";
import { CmekDecryptModal } from "./CmekDecryptModal"; import { CmekDecryptModal } from "./CmekDecryptModal";
@@ -273,8 +273,15 @@ export const CmekTable = () => {
{!isPending && {!isPending &&
keys.length > 0 && keys.length > 0 &&
keys.map((cmek) => { keys.map((cmek) => {
const { name, id, version, description, encryptionAlgorithm, isDisabled, type } = const {
cmek; name,
id,
version,
description,
encryptionAlgorithm,
isDisabled,
keyUsage
} = cmek;
const { variant, label } = getStatusBadgeProps(isDisabled); const { variant, label } = getStatusBadgeProps(isDisabled);
return ( return (
@@ -314,8 +321,8 @@ export const CmekTable = () => {
</Td> </Td>
<Td> <Td>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{kmsKeyUsageOptions[type].label} {kmsKeyUsageOptions[keyUsage].label}
<Tooltip content={kmsKeyUsageOptions[type].tooltip}> <Tooltip content={kmsKeyUsageOptions[keyUsage].tooltip}>
<FontAwesomeIcon icon={faInfoCircle} className="text-mineshaft-400" /> <FontAwesomeIcon icon={faInfoCircle} className="text-mineshaft-400" />
</Tooltip> </Tooltip>
</div> </div>
@@ -339,7 +346,7 @@ export const CmekTable = () => {
</IconButton> </IconButton>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent className="min-w-[160px]"> <DropdownMenuContent className="min-w-[160px]">
{type === KmsKeyIntent.ENCRYPT_DECRYPT && ( {keyUsage === KmsKeyUsage.ENCRYPT_DECRYPT && (
<> <>
<Tooltip <Tooltip
content={ content={
@@ -388,7 +395,7 @@ export const CmekTable = () => {
</> </>
)} )}
{type === KmsKeyIntent.SIGN_VERIFY && ( {keyUsage === KmsKeyUsage.SIGN_VERIFY && (
<> <>
<Tooltip <Tooltip
content={ content={