mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 10:27:26 +00:00
feat: kmip create and get
This commit is contained in:
Vendored
+8
@@ -16,6 +16,8 @@ import { TExternalKmsServiceFactory } from "@app/ee/services/external-kms/extern
|
|||||||
import { TGroupServiceFactory } from "@app/ee/services/group/group-service";
|
import { TGroupServiceFactory } from "@app/ee/services/group/group-service";
|
||||||
import { TIdentityProjectAdditionalPrivilegeServiceFactory } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service";
|
import { TIdentityProjectAdditionalPrivilegeServiceFactory } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service";
|
||||||
import { TIdentityProjectAdditionalPrivilegeV2ServiceFactory } from "@app/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service";
|
import { TIdentityProjectAdditionalPrivilegeV2ServiceFactory } from "@app/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service";
|
||||||
|
import { TKmipClientDALFactory } from "@app/ee/services/kmip/kmip-client-dal";
|
||||||
|
import { TKmipOperationServiceFactory } from "@app/ee/services/kmip/kmip-operation-service";
|
||||||
import { TKmipServiceFactory } from "@app/ee/services/kmip/kmip-service";
|
import { TKmipServiceFactory } from "@app/ee/services/kmip/kmip-service";
|
||||||
import { TLdapConfigServiceFactory } from "@app/ee/services/ldap-config/ldap-config-service";
|
import { TLdapConfigServiceFactory } from "@app/ee/services/ldap-config/ldap-config-service";
|
||||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
@@ -121,6 +123,10 @@ declare module "fastify" {
|
|||||||
isUserCompleted: string;
|
isUserCompleted: string;
|
||||||
providerAuthToken: string;
|
providerAuthToken: string;
|
||||||
};
|
};
|
||||||
|
kmipUser: {
|
||||||
|
projectId: string;
|
||||||
|
clientId: string;
|
||||||
|
};
|
||||||
auditLogInfo: Pick<TCreateAuditLogDTO, "userAgent" | "userAgentType" | "ipAddress" | "actor">;
|
auditLogInfo: Pick<TCreateAuditLogDTO, "userAgent" | "userAgentType" | "ipAddress" | "actor">;
|
||||||
ssoConfig: Awaited<ReturnType<TSamlConfigServiceFactory["getSaml"]>>;
|
ssoConfig: Awaited<ReturnType<TSamlConfigServiceFactory["getSaml"]>>;
|
||||||
ldapConfig: Awaited<ReturnType<TLdapConfigServiceFactory["getLdapCfg"]>>;
|
ldapConfig: Awaited<ReturnType<TLdapConfigServiceFactory["getLdapCfg"]>>;
|
||||||
@@ -214,11 +220,13 @@ declare module "fastify" {
|
|||||||
appConnection: TAppConnectionServiceFactory;
|
appConnection: TAppConnectionServiceFactory;
|
||||||
secretSync: TSecretSyncServiceFactory;
|
secretSync: TSecretSyncServiceFactory;
|
||||||
kmip: TKmipServiceFactory;
|
kmip: TKmipServiceFactory;
|
||||||
|
kmipOperation: TKmipOperationServiceFactory;
|
||||||
};
|
};
|
||||||
// this is exclusive use for middlewares in which we need to inject data
|
// this is exclusive use for middlewares in which we need to inject data
|
||||||
// everywhere else access using service layer
|
// everywhere else access using service layer
|
||||||
store: {
|
store: {
|
||||||
user: Pick<TUserDALFactory, "findById">;
|
user: Pick<TUserDALFactory, "findById">;
|
||||||
|
kmipClient: Pick<TKmipClientDALFactory, "findOne">;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { registerDynamicSecretRouter } from "./dynamic-secret-router";
|
|||||||
import { registerExternalKmsRouter } from "./external-kms-router";
|
import { registerExternalKmsRouter } from "./external-kms-router";
|
||||||
import { registerGroupRouter } from "./group-router";
|
import { registerGroupRouter } from "./group-router";
|
||||||
import { registerIdentityProjectAdditionalPrivilegeRouter } from "./identity-project-additional-privilege-router";
|
import { registerIdentityProjectAdditionalPrivilegeRouter } from "./identity-project-additional-privilege-router";
|
||||||
|
import { registerKmipOperationRouter } from "./kmip-operation-router";
|
||||||
import { registerKmipRouter } from "./kmip-router";
|
import { registerKmipRouter } from "./kmip-router";
|
||||||
import { registerLdapRouter } from "./ldap-router";
|
import { registerLdapRouter } from "./ldap-router";
|
||||||
import { registerLicenseRouter } from "./license-router";
|
import { registerLicenseRouter } from "./license-router";
|
||||||
@@ -112,4 +113,5 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => {
|
|||||||
|
|
||||||
await server.register(registerProjectTemplateRouter, { prefix: "/project-templates" });
|
await server.register(registerProjectTemplateRouter, { prefix: "/project-templates" });
|
||||||
await server.register(registerKmipRouter, { prefix: "/kmip" });
|
await server.register(registerKmipRouter, { prefix: "/kmip" });
|
||||||
|
await server.register(registerKmipOperationRouter, { prefix: "/kmip-operations" });
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
import crypto from "crypto";
|
||||||
|
import jwt, { JwtPayload } from "jsonwebtoken";
|
||||||
|
import z from "zod";
|
||||||
|
|
||||||
|
import { KmsKeysSchema } from "@app/db/schemas";
|
||||||
|
import { SymmetricEncryption } from "@app/lib/crypto/cipher";
|
||||||
|
import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
|
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { CertKeyAlgorithm } from "@app/services/certificate/certificate-types";
|
||||||
|
|
||||||
|
export const registerKmipOperationRouter = async (server: FastifyZodProvider) => {
|
||||||
|
server.decorateRequest("kmipUser", null);
|
||||||
|
|
||||||
|
server.addHook("preHandler", async (req) => {
|
||||||
|
const token = req.headers["x-kmip-jwt"] as string;
|
||||||
|
const serverCertSerialNumber = req.headers["x-server-certificate-serial-number"] as string;
|
||||||
|
|
||||||
|
if (!jwt) {
|
||||||
|
throw new ForbiddenRequestError({
|
||||||
|
message: "Missing KMIP JWT"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!serverCertSerialNumber) {
|
||||||
|
throw new ForbiddenRequestError({
|
||||||
|
message: "Missing server certificate serial number from request"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const serverCert = await server.services.kmip.getServerCertificateBySerialNumber(serverCertSerialNumber);
|
||||||
|
|
||||||
|
// TODO: assert that server certificate used is not revoked
|
||||||
|
// TODO: assert that client certificate used is not revoked
|
||||||
|
|
||||||
|
const publicKey = crypto.createPublicKey({
|
||||||
|
key: serverCert.publicKey,
|
||||||
|
format: "pem",
|
||||||
|
type: [CertKeyAlgorithm.ECDSA_P256, CertKeyAlgorithm.ECDSA_P384].includes(serverCert.keyAlgorithm)
|
||||||
|
? "spki"
|
||||||
|
: "pkcs1"
|
||||||
|
});
|
||||||
|
|
||||||
|
const decodedToken = jwt.verify(token, publicKey) as JwtPayload & { projectId: string; clientId: string };
|
||||||
|
|
||||||
|
const kmipClient = await server.store.kmipClient.findOne({
|
||||||
|
id: decodedToken.clientId,
|
||||||
|
projectId: decodedToken.projectId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!kmipClient) {
|
||||||
|
throw new NotFoundError({
|
||||||
|
message: "KMIP client cannot be found."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
req.kmipUser = {
|
||||||
|
projectId: decodedToken.projectId,
|
||||||
|
clientId: decodedToken.clientId
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "POST",
|
||||||
|
url: "/create",
|
||||||
|
config: {
|
||||||
|
rateLimit: writeLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
description: "KMIP endpoint for creating managed objects",
|
||||||
|
body: z.object({
|
||||||
|
encryptionAlgorithm: z.nativeEnum(SymmetricEncryption)
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: KmsKeysSchema
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handler: async (req) => {
|
||||||
|
const object = await server.services.kmipOperation.create({
|
||||||
|
projectId: req.kmipUser.projectId,
|
||||||
|
clientId: req.kmipUser.clientId,
|
||||||
|
encryptionAlgorithm: req.body.encryptionAlgorithm
|
||||||
|
});
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "POST",
|
||||||
|
url: "/get",
|
||||||
|
config: {
|
||||||
|
rateLimit: writeLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
description: "KMIP endpoint for getting managed objects",
|
||||||
|
body: z.object({
|
||||||
|
id: z.string()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
id: z.string(),
|
||||||
|
value: z.string(),
|
||||||
|
algorithm: z.string()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handler: async (req) => {
|
||||||
|
const object = await server.services.kmipOperation.get({
|
||||||
|
projectId: req.kmipUser.projectId,
|
||||||
|
clientId: req.kmipUser.clientId,
|
||||||
|
id: req.body.id
|
||||||
|
});
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
import { ProjectType } from "@app/db/schemas";
|
||||||
|
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 { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
|
|
||||||
|
import { TKmipClientDALFactory } from "./kmip-client-dal";
|
||||||
|
import { KmipPermission } from "./kmip-enum";
|
||||||
|
import { TKmipCreateDTO, TKmipGetDTO } from "./kmip-types";
|
||||||
|
|
||||||
|
type TKmipOperationServiceFactoryDep = {
|
||||||
|
kmsService: TKmsServiceFactory;
|
||||||
|
kmsDAL: TKmsKeyDALFactory;
|
||||||
|
kmipClientDAL: TKmipClientDALFactory;
|
||||||
|
projectDAL: Pick<TProjectDALFactory, "getProjectFromSplitId" | "findById">;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TKmipOperationServiceFactory = ReturnType<typeof kmipOperationServiceFactory>;
|
||||||
|
|
||||||
|
export const kmipOperationServiceFactory = ({
|
||||||
|
kmsService,
|
||||||
|
kmsDAL,
|
||||||
|
projectDAL,
|
||||||
|
kmipClientDAL
|
||||||
|
}: TKmipOperationServiceFactoryDep) => {
|
||||||
|
const create = async ({ projectId: preSplitProjectId, clientId, encryptionAlgorithm }: TKmipCreateDTO) => {
|
||||||
|
let projectId = preSplitProjectId;
|
||||||
|
const cmekProjectFromSplit = await projectDAL.getProjectFromSplitId(projectId, ProjectType.KMS);
|
||||||
|
if (cmekProjectFromSplit) {
|
||||||
|
projectId = cmekProjectFromSplit.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const project = await projectDAL.findById(projectId);
|
||||||
|
const kmipClient = await kmipClientDAL.findOne({
|
||||||
|
id: clientId,
|
||||||
|
projectId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!kmipClient.permissions?.includes(KmipPermission.Create)) {
|
||||||
|
throw new ForbiddenRequestError({
|
||||||
|
message: "Client does not have sufficient permission to perform KMIP create"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const kmsKey = await kmsService.generateKmsKey({
|
||||||
|
encryptionAlgorithm,
|
||||||
|
orgId: project.orgId,
|
||||||
|
projectId,
|
||||||
|
isReserved: false
|
||||||
|
});
|
||||||
|
|
||||||
|
return kmsKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
const get = async ({ projectId: preSplitProjectId, id, clientId }: TKmipGetDTO) => {
|
||||||
|
let projectId = preSplitProjectId;
|
||||||
|
const cmekProjectFromSplit = await projectDAL.getProjectFromSplitId(projectId, ProjectType.KMS);
|
||||||
|
|
||||||
|
if (cmekProjectFromSplit) {
|
||||||
|
projectId = cmekProjectFromSplit.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const kmipClient = await kmipClientDAL.findOne({
|
||||||
|
id: clientId,
|
||||||
|
projectId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!kmipClient.permissions?.includes(KmipPermission.Get)) {
|
||||||
|
throw new ForbiddenRequestError({
|
||||||
|
message: "Client does not have sufficient permission to perform KMIP get"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = await kmsDAL.findOne({
|
||||||
|
id,
|
||||||
|
projectId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!key) {
|
||||||
|
throw new NotFoundError({ message: `Key with ID ${id} not found` });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.isReserved) {
|
||||||
|
throw new BadRequestError({ message: "Cannot get reserved keys" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const completeKeyDetails = await kmsDAL.findByIdWithAssociatedKms(id);
|
||||||
|
|
||||||
|
if (!completeKeyDetails.internalKms) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Cannot get external key"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const kmsKey = await kmsService.getKeyMaterial({
|
||||||
|
kmsId: key.id
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: key.id,
|
||||||
|
value: kmsKey.toString("base64"),
|
||||||
|
algorithm: completeKeyDetails.internalKms.encryptionAlgorithm
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
create,
|
||||||
|
get
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -18,6 +18,7 @@ import { TKmipClientCertificateDALFactory } from "./kmip-client-certificate-dal"
|
|||||||
import { TKmipClientDALFactory } from "./kmip-client-dal";
|
import { TKmipClientDALFactory } from "./kmip-client-dal";
|
||||||
import { INSTANCE_KMIP_CONFIG_ID } from "./kmip-constants";
|
import { INSTANCE_KMIP_CONFIG_ID } from "./kmip-constants";
|
||||||
import { TKmipInstanceConfigDALFactory } from "./kmip-instance-config-dal";
|
import { TKmipInstanceConfigDALFactory } from "./kmip-instance-config-dal";
|
||||||
|
import { TKmipInstanceServerCertificateDALFactory } from "./kmip-instance-server-certificate-dal";
|
||||||
import {
|
import {
|
||||||
TCreateKmipClientCertificateDTO,
|
TCreateKmipClientCertificateDTO,
|
||||||
TCreateKmipClientDTO,
|
TCreateKmipClientDTO,
|
||||||
@@ -30,6 +31,7 @@ import {
|
|||||||
type TKmipServiceFactoryDep = {
|
type TKmipServiceFactoryDep = {
|
||||||
kmipClientDAL: TKmipClientDALFactory;
|
kmipClientDAL: TKmipClientDALFactory;
|
||||||
kmipClientCertificateDAL: TKmipClientCertificateDALFactory;
|
kmipClientCertificateDAL: TKmipClientCertificateDALFactory;
|
||||||
|
kmipInstanceServerCertificateDAL: TKmipInstanceServerCertificateDALFactory;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
kmsService: Pick<TKmsServiceFactory, "decryptWithRootKey">;
|
kmsService: Pick<TKmsServiceFactory, "decryptWithRootKey">;
|
||||||
kmipInstanceConfigDAL: TKmipInstanceConfigDALFactory;
|
kmipInstanceConfigDAL: TKmipInstanceConfigDALFactory;
|
||||||
@@ -42,7 +44,8 @@ export const kmipServiceFactory = ({
|
|||||||
permissionService,
|
permissionService,
|
||||||
kmipClientCertificateDAL,
|
kmipClientCertificateDAL,
|
||||||
kmipInstanceConfigDAL,
|
kmipInstanceConfigDAL,
|
||||||
kmsService
|
kmsService,
|
||||||
|
kmipInstanceServerCertificateDAL
|
||||||
}: TKmipServiceFactoryDep) => {
|
}: TKmipServiceFactoryDep) => {
|
||||||
const createKmipClient = async ({
|
const createKmipClient = async ({
|
||||||
actor,
|
actor,
|
||||||
@@ -325,12 +328,33 @@ export const kmipServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getServerCertificateBySerialNumber = async (serialNumber: string) => {
|
||||||
|
const serverCert = await kmipInstanceServerCertificateDAL.findOne({
|
||||||
|
serialNumber
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!serverCert) {
|
||||||
|
throw new NotFoundError({
|
||||||
|
message: "Server certificate not found"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const decryptWithRootKey = kmsService.decryptWithRootKey();
|
||||||
|
const parsedCertificate = new x509.X509Certificate(decryptWithRootKey(serverCert.encryptedCertificate));
|
||||||
|
|
||||||
|
return {
|
||||||
|
publicKey: parsedCertificate.publicKey.toString("pem"),
|
||||||
|
keyAlgorithm: serverCert.keyAlgorithm as CertKeyAlgorithm
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createKmipClient,
|
createKmipClient,
|
||||||
updateKmipClient,
|
updateKmipClient,
|
||||||
deleteKmipClient,
|
deleteKmipClient,
|
||||||
getKmipClient,
|
getKmipClient,
|
||||||
listKmipClientsByProjectId,
|
listKmipClientsByProjectId,
|
||||||
createKmipClientCertificate
|
createKmipClientCertificate,
|
||||||
|
getServerCertificateBySerialNumber
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { SymmetricEncryption } from "@app/lib/crypto/cipher";
|
||||||
import { OrderByDirection, TProjectPermission } from "@app/lib/types";
|
import { OrderByDirection, TProjectPermission } from "@app/lib/types";
|
||||||
import { CertKeyAlgorithm } from "@app/services/certificate/certificate-types";
|
import { CertKeyAlgorithm } from "@app/services/certificate/certificate-types";
|
||||||
|
|
||||||
@@ -41,3 +42,15 @@ export type TListKmipClientsByProjectIdDTO = {
|
|||||||
orderDirection?: OrderByDirection;
|
orderDirection?: OrderByDirection;
|
||||||
search?: string;
|
search?: string;
|
||||||
} & TProjectPermission;
|
} & TProjectPermission;
|
||||||
|
|
||||||
|
export type TKmipCreateDTO = {
|
||||||
|
clientId: string;
|
||||||
|
projectId: string;
|
||||||
|
encryptionAlgorithm: SymmetricEncryption;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TKmipGetDTO = {
|
||||||
|
clientId: string;
|
||||||
|
projectId: string;
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import { kmipClientCertificateDALFactory } from "@app/ee/services/kmip/kmip-clie
|
|||||||
import { kmipClientDALFactory } from "@app/ee/services/kmip/kmip-client-dal";
|
import { kmipClientDALFactory } from "@app/ee/services/kmip/kmip-client-dal";
|
||||||
import { kmipInstanceConfigDALFactory } from "@app/ee/services/kmip/kmip-instance-config-dal";
|
import { kmipInstanceConfigDALFactory } from "@app/ee/services/kmip/kmip-instance-config-dal";
|
||||||
import { kmipInstanceServerCertificateDALFactory } from "@app/ee/services/kmip/kmip-instance-server-certificate-dal";
|
import { kmipInstanceServerCertificateDALFactory } from "@app/ee/services/kmip/kmip-instance-server-certificate-dal";
|
||||||
|
import { kmipOperationServiceFactory } from "@app/ee/services/kmip/kmip-operation-service";
|
||||||
import { kmipServiceFactory } from "@app/ee/services/kmip/kmip-service";
|
import { kmipServiceFactory } from "@app/ee/services/kmip/kmip-service";
|
||||||
import { ldapConfigDALFactory } from "@app/ee/services/ldap-config/ldap-config-dal";
|
import { ldapConfigDALFactory } from "@app/ee/services/ldap-config/ldap-config-dal";
|
||||||
import { ldapConfigServiceFactory } from "@app/ee/services/ldap-config/ldap-config-service";
|
import { ldapConfigServiceFactory } from "@app/ee/services/ldap-config/ldap-config-service";
|
||||||
@@ -1434,7 +1435,15 @@ export const registerRoutes = async (
|
|||||||
permissionService,
|
permissionService,
|
||||||
kmipClientCertificateDAL,
|
kmipClientCertificateDAL,
|
||||||
kmipInstanceConfigDAL,
|
kmipInstanceConfigDAL,
|
||||||
kmsService
|
kmsService,
|
||||||
|
kmipInstanceServerCertificateDAL
|
||||||
|
});
|
||||||
|
|
||||||
|
const kmipOperationService = kmipOperationServiceFactory({
|
||||||
|
kmsService,
|
||||||
|
kmsDAL,
|
||||||
|
projectDAL,
|
||||||
|
kmipClientDAL
|
||||||
});
|
});
|
||||||
|
|
||||||
await superAdminService.initServerCfg();
|
await superAdminService.initServerCfg();
|
||||||
@@ -1536,7 +1545,8 @@ export const registerRoutes = async (
|
|||||||
totp: totpService,
|
totp: totpService,
|
||||||
appConnection: appConnectionService,
|
appConnection: appConnectionService,
|
||||||
secretSync: secretSyncService,
|
secretSync: secretSyncService,
|
||||||
kmip: kmipService
|
kmip: kmipService,
|
||||||
|
kmipOperation: kmipOperationService
|
||||||
});
|
});
|
||||||
|
|
||||||
const cronJobs: CronJob[] = [];
|
const cronJobs: CronJob[] = [];
|
||||||
@@ -1548,7 +1558,8 @@ export const registerRoutes = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
server.decorate<FastifyZodProvider["store"]>("store", {
|
server.decorate<FastifyZodProvider["store"]>("store", {
|
||||||
user: userDAL
|
user: userDAL,
|
||||||
|
kmipClient: kmipClientDAL
|
||||||
});
|
});
|
||||||
|
|
||||||
await server.register(injectIdentity, { userDAL, serviceTokenDAL });
|
await server.register(injectIdentity, { userDAL, serviceTokenDAL });
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import {
|
|||||||
TEncryptWithKmsDataKeyDTO,
|
TEncryptWithKmsDataKeyDTO,
|
||||||
TEncryptWithKmsDTO,
|
TEncryptWithKmsDTO,
|
||||||
TGenerateKMSDTO,
|
TGenerateKMSDTO,
|
||||||
|
TGetKeyMaterialDTO,
|
||||||
TUpdateProjectSecretManagerKmsKeyDTO
|
TUpdateProjectSecretManagerKmsKeyDTO
|
||||||
} from "./kms-types";
|
} from "./kms-types";
|
||||||
|
|
||||||
@@ -326,6 +327,30 @@ export const kmsServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getKeyMaterial = async ({ kmsId }: TGetKeyMaterialDTO) => {
|
||||||
|
const kmsDoc = await kmsDAL.findByIdWithAssociatedKms(kmsId);
|
||||||
|
if (!kmsDoc) {
|
||||||
|
throw new NotFoundError({ message: `KMS with ID '${kmsId}' not found` });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kmsDoc.isReserved) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Cannot get key material for reserved key"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kmsDoc.externalKms) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Cannot get key material for external key"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyCipher = symmetricCipherService(SymmetricEncryption.AES_GCM_256);
|
||||||
|
const kmsKey = keyCipher.decrypt(kmsDoc.internalKms?.encryptedKey as Buffer, ROOT_ENCRYPTION_KEY);
|
||||||
|
|
||||||
|
return kmsKey;
|
||||||
|
};
|
||||||
|
|
||||||
const encryptWithKmsKey = async ({ kmsId }: Omit<TEncryptWithKmsDTO, "plainText">, tx?: Knex) => {
|
const encryptWithKmsKey = async ({ kmsId }: Omit<TEncryptWithKmsDTO, "plainText">, tx?: Knex) => {
|
||||||
const kmsDoc = await kmsDAL.findByIdWithAssociatedKms(kmsId, tx);
|
const kmsDoc = await kmsDAL.findByIdWithAssociatedKms(kmsId, tx);
|
||||||
if (!kmsDoc) {
|
if (!kmsDoc) {
|
||||||
@@ -967,6 +992,7 @@ export const kmsServiceFactory = ({
|
|||||||
getProjectKeyBackup,
|
getProjectKeyBackup,
|
||||||
loadProjectKeyBackup,
|
loadProjectKeyBackup,
|
||||||
getKmsById,
|
getKmsById,
|
||||||
createCipherPairWithDataKey
|
createCipherPairWithDataKey,
|
||||||
|
getKeyMaterial
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -61,3 +61,6 @@ export enum RootKeyEncryptionStrategy {
|
|||||||
Software = "SOFTWARE",
|
Software = "SOFTWARE",
|
||||||
HSM = "HSM"
|
HSM = "HSM"
|
||||||
}
|
}
|
||||||
|
export type TGetKeyMaterialDTO = {
|
||||||
|
kmsId: string;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user