PKI: add support for auto-renewal option on API enrollment type

This commit is contained in:
Carlos Monastyrski
2025-10-23 00:38:24 -03:00
parent 7224ff9ece
commit 9d09990143
34 changed files with 2739 additions and 94 deletions
+12
View File
@@ -175,6 +175,7 @@ import { certificateTemplateEstConfigDALFactory } from "@app/services/certificat
import { certificateTemplateServiceFactory } from "@app/services/certificate-template/certificate-template-service";
import { certificateTemplateV2DALFactory } from "@app/services/certificate-template-v2/certificate-template-v2-dal";
import { certificateTemplateV2ServiceFactory } from "@app/services/certificate-template-v2/certificate-template-v2-service";
import { certificateV3QueueServiceFactory } from "@app/services/certificate-v3/certificate-v3-queue";
import { certificateV3ServiceFactory } from "@app/services/certificate-v3/certificate-v3-service";
import { cmekServiceFactory } from "@app/services/cmek/cmek-service";
import { convertorServiceFactory } from "@app/services/convertor/convertor-service";
@@ -2122,6 +2123,16 @@ export const registerRoutes = async (
permissionService
});
const certificateV3Queue = certificateV3QueueServiceFactory({
queueService,
certificateDAL,
certificateAuthorityDAL,
certificateProfileDAL,
projectDAL,
certificateV3Service,
auditLogService
});
const certificateEstV3Service = certificateEstV3ServiceFactory({
internalCertificateAuthorityService,
certificateTemplateV2Service,
@@ -2281,6 +2292,7 @@ export const registerRoutes = async (
await dailyReminderQueueService.startSecretReminderMigrationJob();
await dailyExpiringPkiItemAlert.startSendingAlerts();
await pkiSubscriberQueue.startDailyAutoRenewalJob();
await certificateV3Queue.startDailyAutoRenewalJob();
await kmsService.startService();
await microsoftTeamsService.start();
await dynamicSecretQueueService.init();
@@ -42,7 +42,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
apiConfig: z
.object({
autoRenew: z.boolean().default(false),
autoRenewDays: z.number().min(1).max(365).optional()
renewBeforeDays: z.number().min(1).max(30).optional()
})
.optional()
})
@@ -150,7 +150,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
.object({
id: z.string(),
autoRenew: z.boolean(),
autoRenewDays: z.number().optional()
renewBeforeDays: z.number().optional()
})
.optional()
}).array(),
@@ -230,7 +230,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
.object({
id: z.string(),
autoRenew: z.boolean(),
autoRenewDays: z.number().optional()
renewBeforeDays: z.number().optional()
})
.optional(),
metrics: z
@@ -355,7 +355,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
apiConfig: z
.object({
autoRenew: z.boolean().default(false),
autoRenewDays: z.number().min(1).max(365).optional()
renewBeforeDays: z.number().min(1).max(30).optional()
})
.optional()
})
@@ -343,4 +343,138 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
return data;
}
});
server.route({
method: "POST",
url: "/:certificateId/renew",
config: {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
params: z.object({
certificateId: z.string().uuid()
}),
response: {
200: z.object({
certificate: z.string().trim(),
issuingCaCertificate: z.string().trim(),
certificateChain: z.string().trim(),
privateKey: z.string().trim().optional(),
serialNumber: z.string().trim(),
certificateId: z.string()
})
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const data = await server.services.certificateV3.renewCertificate({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
certificateId: req.params.certificateId
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
projectId: data.projectId,
event: {
type: EventType.RENEW_CERTIFICATE,
metadata: {
originalCertificateId: req.params.certificateId,
newCertificateId: data.certificateId,
profileName: data.profileName
}
}
});
return data;
}
});
server.route({
method: "PATCH",
url: "/:certificateId/config",
config: {
rateLimit: writeLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
params: z.object({
certificateId: z.string().uuid()
}),
body: z.object({
renewBeforeDays: z.number().int().min(1).max(30).optional(),
disableAutoRenewal: z.boolean().optional()
}),
response: {
200: z.object({
message: z.string(),
renewBeforeDays: z.number().optional()
})
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
if (req.body.disableAutoRenewal === true) {
const data = await server.services.certificateV3.disableRenewalConfig({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
certificateId: req.params.certificateId
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
projectId: data.projectId,
event: {
type: EventType.DISABLE_CERTIFICATE_RENEWAL_CONFIG,
metadata: {
certificateId: req.params.certificateId
}
}
});
return {
message: "Auto-renewal disabled successfully"
};
}
if (req.body.renewBeforeDays !== undefined) {
const data = await server.services.certificateV3.updateRenewalConfig({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
certificateId: req.params.certificateId,
renewBeforeDays: req.body.renewBeforeDays
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
projectId: data.projectId,
event: {
type: EventType.UPDATE_CERTIFICATE_RENEWAL_CONFIG,
metadata: {
certificateId: req.params.certificateId,
renewBeforeDays: req.body.renewBeforeDays.toString()
}
}
});
return {
message: "Certificate configuration updated successfully",
renewBeforeDays: data.renewBeforeDays
};
}
return {
message: "No configuration changes requested"
};
}
});
};