Address PR comments

This commit is contained in:
Carlos Monastyrski
2025-12-02 12:46:12 -03:00
parent 443e4226fb
commit 36ccc3769a
16 changed files with 139 additions and 114 deletions
@@ -665,16 +665,15 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
} }
}, },
handler: async (req) => { handler: async (req) => {
const response = await server.services.internalCertificateAuthority.issueCertFromCa({ const { certificate, certificateChain, issuingCaCertificate, privateKey, serialNumber, ca } =
caId: req.params.caId, await server.services.internalCertificateAuthority.issueCertFromCa({
actor: req.permission.type, caId: req.params.caId,
actorId: req.permission.id, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorAuthMethod: req.permission.authMethod,
...req.body actorOrgId: req.permission.orgId,
}); ...req.body
});
const { certificate, certificateChain, issuingCaCertificate, privateKey, serialNumber, ca } = response;
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
...req.auditLogInfo, ...req.auditLogInfo,
@@ -170,8 +170,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => {
serialNumber: z.string().trim(), serialNumber: z.string().trim(),
certificateId: z.string() certificateId: z.string()
}) })
.nullable() .nullable(),
.optional(),
certificateRequestId: z.string() certificateRequestId: z.string()
}) })
} }
@@ -373,11 +372,9 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => {
...req.auditLogInfo, ...req.auditLogInfo,
projectId: (req.query as { projectId: string }).projectId, projectId: (req.query as { projectId: string }).projectId,
event: { event: {
type: EventType.GET_CERT, type: EventType.GET_CERTIFICATE_REQUEST,
metadata: { metadata: {
certId: req.params.requestId, certificateRequestId: req.params.requestId
cn: "",
serialNumber: data.serialNumber || ""
} }
} }
}); });
@@ -242,15 +242,14 @@ export const registerDeprecatedCertRouter = async (server: FastifyZodProvider) =
} }
}, },
handler: async (req) => { handler: async (req) => {
const response = await server.services.internalCertificateAuthority.issueCertFromCa({ const { certificate, certificateChain, issuingCaCertificate, privateKey, serialNumber, ca } =
actor: req.permission.type, await server.services.internalCertificateAuthority.issueCertFromCa({
actorId: req.permission.id, actor: req.permission.type,
actorAuthMethod: req.permission.authMethod, actorId: req.permission.id,
actorOrgId: req.permission.orgId, actorAuthMethod: req.permission.authMethod,
...req.body actorOrgId: req.permission.orgId,
}); ...req.body
});
const { certificate, certificateChain, issuingCaCertificate, privateKey, serialNumber, ca } = response;
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
...req.auditLogInfo, ...req.auditLogInfo,
@@ -17,6 +17,7 @@ import {
import { extractCertificateRequestFromCSR } from "@app/services/certificate-common/certificate-csr-utils"; import { extractCertificateRequestFromCSR } from "@app/services/certificate-common/certificate-csr-utils";
import { mapEnumsForValidation } from "@app/services/certificate-common/certificate-utils"; import { mapEnumsForValidation } from "@app/services/certificate-common/certificate-utils";
import { EnrollmentType } from "@app/services/certificate-profile/certificate-profile-types"; import { EnrollmentType } from "@app/services/certificate-profile/certificate-profile-types";
import { CertificateRequestStatus } from "@app/services/certificate-request/certificate-request-types";
import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators"; import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators";
import { booleanSchema } from "../sanitizedSchemas"; import { booleanSchema } from "../sanitizedSchemas";
@@ -138,6 +139,7 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
}); });
const certificateRequest = await server.services.certificateRequest.createCertificateRequest({ const certificateRequest = await server.services.certificateRequest.createCertificateRequest({
status: CertificateRequestStatus.ISSUED,
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
@@ -244,6 +246,7 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
const certificateRequest = await server.services.certificateRequest.createCertificateRequest({ const certificateRequest = await server.services.certificateRequest.createCertificateRequest({
actor: req.permission.type, actor: req.permission.type,
status: CertificateRequestStatus.ISSUED,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
@@ -365,6 +368,7 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
}); });
const certificateRequest = await server.services.certificateRequest.createCertificateRequest({ const certificateRequest = await server.services.certificateRequest.createCertificateRequest({
status: CertificateRequestStatus.PENDING,
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
@@ -1575,15 +1575,16 @@ export const internalCertificateAuthorityServiceFactory = ({
keyUsages, keyUsages,
extendedKeyUsages, extendedKeyUsages,
signatureAlgorithm, signatureAlgorithm,
keyAlgorithm keyAlgorithm,
tx
} = dto; } = dto;
let collectionId = pkiCollectionId; let collectionId = pkiCollectionId;
if (caId) { if (caId) {
ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId); ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId, tx);
} else if (certificateTemplateId) { } else if (certificateTemplateId) {
certificateTemplate = await certificateTemplateDAL.getById(certificateTemplateId); certificateTemplate = await certificateTemplateDAL.getById(certificateTemplateId, tx);
if (!certificateTemplate) { if (!certificateTemplate) {
throw new NotFoundError({ throw new NotFoundError({
message: `Certificate template with ID '${certificateTemplateId}' not found` message: `Certificate template with ID '${certificateTemplateId}' not found`
@@ -1591,7 +1592,7 @@ export const internalCertificateAuthorityServiceFactory = ({
} }
collectionId = certificateTemplate.pkiCollectionId as string; collectionId = certificateTemplate.pkiCollectionId as string;
ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(certificateTemplate.caId); ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(certificateTemplate.caId, tx);
} }
if (!ca) { if (!ca) {
@@ -1640,7 +1641,7 @@ export const internalCertificateAuthorityServiceFactory = ({
// check PKI collection // check PKI collection
if (pkiCollectionId) { if (pkiCollectionId) {
const pkiCollection = await pkiCollectionDAL.findById(pkiCollectionId); const pkiCollection = await pkiCollectionDAL.findById(pkiCollectionId, tx);
if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${pkiCollectionId}' not found` }); if (!pkiCollection) throw new NotFoundError({ message: `PKI collection with ID '${pkiCollectionId}' not found` });
if (pkiCollection.projectId !== ca.projectId) throw new BadRequestError({ message: "Invalid PKI collection" }); if (pkiCollection.projectId !== ca.projectId) throw new BadRequestError({ message: "Invalid PKI collection" });
} }
@@ -1909,7 +1910,7 @@ export const internalCertificateAuthorityServiceFactory = ({
plainText: Buffer.from(certificateChainPem) plainText: Buffer.from(certificateChainPem)
}); });
const cert = await certificateDAL.transaction(async (tx) => { const createSignedCert = async (transaction: Knex) => {
const newCert = await certificateDAL.create( const newCert = await certificateDAL.create(
{ {
caId: (ca as TCertificateAuthorities).id, caId: (ca as TCertificateAuthorities).id,
@@ -1928,7 +1929,7 @@ export const internalCertificateAuthorityServiceFactory = ({
keyAlgorithm: keyAlgorithm || ca!.internalCa!.keyAlgorithm, keyAlgorithm: keyAlgorithm || ca!.internalCa!.keyAlgorithm,
signatureAlgorithm: signatureAlgorithm || ca!.internalCa!.keyAlgorithm signatureAlgorithm: signatureAlgorithm || ca!.internalCa!.keyAlgorithm
}, },
tx transaction
); );
await certificateBodyDAL.create( await certificateBodyDAL.create(
@@ -1937,7 +1938,7 @@ export const internalCertificateAuthorityServiceFactory = ({
encryptedCertificate, encryptedCertificate,
encryptedCertificateChain encryptedCertificateChain
}, },
tx transaction
); );
if (collectionId) { if (collectionId) {
@@ -1946,12 +1947,19 @@ export const internalCertificateAuthorityServiceFactory = ({
pkiCollectionId: collectionId, pkiCollectionId: collectionId,
certId: newCert.id certId: newCert.id
}, },
tx transaction
); );
} }
return newCert; return newCert;
}); };
let cert;
if (tx) {
cert = await createSignedCert(tx);
} else {
cert = await certificateDAL.transaction(createSignedCert);
}
return { return {
certificate: leafCert, certificate: leafCert,
@@ -160,6 +160,7 @@ export type TSignCertFromCaDTO =
keyAlgorithm?: string; keyAlgorithm?: string;
isFromProfile?: boolean; isFromProfile?: boolean;
profileId?: string; profileId?: string;
tx?: Knex;
} }
| ({ | ({
isInternal: false; isInternal: false;
@@ -179,6 +180,7 @@ export type TSignCertFromCaDTO =
keyAlgorithm?: string; keyAlgorithm?: string;
isFromProfile?: boolean; isFromProfile?: boolean;
profileId?: string; profileId?: string;
tx?: Knex;
} & Omit<TProjectPermission, "projectId">); } & Omit<TProjectPermission, "projectId">);
export type TGetCaCertificateTemplatesDTO = { export type TGetCaCertificateTemplatesDTO = {
@@ -71,7 +71,8 @@ describe("CertificateRequestService", () => {
actorOrgId: "550e8400-e29b-41d4-a716-446655440002", actorOrgId: "550e8400-e29b-41d4-a716-446655440002",
projectId: "550e8400-e29b-41d4-a716-446655440003", projectId: "550e8400-e29b-41d4-a716-446655440003",
profileId: "550e8400-e29b-41d4-a716-446655440004", profileId: "550e8400-e29b-41d4-a716-446655440004",
commonName: "test.example.com" commonName: "test.example.com",
status: CertificateRequestStatus.PENDING
}; };
it("should create certificate request successfully", async () => { it("should create certificate request successfully", async () => {
@@ -105,12 +106,13 @@ describe("CertificateRequestService", () => {
actionProjectType: ActionProjectType.CertificateManager actionProjectType: ActionProjectType.CertificateManager
}); });
expect(mockCertificateRequestDAL.create).toHaveBeenCalledWith( expect(mockCertificateRequestDAL.create).toHaveBeenCalledWith(
expect.objectContaining({ {
status: CertificateRequestStatus.PENDING, status: CertificateRequestStatus.PENDING,
projectId: "550e8400-e29b-41d4-a716-446655440003", projectId: "550e8400-e29b-41d4-a716-446655440003",
profileId: "550e8400-e29b-41d4-a716-446655440004", profileId: "550e8400-e29b-41d4-a716-446655440004",
commonName: "test.example.com" commonName: "test.example.com"
}) },
undefined
); );
expect(result).toEqual(mockCreatedRequest); expect(result).toEqual(mockCreatedRequest);
}); });
@@ -12,6 +12,7 @@ import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal"; import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal";
import { TCertificateServiceFactory } from "@app/services/certificate/certificate-service"; import { TCertificateServiceFactory } from "@app/services/certificate/certificate-service";
import { ActorType } from "../auth/auth-type";
import { TCertificateRequestDALFactory } from "./certificate-request-dal"; import { TCertificateRequestDALFactory } from "./certificate-request-dal";
import { import {
CertificateRequestStatus, CertificateRequestStatus,
@@ -44,7 +45,8 @@ const certificateRequestDataSchema = z
notAfter: z.date().optional(), notAfter: z.date().optional(),
keyAlgorithm: z.string().max(100).optional(), keyAlgorithm: z.string().max(100).optional(),
signatureAlgorithm: z.string().max(100).optional(), signatureAlgorithm: z.string().max(100).optional(),
metadata: z.string().max(2000).optional() metadata: z.string().max(2000).optional(),
certificateId: z.string().optional()
}) })
.refine( .refine(
(data) => { (data) => {
@@ -94,39 +96,36 @@ export const certificateRequestServiceFactory = ({
actorOrgId, actorOrgId,
projectId, projectId,
tx, tx,
status,
...requestData ...requestData
}: TCreateCertificateRequestDTO & { tx?: Knex }) => { }: TCreateCertificateRequestDTO & { tx?: Knex }) => {
const { permission } = await permissionService.getProjectPermission({ if (actor !== ActorType.ACME_ACCOUNT) {
actor, const { permission } = await permissionService.getProjectPermission({
actorId, actor,
projectId, actorId,
actorAuthMethod, projectId,
actorOrgId, actorAuthMethod,
actionProjectType: ActionProjectType.CertificateManager actorOrgId,
}); actionProjectType: ActionProjectType.CertificateManager
});
ForbiddenError.from(permission).throwUnlessCan( ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionCertificateActions.Create, ProjectPermissionCertificateActions.Create,
ProjectPermissionSub.Certificates ProjectPermissionSub.Certificates
); );
}
// Validate input data before creating the request // Validate input data before creating the request
const validatedData = validateCertificateRequestData(requestData); const validatedData = validateCertificateRequestData(requestData);
const certificateRequest = tx const certificateRequest = await certificateRequestDAL.create(
? await certificateRequestDAL.create( {
{ status,
status: CertificateRequestStatus.PENDING, projectId,
projectId, ...validatedData
...validatedData },
}, tx
tx );
)
: await certificateRequestDAL.create({
status: CertificateRequestStatus.PENDING,
projectId,
...validatedData
});
return certificateRequest; return certificateRequest;
}; };
@@ -19,6 +19,8 @@ export type TCreateCertificateRequestDTO = TProjectPermission & {
keyAlgorithm?: string; keyAlgorithm?: string;
signatureAlgorithm?: string; signatureAlgorithm?: string;
metadata?: string; metadata?: string;
status: CertificateRequestStatus;
certificateId?: string;
}; };
export type TGetCertificateRequestDTO = TProjectPermission & { export type TGetCertificateRequestDTO = TProjectPermission & {
@@ -19,10 +19,8 @@ import { TCertificateBodyDALFactory } from "@app/services/certificate/certificat
import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal"; import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal";
import { TCertificateSecretDALFactory } from "@app/services/certificate/certificate-secret-dal"; import { TCertificateSecretDALFactory } from "@app/services/certificate/certificate-secret-dal";
import { import {
CertExtendedKeyUsage,
CertKeyAlgorithm, CertKeyAlgorithm,
CertKeyType, CertKeyType,
CertKeyUsage,
CertSignatureAlgorithm, CertSignatureAlgorithm,
CertStatus CertStatus
} from "@app/services/certificate/certificate-types"; } from "@app/services/certificate/certificate-types";
@@ -58,15 +56,14 @@ import {
bufferToString, bufferToString,
buildCertificateSubjectFromTemplate, buildCertificateSubjectFromTemplate,
buildSubjectAlternativeNamesFromTemplate, buildSubjectAlternativeNamesFromTemplate,
convertExtendedKeyUsageArrayFromLegacy,
convertExtendedKeyUsageArrayToLegacy, convertExtendedKeyUsageArrayToLegacy,
convertKeyUsageArrayFromLegacy,
convertKeyUsageArrayToLegacy, convertKeyUsageArrayToLegacy,
mapEnumsForValidation, mapEnumsForValidation,
normalizeDateForApi, normalizeDateForApi,
removeRootCaFromChain removeRootCaFromChain
} from "../certificate-common/certificate-utils"; } from "../certificate-common/certificate-utils";
import { TCertificateRequestServiceFactory } from "../certificate-request/certificate-request-service"; import { TCertificateRequestServiceFactory } from "../certificate-request/certificate-request-service";
import { CertificateRequestStatus } from "../certificate-request/certificate-request-types";
import { TCertificateSyncDALFactory } from "../certificate-sync/certificate-sync-dal"; import { TCertificateSyncDALFactory } from "../certificate-sync/certificate-sync-dal";
import { TCertificateRequest } from "../certificate-template-v2/certificate-template-v2-types"; import { TCertificateRequest } from "../certificate-template-v2/certificate-template-v2-types";
import { TPkiSyncDALFactory } from "../pki-sync/pki-sync-dal"; import { TPkiSyncDALFactory } from "../pki-sync/pki-sync-dal";
@@ -307,14 +304,15 @@ const extractCertificateFromBuffer = (certData: Buffer | { rawData: Buffer } | s
return bufferToString(certData as unknown as Buffer); return bufferToString(certData as unknown as Buffer);
}; };
const parseKeyUsages = (keyUsages: unknown): CertKeyUsage[] => { const parseKeyUsages = (keyUsages: unknown): CertKeyUsageType[] => {
if (!keyUsages) return []; if (!keyUsages) return [];
const validKeyUsages = Object.values(CertKeyUsage); const validKeyUsages = Object.values(CertKeyUsageType);
if (Array.isArray(keyUsages)) { if (Array.isArray(keyUsages)) {
return keyUsages.filter( return keyUsages.filter(
(usage): usage is CertKeyUsage => typeof usage === "string" && validKeyUsages.includes(usage as CertKeyUsage) (usage): usage is CertKeyUsageType =>
typeof usage === "string" && validKeyUsages.includes(usage as CertKeyUsageType)
); );
} }
@@ -322,21 +320,21 @@ const parseKeyUsages = (keyUsages: unknown): CertKeyUsage[] => {
return keyUsages return keyUsages
.split(",") .split(",")
.map((usage) => usage.trim()) .map((usage) => usage.trim())
.filter((usage): usage is CertKeyUsage => validKeyUsages.includes(usage as CertKeyUsage)); .filter((usage): usage is CertKeyUsageType => validKeyUsages.includes(usage as CertKeyUsageType));
} }
return []; return [];
}; };
const parseExtendedKeyUsages = (extendedKeyUsages: unknown): CertExtendedKeyUsage[] => { const parseExtendedKeyUsages = (extendedKeyUsages: unknown): CertExtendedKeyUsageType[] => {
if (!extendedKeyUsages) return []; if (!extendedKeyUsages) return [];
const validExtendedKeyUsages = Object.values(CertExtendedKeyUsage); const validExtendedKeyUsages = Object.values(CertExtendedKeyUsageType);
if (Array.isArray(extendedKeyUsages)) { if (Array.isArray(extendedKeyUsages)) {
return extendedKeyUsages.filter( return extendedKeyUsages.filter(
(usage): usage is CertExtendedKeyUsage => (usage): usage is CertExtendedKeyUsageType =>
typeof usage === "string" && validExtendedKeyUsages.includes(usage as CertExtendedKeyUsage) typeof usage === "string" && validExtendedKeyUsages.includes(usage as CertExtendedKeyUsageType)
); );
} }
@@ -344,7 +342,9 @@ const parseExtendedKeyUsages = (extendedKeyUsages: unknown): CertExtendedKeyUsag
return extendedKeyUsages return extendedKeyUsages
.split(",") .split(",")
.map((usage) => usage.trim()) .map((usage) => usage.trim())
.filter((usage): usage is CertExtendedKeyUsage => validExtendedKeyUsages.includes(usage as CertExtendedKeyUsage)); .filter((usage): usage is CertExtendedKeyUsageType =>
validExtendedKeyUsages.includes(usage as CertExtendedKeyUsageType)
);
} }
return []; return [];
@@ -972,7 +972,9 @@ export const certificateV3ServiceFactory = ({
notBefore: certificateRequest.notBefore, notBefore: certificateRequest.notBefore,
notAfter: certificateRequest.notAfter, notAfter: certificateRequest.notAfter,
keyAlgorithm: effectiveKeyAlgorithm, keyAlgorithm: effectiveKeyAlgorithm,
signatureAlgorithm: effectiveSignatureAlgorithm signatureAlgorithm: effectiveSignatureAlgorithm,
status: CertificateRequestStatus.ISSUED,
certificateId: selfSignedResult.certificateData.id
}); });
return { ...selfSignedResult, certificateRequestId: certRequestResult.id }; return { ...selfSignedResult, certificateRequestId: certRequestResult.id };
@@ -1048,7 +1050,8 @@ export const certificateV3ServiceFactory = ({
actorId, actorId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId,
isFromProfile: true isFromProfile: true,
tx
}); });
const certificateRecord = await certificateDAL.findById(certResult.certificateId); const certificateRecord = await certificateDAL.findById(certResult.certificateId);
@@ -1066,7 +1069,7 @@ export const certificateV3ServiceFactory = ({
if (finalRenewBeforeDays !== undefined) { if (finalRenewBeforeDays !== undefined) {
updateData.renewBeforeDays = finalRenewBeforeDays; updateData.renewBeforeDays = finalRenewBeforeDays;
} }
await certificateDAL.updateById(certificateRecord.id, updateData); await certificateDAL.updateById(certificateRecord.id, updateData, tx);
const certRequestResult = await certificateRequestService.createCertificateRequest({ const certRequestResult = await certificateRequestService.createCertificateRequest({
actor, actor,
@@ -1075,6 +1078,7 @@ export const certificateV3ServiceFactory = ({
actorOrgId, actorOrgId,
projectId: profile.projectId, projectId: profile.projectId,
tx, tx,
caId: ca.id,
profileId: profile.id, profileId: profile.id,
commonName: certificateRequest.commonName, commonName: certificateRequest.commonName,
altNames: certificateRequest.altNames?.map((san) => san.value).join(","), altNames: certificateRequest.altNames?.map((san) => san.value).join(","),
@@ -1083,7 +1087,9 @@ export const certificateV3ServiceFactory = ({
notBefore: certificateRequest.notBefore, notBefore: certificateRequest.notBefore,
notAfter: certificateRequest.notAfter, notAfter: certificateRequest.notAfter,
keyAlgorithm: effectiveKeyAlgorithm, keyAlgorithm: effectiveKeyAlgorithm,
signatureAlgorithm: effectiveSignatureAlgorithm signatureAlgorithm: effectiveSignatureAlgorithm,
status: CertificateRequestStatus.ISSUED,
certificateId: certResult.certificateId
}); });
return { ...certResult, cert: certificateRecord, certificateRequestId: certRequestResult.id }; return { ...certResult, cert: certificateRecord, certificateRequestId: certRequestResult.id };
@@ -1197,7 +1203,8 @@ export const certificateV3ServiceFactory = ({
notAfter: normalizeDateForApi(notAfter), notAfter: normalizeDateForApi(notAfter),
signatureAlgorithm: effectiveSignatureAlgorithm, signatureAlgorithm: effectiveSignatureAlgorithm,
keyAlgorithm: effectiveKeyAlgorithm, keyAlgorithm: effectiveKeyAlgorithm,
isFromProfile: true isFromProfile: true,
tx
}); });
const signedCertRecord = await certificateDAL.findById(certResult.certificateId); const signedCertRecord = await certificateDAL.findById(certResult.certificateId);
@@ -1215,7 +1222,7 @@ export const certificateV3ServiceFactory = ({
if (finalRenewBeforeDays !== undefined) { if (finalRenewBeforeDays !== undefined) {
updateData.renewBeforeDays = finalRenewBeforeDays; updateData.renewBeforeDays = finalRenewBeforeDays;
} }
await certificateDAL.updateById(signedCertRecord.id, updateData); await certificateDAL.updateById(signedCertRecord.id, updateData, tx);
const certRequestResult = await certificateRequestService.createCertificateRequest({ const certRequestResult = await certificateRequestService.createCertificateRequest({
actor, actor,
@@ -1224,6 +1231,7 @@ export const certificateV3ServiceFactory = ({
actorOrgId, actorOrgId,
projectId: profile.projectId, projectId: profile.projectId,
tx, tx,
caId: ca.id,
profileId: profile.id, profileId: profile.id,
csr, csr,
commonName: mappedCertificateRequest.commonName, commonName: mappedCertificateRequest.commonName,
@@ -1233,7 +1241,9 @@ export const certificateV3ServiceFactory = ({
notBefore, notBefore,
notAfter, notAfter,
keyAlgorithm: effectiveKeyAlgorithm, keyAlgorithm: effectiveKeyAlgorithm,
signatureAlgorithm: effectiveSignatureAlgorithm signatureAlgorithm: effectiveSignatureAlgorithm,
status: CertificateRequestStatus.ISSUED,
certificateId: certResult.certificateId
}); });
return { ...certResult, cert: signedCertRecord, certificateRequestId: certRequestResult.id }; return { ...certResult, cert: signedCertRecord, certificateRequestId: certRequestResult.id };
@@ -1370,6 +1380,7 @@ export const certificateV3ServiceFactory = ({
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId,
projectId: profile.projectId, projectId: profile.projectId,
caId: ca.id,
profileId: profile.id, profileId: profile.id,
commonName: certificateOrder.commonName || "", commonName: certificateOrder.commonName || "",
keyUsages: certificateOrder.keyUsages ? convertEnumsToStringArray(certificateOrder.keyUsages) : [], keyUsages: certificateOrder.keyUsages ? convertEnumsToStringArray(certificateOrder.keyUsages) : [],
@@ -1380,7 +1391,8 @@ export const certificateV3ServiceFactory = ({
signatureAlgorithm: certificateOrder.signatureAlgorithm || "", signatureAlgorithm: certificateOrder.signatureAlgorithm || "",
altNames: certificateOrder.altNames?.map((san) => san.value).join(",") || "", altNames: certificateOrder.altNames?.map((san) => san.value).join(",") || "",
notBefore: certificateOrder.notBefore, notBefore: certificateOrder.notBefore,
notAfter: certificateOrder.notAfter notAfter: certificateOrder.notAfter,
status: CertificateRequestStatus.PENDING
}); });
await certificateIssuanceQueue.queueCertificateIssuance({ await certificateIssuanceQueue.queueCertificateIssuance({
@@ -1554,10 +1566,8 @@ export const certificateV3ServiceFactory = ({
const certificateRequest = { const certificateRequest = {
commonName: originalCert.commonName || undefined, commonName: originalCert.commonName || undefined,
keyUsages: convertKeyUsageArrayFromLegacy(parseKeyUsages(originalCert.keyUsages)), keyUsages: parseKeyUsages(originalCert.keyUsages),
extendedKeyUsages: convertExtendedKeyUsageArrayFromLegacy( extendedKeyUsages: parseExtendedKeyUsages(originalCert.extendedKeyUsages),
parseExtendedKeyUsages(originalCert.extendedKeyUsages)
),
subjectAlternativeNames: originalCert.altNames subjectAlternativeNames: originalCert.altNames
? originalCert.altNames.split(",").map((san) => detectSanType(san.trim())) ? originalCert.altNames.split(",").map((san) => detectSanType(san.trim()))
: [], : [],
@@ -1622,8 +1632,10 @@ export const certificateV3ServiceFactory = ({
ttl, ttl,
notBefore: normalizeDateForApi(notBefore), notBefore: normalizeDateForApi(notBefore),
notAfter: normalizeDateForApi(notAfter), notAfter: normalizeDateForApi(notAfter),
keyUsages: parseKeyUsages(originalCert.keyUsages), keyUsages: convertKeyUsageArrayToLegacy(parseKeyUsages(originalCert.keyUsages)),
extendedKeyUsages: parseExtendedKeyUsages(originalCert.extendedKeyUsages), extendedKeyUsages: convertExtendedKeyUsageArrayToLegacy(
parseExtendedKeyUsages(originalCert.extendedKeyUsages)
),
signatureAlgorithm: originalSignatureAlgorithm, signatureAlgorithm: originalSignatureAlgorithm,
keyAlgorithm: originalKeyAlgorithm, keyAlgorithm: originalKeyAlgorithm,
isFromProfile: true, isFromProfile: true,
@@ -1736,18 +1748,19 @@ export const certificateV3ServiceFactory = ({
actorOrgId, actorOrgId,
projectId: originalCert.projectId, projectId: originalCert.projectId,
tx, tx,
caId: ca?.id || originalCert.caId || undefined,
profileId: originalCert.profileId || undefined, profileId: originalCert.profileId || undefined,
commonName: originalCert.commonName || undefined, commonName: originalCert.commonName || undefined,
altNames: originalCert.altNames || undefined, altNames: originalCert.altNames || undefined,
keyUsages: convertKeyUsageArrayFromLegacy(parseKeyUsages(originalCert.keyUsages)), keyUsages: parseKeyUsages(originalCert.keyUsages),
extendedKeyUsages: convertExtendedKeyUsageArrayFromLegacy( extendedKeyUsages: parseExtendedKeyUsages(originalCert.extendedKeyUsages),
parseExtendedKeyUsages(originalCert.extendedKeyUsages)
),
notBefore: new Date(newCert.notBefore), notBefore: new Date(newCert.notBefore),
notAfter: new Date(newCert.notAfter), notAfter: new Date(newCert.notAfter),
keyAlgorithm: originalKeyAlgorithm, keyAlgorithm: originalKeyAlgorithm,
signatureAlgorithm: originalSignatureAlgorithm, signatureAlgorithm: originalSignatureAlgorithm,
metadata: `Renewed from certificate ID: ${originalCert.id}` metadata: `Renewed from certificate ID: ${originalCert.id}`,
status: CertificateRequestStatus.ISSUED,
certificateId: newCert.id
}); });
return { return {
@@ -1783,13 +1796,12 @@ export const certificateV3ServiceFactory = ({
caId: ca.id, caId: ca.id,
commonName: originalCert.commonName || undefined, commonName: originalCert.commonName || undefined,
altNames: originalCert.altNames || undefined, altNames: originalCert.altNames || undefined,
keyUsages: convertKeyUsageArrayFromLegacy(parseKeyUsages(originalCert.keyUsages)), keyUsages: parseKeyUsages(originalCert.keyUsages),
extendedKeyUsages: convertExtendedKeyUsageArrayFromLegacy( extendedKeyUsages: parseExtendedKeyUsages(originalCert.extendedKeyUsages),
parseExtendedKeyUsages(originalCert.extendedKeyUsages)
),
keyAlgorithm: originalKeyAlgorithm, keyAlgorithm: originalKeyAlgorithm,
signatureAlgorithm: originalSignatureAlgorithm, signatureAlgorithm: originalSignatureAlgorithm,
metadata: `Renewed from certificate ID: ${originalCert.id}` metadata: `Renewed from certificate ID: ${originalCert.id}`,
status: CertificateRequestStatus.PENDING
}); });
certificateRequestId = certificateRequest.id; certificateRequestId = certificateRequest.id;
+4 -2
View File
@@ -189,10 +189,12 @@ export const useGetCaCertTemplates = (caId: string) => {
export const useGetAzureAdcsTemplates = ({ export const useGetAzureAdcsTemplates = ({
caId, caId,
projectId projectId,
isAzureAdcsCa
}: { }: {
caId: string; caId: string;
projectId: string; projectId: string;
isAzureAdcsCa: boolean;
}) => { }) => {
return useQuery({ return useQuery({
queryKey: caKeys.getAzureAdcsTemplates(caId, projectId), queryKey: caKeys.getAzureAdcsTemplates(caId, projectId),
@@ -202,6 +204,6 @@ export const useGetAzureAdcsTemplates = ({
}>(`/api/v1/cert-manager/ca/azure-ad-cs/${caId}/templates?projectId=${projectId}`); }>(`/api/v1/cert-manager/ca/azure-ad-cs/${caId}/templates?projectId=${projectId}`);
return data; return data;
}, },
enabled: Boolean(caId && projectId) enabled: Boolean(caId && projectId && isAzureAdcsCa)
}); });
}; };
@@ -195,10 +195,7 @@ export const useUnifiedCertificateIssuance = () => {
const { projectSlug, ...requestData } = body; const { projectSlug, ...requestData } = body;
const { data } = await apiRequest.post<TUnifiedCertificateIssuanceResponse>( const { data } = await apiRequest.post<TUnifiedCertificateIssuanceResponse>(
"/api/v1/cert-manager/certificates", "/api/v1/cert-manager/certificates",
requestData, requestData
{
params: { projectSlug }
}
); );
return data; return data;
}, },
@@ -298,7 +298,6 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId }
const formattedSans = formatSubjectAltNames(subjectAltNames); const formattedSans = formatSubjectAltNames(subjectAltNames);
if (formattedSans && formattedSans.length > 0) { if (formattedSans && formattedSans.length > 0) {
request.attributes.altNames = formattedSans; request.attributes.altNames = formattedSans;
request.attributes.subjectAlternativeNames = formattedSans;
} }
} }
@@ -325,7 +324,7 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId }
} else { } else {
// Certificate request - async processing // Certificate request - async processing
createNotification({ createNotification({
text: `Certificate request submitted successfully. This may take a few minutes to process. Request ID: ${response.certificateRequestId}`, text: `Certificate request submitted successfully. This may take a few minutes to process. Certificate Request ID: ${response.certificateRequestId}`,
type: "success" type: "success"
}); });
handlePopUpToggle("issueCertificate", false); handlePopUpToggle("issueCertificate", false);
@@ -25,7 +25,7 @@ export const CertificateRenewalModal = ({ popUp, handlePopUpToggle }: Props) =>
}); });
const notificationText = result.certificateRequestId const notificationText = result.certificateRequestId
? `Certificate renewal initiated successfully. Request ID: ${result.certificateRequestId}` ? `Certificate renewal initiated successfully. Certificate Request ID: ${result.certificateRequestId}`
: "Certificate renewed successfully"; : "Certificate renewed successfully";
createNotification({ createNotification({
@@ -71,7 +71,9 @@ export const CertificateRequestTracker = ({ requestId, onCertificateIssued }: Pr
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center space-x-2"> <div className="flex items-center space-x-2">
{getStatusIcon()} {getStatusIcon()}
<span className="text-sm font-medium text-mineshaft-300">Request ID: {requestId}</span> <span className="text-sm font-medium text-mineshaft-300">
Certificate Request ID: {requestId}
</span>
</div> </div>
<div className="text-sm text-mineshaft-400"> <div className="text-sm text-mineshaft-400">
@@ -447,7 +447,8 @@ export const CreateProfileModal = ({
// Fetch Azure ADCS templates if needed // Fetch Azure ADCS templates if needed
const { data: azureAdcsTemplatesData } = useGetAzureAdcsTemplates({ const { data: azureAdcsTemplatesData } = useGetAzureAdcsTemplates({
caId: watchedCertificateAuthorityId || "", caId: watchedCertificateAuthorityId || "",
projectId: currentProject?.id || "" projectId: currentProject?.id || "",
isAzureAdcsCa
}); });
useEffect(() => { useEffect(() => {
@@ -732,7 +733,7 @@ export const CreateProfileModal = ({
name="externalConfigs.template" name="externalConfigs.template"
render={({ field: { onChange, value }, fieldState: { error } }) => ( render={({ field: { onChange, value }, fieldState: { error } }) => (
<FormControl <FormControl
label="Azure ADCS Template" label="Windows ADCS Template"
isRequired isRequired
isError={Boolean(error)} isError={Boolean(error)}
errorText={error?.message} errorText={error?.message}