Merge pull request #4993 from Infisical/fix/pki-routes-cleanup

fix: improvements on certificate request endpoint
This commit is contained in:
carlosmonastyrski
2025-12-09 13:06:04 -03:00
committed by GitHub
4 changed files with 53 additions and 43 deletions
@@ -316,13 +316,11 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => {
params: z.object({ params: z.object({
requestId: z.string().uuid() requestId: z.string().uuid()
}), }),
query: z.object({
projectId: z.string().uuid()
}),
response: { response: {
200: z.object({ 200: z.object({
status: z.nativeEnum(CertificateRequestStatus), status: z.nativeEnum(CertificateRequestStatus),
certificate: z.string().nullable(), certificate: z.string().nullable(),
certificateId: z.string().nullable(),
privateKey: z.string().nullable(), privateKey: z.string().nullable(),
serialNumber: z.string().nullable(), serialNumber: z.string().nullable(),
errorMessage: z.string().nullable(), errorMessage: z.string().nullable(),
@@ -333,18 +331,17 @@ export const registerCertificateRouter = 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 data = await server.services.certificateRequest.getCertificateFromRequest({ const { certificateRequest, projectId } = await server.services.certificateRequest.getCertificateFromRequest({
actor: req.permission.type, actor: req.permission.type,
actorId: req.permission.id, actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod, actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId, actorOrgId: req.permission.orgId,
projectId: (req.query as { projectId: string }).projectId,
certificateRequestId: req.params.requestId certificateRequestId: req.params.requestId
}); });
await server.services.auditLog.createAuditLog({ await server.services.auditLog.createAuditLog({
...req.auditLogInfo, ...req.auditLogInfo,
projectId: (req.query as { projectId: string }).projectId, projectId,
event: { event: {
type: EventType.GET_CERTIFICATE_REQUEST, type: EventType.GET_CERTIFICATE_REQUEST,
metadata: { metadata: {
@@ -352,7 +349,7 @@ export const registerCertificateRouter = async (server: FastifyZodProvider) => {
} }
} }
}); });
return data; return certificateRequest;
} }
}); });
@@ -258,7 +258,7 @@ describe("CertificateRequestService", () => {
(mockCertificateService.getCertBody as any).mockResolvedValue(mockCertBody); (mockCertificateService.getCertBody as any).mockResolvedValue(mockCertBody);
(mockCertificateService.getCertPrivateKey as any).mockResolvedValue(mockPrivateKey); (mockCertificateService.getCertPrivateKey as any).mockResolvedValue(mockPrivateKey);
const result = await service.getCertificateFromRequest(mockGetData); const { certificateRequest, projectId } = await service.getCertificateFromRequest(mockGetData);
expect(mockCertificateRequestDAL.findByIdWithCertificate).toHaveBeenCalledWith( expect(mockCertificateRequestDAL.findByIdWithCertificate).toHaveBeenCalledWith(
"550e8400-e29b-41d4-a716-446655440005" "550e8400-e29b-41d4-a716-446655440005"
@@ -277,8 +277,9 @@ describe("CertificateRequestService", () => {
actorAuthMethod: AuthMethod.EMAIL, actorAuthMethod: AuthMethod.EMAIL,
actorOrgId: "550e8400-e29b-41d4-a716-446655440002" actorOrgId: "550e8400-e29b-41d4-a716-446655440002"
}); });
expect(result).toEqual({ expect(certificateRequest).toEqual({
status: CertificateRequestStatus.ISSUED, status: CertificateRequestStatus.ISSUED,
certificateId: "550e8400-e29b-41d4-a716-446655440006",
certificate: "-----BEGIN CERTIFICATE-----\nMOCK_CERT_PEM\n-----END CERTIFICATE-----", certificate: "-----BEGIN CERTIFICATE-----\nMOCK_CERT_PEM\n-----END CERTIFICATE-----",
privateKey: "-----BEGIN PRIVATE KEY-----\nMOCK_KEY_PEM\n-----END PRIVATE KEY-----", privateKey: "-----BEGIN PRIVATE KEY-----\nMOCK_KEY_PEM\n-----END PRIVATE KEY-----",
serialNumber: "123456", serialNumber: "123456",
@@ -286,6 +287,7 @@ describe("CertificateRequestService", () => {
createdAt: mockRequestWithCert.createdAt, createdAt: mockRequestWithCert.createdAt,
updatedAt: mockRequestWithCert.updatedAt updatedAt: mockRequestWithCert.updatedAt
}); });
expect(projectId).toEqual("550e8400-e29b-41d4-a716-446655440003");
}); });
it("should get certificate from request successfully when no certificate is attached", async () => { it("should get certificate from request successfully when no certificate is attached", async () => {
@@ -310,10 +312,11 @@ describe("CertificateRequestService", () => {
(mockPermissionService.getProjectPermission as any).mockResolvedValue(mockPermission); (mockPermissionService.getProjectPermission as any).mockResolvedValue(mockPermission);
(mockCertificateRequestDAL.findByIdWithCertificate as any).mockResolvedValue(mockRequestWithoutCert); (mockCertificateRequestDAL.findByIdWithCertificate as any).mockResolvedValue(mockRequestWithoutCert);
const result = await service.getCertificateFromRequest(mockGetData); const { certificateRequest, projectId } = await service.getCertificateFromRequest(mockGetData);
expect(result).toEqual({ expect(certificateRequest).toEqual({
status: CertificateRequestStatus.PENDING, status: CertificateRequestStatus.PENDING,
certificateId: null,
certificate: null, certificate: null,
privateKey: null, privateKey: null,
serialNumber: null, serialNumber: null,
@@ -321,6 +324,7 @@ describe("CertificateRequestService", () => {
createdAt: mockRequestWithoutCert.createdAt, createdAt: mockRequestWithoutCert.createdAt,
updatedAt: mockRequestWithoutCert.updatedAt updatedAt: mockRequestWithoutCert.updatedAt
}); });
expect(projectId).toEqual("550e8400-e29b-41d4-a716-446655440003");
}); });
it("should get certificate from request successfully when user lacks private key permission", async () => { it("should get certificate from request successfully when user lacks private key permission", async () => {
@@ -354,7 +358,7 @@ describe("CertificateRequestService", () => {
(mockCertificateRequestDAL.findByIdWithCertificate as any).mockResolvedValue(mockRequestWithCert); (mockCertificateRequestDAL.findByIdWithCertificate as any).mockResolvedValue(mockRequestWithCert);
(mockCertificateService.getCertBody as any).mockResolvedValue(mockCertBody); (mockCertificateService.getCertBody as any).mockResolvedValue(mockCertBody);
const result = await service.getCertificateFromRequest(mockGetData); const { certificateRequest, projectId } = await service.getCertificateFromRequest(mockGetData);
expect(mockCertificateRequestDAL.findByIdWithCertificate).toHaveBeenCalledWith( expect(mockCertificateRequestDAL.findByIdWithCertificate).toHaveBeenCalledWith(
"550e8400-e29b-41d4-a716-446655440005" "550e8400-e29b-41d4-a716-446655440005"
@@ -367,8 +371,9 @@ describe("CertificateRequestService", () => {
actorOrgId: "550e8400-e29b-41d4-a716-446655440002" actorOrgId: "550e8400-e29b-41d4-a716-446655440002"
}); });
expect(mockCertificateService.getCertPrivateKey).not.toHaveBeenCalled(); expect(mockCertificateService.getCertPrivateKey).not.toHaveBeenCalled();
expect(result).toEqual({ expect(certificateRequest).toEqual({
status: CertificateRequestStatus.ISSUED, status: CertificateRequestStatus.ISSUED,
certificateId: "550e8400-e29b-41d4-a716-446655440008",
certificate: "-----BEGIN CERTIFICATE-----\nMOCK_CERT_PEM\n-----END CERTIFICATE-----", certificate: "-----BEGIN CERTIFICATE-----\nMOCK_CERT_PEM\n-----END CERTIFICATE-----",
privateKey: null, privateKey: null,
serialNumber: "123456", serialNumber: "123456",
@@ -376,6 +381,7 @@ describe("CertificateRequestService", () => {
createdAt: mockRequestWithCert.createdAt, createdAt: mockRequestWithCert.createdAt,
updatedAt: mockRequestWithCert.updatedAt updatedAt: mockRequestWithCert.updatedAt
}); });
expect(projectId).toEqual("550e8400-e29b-41d4-a716-446655440003");
}); });
it("should get certificate from request successfully when user has private key permission but key retrieval fails", async () => { it("should get certificate from request successfully when user has private key permission but key retrieval fails", async () => {
@@ -414,7 +420,7 @@ describe("CertificateRequestService", () => {
(mockCertificateService.getCertBody as any).mockResolvedValue(mockCertBody); (mockCertificateService.getCertBody as any).mockResolvedValue(mockCertBody);
(mockCertificateService.getCertPrivateKey as any).mockRejectedValue(new Error("Private key not found")); (mockCertificateService.getCertPrivateKey as any).mockRejectedValue(new Error("Private key not found"));
const result = await service.getCertificateFromRequest(mockGetData); const { certificateRequest, projectId } = await service.getCertificateFromRequest(mockGetData);
expect(mockCertificateRequestDAL.findByIdWithCertificate).toHaveBeenCalledWith( expect(mockCertificateRequestDAL.findByIdWithCertificate).toHaveBeenCalledWith(
"550e8400-e29b-41d4-a716-446655440005" "550e8400-e29b-41d4-a716-446655440005"
@@ -433,8 +439,9 @@ describe("CertificateRequestService", () => {
actorAuthMethod: AuthMethod.EMAIL, actorAuthMethod: AuthMethod.EMAIL,
actorOrgId: "550e8400-e29b-41d4-a716-446655440002" actorOrgId: "550e8400-e29b-41d4-a716-446655440002"
}); });
expect(result).toEqual({ expect(certificateRequest).toEqual({
status: CertificateRequestStatus.ISSUED, status: CertificateRequestStatus.ISSUED,
certificateId: "550e8400-e29b-41d4-a716-446655440009",
certificate: "-----BEGIN CERTIFICATE-----\nMOCK_CERT_PEM\n-----END CERTIFICATE-----", certificate: "-----BEGIN CERTIFICATE-----\nMOCK_CERT_PEM\n-----END CERTIFICATE-----",
privateKey: null, privateKey: null,
serialNumber: "123456", serialNumber: "123456",
@@ -442,6 +449,7 @@ describe("CertificateRequestService", () => {
createdAt: mockRequestWithCert.createdAt, createdAt: mockRequestWithCert.createdAt,
updatedAt: mockRequestWithCert.updatedAt updatedAt: mockRequestWithCert.updatedAt
}); });
expect(projectId).toEqual("550e8400-e29b-41d4-a716-446655440003");
}); });
it("should get certificate from request with error message when failed", async () => { it("should get certificate from request with error message when failed", async () => {
@@ -466,17 +474,19 @@ describe("CertificateRequestService", () => {
(mockPermissionService.getProjectPermission as any).mockResolvedValue(mockPermission); (mockPermissionService.getProjectPermission as any).mockResolvedValue(mockPermission);
(mockCertificateRequestDAL.findByIdWithCertificate as any).mockResolvedValue(mockFailedRequest); (mockCertificateRequestDAL.findByIdWithCertificate as any).mockResolvedValue(mockFailedRequest);
const result = await service.getCertificateFromRequest(mockGetData); const { certificateRequest, projectId } = await service.getCertificateFromRequest(mockGetData);
expect(result).toEqual({ expect(certificateRequest).toEqual({
status: CertificateRequestStatus.FAILED, status: CertificateRequestStatus.FAILED,
certificate: null, certificate: null,
certificateId: null,
privateKey: null, privateKey: null,
serialNumber: null, serialNumber: null,
errorMessage: "Certificate issuance failed", errorMessage: "Certificate issuance failed",
createdAt: mockFailedRequest.createdAt, createdAt: mockFailedRequest.createdAt,
updatedAt: mockFailedRequest.updatedAt updatedAt: mockFailedRequest.updatedAt
}); });
expect(projectId).toEqual("550e8400-e29b-41d4-a716-446655440003");
}); });
it("should throw NotFoundError when certificate request does not exist", async () => { it("should throw NotFoundError when certificate request does not exist", async () => {
@@ -170,13 +170,17 @@ export const certificateRequestServiceFactory = ({
actorId, actorId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId,
projectId,
certificateRequestId certificateRequestId
}: TGetCertificateFromRequestDTO) => { }: TGetCertificateFromRequestDTO) => {
const certificateRequest = await certificateRequestDAL.findByIdWithCertificate(certificateRequestId);
if (!certificateRequest) {
throw new NotFoundError({ message: "Certificate request not found" });
}
const { permission } = await permissionService.getProjectPermission({ const { permission } = await permissionService.getProjectPermission({
actor, actor,
actorId, actorId,
projectId, projectId: certificateRequest.projectId,
actorAuthMethod, actorAuthMethod,
actorOrgId, actorOrgId,
actionProjectType: ActionProjectType.CertificateManager actionProjectType: ActionProjectType.CertificateManager
@@ -187,25 +191,20 @@ export const certificateRequestServiceFactory = ({
ProjectPermissionSub.Certificates ProjectPermissionSub.Certificates
); );
const certificateRequest = await certificateRequestDAL.findByIdWithCertificate(certificateRequestId);
if (!certificateRequest) {
throw new NotFoundError({ message: "Certificate request not found" });
}
if (certificateRequest.projectId !== projectId) {
throw new NotFoundError({ message: "Certificate request not found" });
}
// If no certificate is attached, return basic info // If no certificate is attached, return basic info
if (!certificateRequest.certificate) { if (!certificateRequest.certificate) {
return { return {
status: certificateRequest.status as CertificateRequestStatus, certificateRequest: {
certificate: null, status: certificateRequest.status as CertificateRequestStatus,
privateKey: null, certificate: null,
serialNumber: null, certificateId: null,
errorMessage: certificateRequest.errorMessage || null, privateKey: null,
createdAt: certificateRequest.createdAt, serialNumber: null,
updatedAt: certificateRequest.updatedAt errorMessage: certificateRequest.errorMessage || null,
createdAt: certificateRequest.createdAt,
updatedAt: certificateRequest.updatedAt
},
projectId: certificateRequest.projectId
}; };
} }
@@ -240,13 +239,17 @@ export const certificateRequestServiceFactory = ({
} }
return { return {
status: certificateRequest.status as CertificateRequestStatus, certificateRequest: {
certificate: certBody.certificate, status: certificateRequest.status as CertificateRequestStatus,
privateKey, certificate: certBody.certificate,
serialNumber: certificateRequest.certificate.serialNumber, certificateId: certificateRequest.certificate.id,
errorMessage: certificateRequest.errorMessage || null, privateKey,
createdAt: certificateRequest.createdAt, serialNumber: certificateRequest.certificate.serialNumber,
updatedAt: certificateRequest.updatedAt errorMessage: certificateRequest.errorMessage || null,
createdAt: certificateRequest.createdAt,
updatedAt: certificateRequest.updatedAt
},
projectId: certificateRequest.projectId
}; };
}; };
@@ -27,7 +27,7 @@ export type TGetCertificateRequestDTO = TProjectPermission & {
certificateRequestId: string; certificateRequestId: string;
}; };
export type TGetCertificateFromRequestDTO = TProjectPermission & { export type TGetCertificateFromRequestDTO = Omit<TProjectPermission, "projectId"> & {
certificateRequestId: string; certificateRequestId: string;
}; };