Addressed PR comments

This commit is contained in:
Carlos Monastyrski
2025-10-14 03:18:35 -03:00
parent 073be13906
commit 42800fdfe5
82 changed files with 4223 additions and 1956 deletions
@@ -1,3 +1,4 @@
import RE2 from "re2";
import { z } from "zod";
import { CertificateProfilesSchema } from "@app/db/schemas";
@@ -6,12 +7,7 @@ import { ApiDocsTags } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import {
createCertificateProfileSchema,
deleteCertificateProfileSchema,
listCertificateProfilesSchema,
updateCertificateProfileSchema
} from "@app/services/certificate-profile/certificate-profile-schemas";
import { EnrollmentType } from "@app/services/certificate-profile/certificate-profile-types";
export const registerCertificateProfilesRouter = async (server: FastifyZodProvider) => {
server.route({
@@ -23,7 +19,57 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateProfiles],
body: createCertificateProfileSchema,
body: z
.object({
projectId: z.string().min(1),
caId: z.string().uuid(),
certificateTemplateId: z.string().uuid(),
slug: z
.string()
.min(1)
.max(255)
.regex(new RE2("^[a-z0-9-]+$"), "Slug must contain only lowercase letters, numbers, and hyphens"),
description: z.string().max(1000).optional(),
enrollmentType: z.nativeEnum(EnrollmentType),
estConfig: z
.object({
disableBootstrapCaValidation: z.boolean().default(false),
passphrase: z.string().min(1),
encryptedCaChain: z.string()
})
.optional(),
apiConfig: z
.object({
autoRenew: z.boolean().default(false),
autoRenewDays: z.number().min(1).max(365).optional()
})
.optional()
})
.refine(
(data) => {
if (data.enrollmentType === EnrollmentType.EST) {
if (!data.estConfig) {
return false;
}
if (data.apiConfig) {
return false;
}
}
if (data.enrollmentType === EnrollmentType.API) {
if (!data.apiConfig) {
return false;
}
if (data.estConfig) {
return false;
}
}
return true;
},
{
message:
"EST enrollment type requires EST configuration and cannot have API configuration. API enrollment type requires API configuration and cannot have EST configuration."
}
),
response: {
200: z.object({
certificateProfile: CertificateProfilesSchema
@@ -68,7 +114,13 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateProfiles],
querystring: listCertificateProfilesSchema.extend({
querystring: z.object({
projectId: z.string().min(1),
offset: z.coerce.number().min(0).default(0),
limit: z.coerce.number().min(1).max(100).default(20),
search: z.string().optional(),
enrollmentType: z.nativeEnum(EnrollmentType).optional(),
caId: z.string().uuid().optional(),
includeMetrics: z.coerce.boolean().optional().default(false),
expiringDays: z.coerce.number().min(1).max(365).optional().default(7)
}),
@@ -209,7 +261,8 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
event: {
type: EventType.GET_CERTIFICATE_PROFILE,
metadata: {
certificateProfileId: certificateProfile.id
certificateProfileId: certificateProfile.id,
name: certificateProfile.slug
}
}
});
@@ -266,7 +319,48 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
params: z.object({
id: z.string().min(1)
}),
body: updateCertificateProfileSchema,
body: z
.object({
slug: z
.string()
.min(1)
.max(255)
.regex(new RE2("^[a-z0-9-]+$"), "Slug must contain only lowercase letters, numbers, and hyphens")
.optional(),
description: z.string().max(1000).optional(),
enrollmentType: z.nativeEnum(EnrollmentType).optional(),
estConfig: z
.object({
disableBootstrapCaValidation: z.boolean().default(false),
passphrase: z.string().min(1),
encryptedCaChain: z.string()
})
.optional(),
apiConfig: z
.object({
autoRenew: z.boolean().default(false),
autoRenewDays: z.number().min(1).max(365).optional()
})
.optional()
})
.refine(
(data) => {
if (data.enrollmentType === EnrollmentType.EST) {
if (data.apiConfig) {
return false;
}
}
if (data.enrollmentType === EnrollmentType.API) {
if (data.estConfig) {
return false;
}
}
return true;
},
{
message: "Cannot have EST config with API enrollment type or API config with EST enrollment type."
}
),
response: {
200: z.object({
certificateProfile: CertificateProfilesSchema
@@ -309,7 +403,9 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateProfiles],
params: deleteCertificateProfileSchema,
params: z.object({
id: z.string().uuid()
}),
response: {
200: z.object({
certificateProfile: CertificateProfilesSchema
@@ -332,7 +428,8 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid
event: {
type: EventType.DELETE_CERTIFICATE_PROFILE,
metadata: {
certificateProfileId: certificateProfile.id
certificateProfileId: certificateProfile.id,
name: certificateProfile.slug
}
}
});
@@ -117,7 +117,12 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
type: EventType.CREATE_CERTIFICATE_TEMPLATE,
metadata: {
certificateTemplateId: certificateTemplate.id,
caId: certificateTemplate.caId,
pkiCollectionId: certificateTemplate.pkiCollectionId as string,
name: certificateTemplate.name,
commonName: certificateTemplate.commonName,
subjectAlternativeName: certificateTemplate.subjectAlternativeName,
ttl: certificateTemplate.ttl,
projectId: certificateTemplate.projectId
}
}
@@ -181,7 +186,12 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
type: EventType.UPDATE_CERTIFICATE_TEMPLATE,
metadata: {
certificateTemplateId: certificateTemplate.id,
name: certificateTemplate.name
name: certificateTemplate.name,
caId: certificateTemplate.caId,
pkiCollectionId: certificateTemplate.pkiCollectionId as string,
commonName: certificateTemplate.commonName,
subjectAlternativeName: certificateTemplate.subjectAlternativeName,
ttl: certificateTemplate.ttl
}
}
});
@@ -4,18 +4,107 @@ import { CertificateTemplatesV2Schema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { ApiDocsTags } from "@app/lib/api-docs";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
import { slugSchema } from "@app/server/lib/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import {
certificateRequestSchema,
createCertificateTemplateV2Schema,
deleteCertificateTemplateV2Schema,
getCertificateTemplateV2ByIdSchema,
listCertificateTemplatesV2Schema,
updateCertificateTemplateV2Schema
} from "@app/services/certificate-template-v2/certificate-template-v2-schemas";
CertDurationUnit,
CertExtendedKeyUsageType,
CertIncludeType,
CertKeyUsageType,
CertSubjectAlternativeNameType,
CertSubjectAttributeType
} from "@app/services/certificate-common/certificate-constants";
export const registerCertificateTemplatesV2Router = async (server: FastifyZodProvider) => {
const templateV2AttributeSchema = z
.object({
type: z.nativeEnum(CertSubjectAttributeType),
include: z.nativeEnum(CertIncludeType),
value: z.array(z.string()).optional()
})
.refine(
(data) => {
if (data.type === CertSubjectAttributeType.COMMON_NAME && data.value && data.value.length > 1) {
return false;
}
if (data.include === CertIncludeType.MANDATORY && (!data.value || data.value.length > 1)) {
return false;
}
return true;
},
{
message: "Common name can only have one value. Mandatory attributes can only have one value or no value (empty)"
}
);
const templateV2KeyUsagesSchema = z.object({
requiredUsages: z
.object({
all: z.array(z.nativeEnum(CertKeyUsageType))
})
.optional(),
optionalUsages: z
.object({
all: z.array(z.nativeEnum(CertKeyUsageType))
})
.optional()
});
const templateV2ExtendedKeyUsagesSchema = z.object({
requiredUsages: z
.object({
all: z.array(z.nativeEnum(CertExtendedKeyUsageType))
})
.optional(),
optionalUsages: z
.object({
all: z.array(z.nativeEnum(CertExtendedKeyUsageType))
})
.optional()
});
const templateV2SanSchema = z
.object({
type: z.nativeEnum(CertSubjectAlternativeNameType),
include: z.nativeEnum(CertIncludeType),
value: z.array(z.string()).optional()
})
.refine(
(data) => {
if (data.include === CertIncludeType.MANDATORY && (!data.value || data.value.length > 1)) {
return false;
}
return true;
},
{
message: "Mandatory SANs can only have one value or no value (empty)"
}
);
const templateV2ValiditySchema = z.object({
maxDuration: z.object({
value: z.number().positive(),
unit: z.nativeEnum(CertDurationUnit)
}),
minDuration: z
.object({
value: z.number().positive(),
unit: z.nativeEnum(CertDurationUnit)
})
.optional()
});
const templateV2SignatureAlgorithmSchema = z.object({
allowedAlgorithms: z.array(z.string()).min(1),
defaultAlgorithm: z.string()
});
const templateV2KeyAlgorithmSchema = z.object({
allowedKeyTypes: z.array(z.string()).min(1),
defaultKeyType: z.string()
});
server.route({
method: "POST",
url: "/",
@@ -25,7 +114,36 @@ export const registerCertificateTemplatesV2Router = async (server: FastifyZodPro
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
body: createCertificateTemplateV2Schema,
body: z
.object({
projectId: z.string().min(1),
slug: slugSchema({ min: 1, max: 255 }),
description: z.string().max(1000).optional(),
attributes: z.array(templateV2AttributeSchema).optional(),
keyUsages: templateV2KeyUsagesSchema.optional(),
extendedKeyUsages: templateV2ExtendedKeyUsagesSchema.optional(),
subjectAlternativeNames: z.array(templateV2SanSchema).optional(),
validity: templateV2ValiditySchema.optional(),
signatureAlgorithm: templateV2SignatureAlgorithmSchema.optional(),
keyAlgorithm: templateV2KeyAlgorithmSchema.optional()
})
.refine(
(data) => {
const hasConstraints =
(data.attributes && data.attributes.length > 0) ||
(data.subjectAlternativeNames && data.subjectAlternativeNames.length > 0) ||
data.keyUsages ||
data.extendedKeyUsages ||
data.validity ||
data.signatureAlgorithm ||
data.keyAlgorithm;
return hasConstraints;
},
{
message:
"Certificate template must define at least one constraint (attributes, SANs, key usages, validity, or algorithms)"
}
),
response: {
200: z.object({
certificateTemplate: CertificateTemplatesV2Schema
@@ -70,7 +188,12 @@ export const registerCertificateTemplatesV2Router = async (server: FastifyZodPro
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
querystring: listCertificateTemplatesV2Schema,
querystring: z.object({
projectId: z.string().min(1),
offset: z.coerce.number().min(0).default(0),
limit: z.coerce.number().min(1).max(100).default(20),
search: z.string().optional()
}),
response: {
200: z.object({
certificateTemplates: CertificateTemplatesV2Schema.array(),
@@ -112,7 +235,9 @@ export const registerCertificateTemplatesV2Router = async (server: FastifyZodPro
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
params: getCertificateTemplateV2ByIdSchema,
params: z.object({
id: z.string().uuid()
}),
response: {
200: z.object({
certificateTemplate: CertificateTemplatesV2Schema
@@ -154,8 +279,20 @@ export const registerCertificateTemplatesV2Router = async (server: FastifyZodPro
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
params: getCertificateTemplateV2ByIdSchema,
body: updateCertificateTemplateV2Schema,
params: z.object({
id: z.string().uuid()
}),
body: z.object({
slug: slugSchema({ min: 1, max: 255 }).optional(),
description: z.string().max(1000).optional(),
attributes: z.array(templateV2AttributeSchema).optional(),
keyUsages: templateV2KeyUsagesSchema.optional(),
extendedKeyUsages: templateV2ExtendedKeyUsagesSchema.optional(),
subjectAlternativeNames: z.array(templateV2SanSchema).optional(),
validity: templateV2ValiditySchema.optional(),
signatureAlgorithm: templateV2SignatureAlgorithmSchema.optional(),
keyAlgorithm: templateV2KeyAlgorithmSchema.optional()
}),
response: {
200: z.object({
certificateTemplate: CertificateTemplatesV2Schema
@@ -198,7 +335,9 @@ export const registerCertificateTemplatesV2Router = async (server: FastifyZodPro
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
params: deleteCertificateTemplateV2Schema,
params: z.object({
id: z.string().uuid()
}),
response: {
200: z.object({
certificateTemplate: CertificateTemplatesV2Schema
@@ -230,38 +369,4 @@ export const registerCertificateTemplatesV2Router = async (server: FastifyZodPro
return { certificateTemplate };
}
});
server.route({
method: "POST",
url: "/:id/validate",
config: {
rateLimit: readLimit
},
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificateTemplates],
params: getCertificateTemplateV2ByIdSchema,
body: z.object({
request: certificateRequestSchema
}),
response: {
200: z.object({
valid: z.boolean(),
errors: z.array(z.string()).optional()
})
}
},
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const result = await server.services.certificateTemplateV2.validateCertificateRequest(
req.params.id,
req.body.request
);
return {
valid: result.isValid,
errors: result.errors.length > 0 ? result.errors : undefined
};
}
});
};
@@ -6,12 +6,22 @@ import { ms } from "@app/lib/ms";
import { writeLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { CertExtendedKeyUsage, CertKeyUsage } from "@app/services/certificate/certificate-types";
import {
ACMESANType,
CertificateOrderStatus,
CertKeyAlgorithm,
CertSignatureAlgorithm
} from "@app/services/certificate/certificate-types";
import {
validateAltNamesField,
validateAndMapAltNameType,
validateCaDateField
} from "@app/services/certificate-authority/certificate-authority-validators";
import {
CertExtendedKeyUsageType,
CertKeyUsageType,
CertSubjectAlternativeNameType
} from "@app/services/certificate-common/certificate-constants";
import { mapEnumsForValidation } from "@app/services/certificate-common/certificate-utils";
import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators";
@@ -25,18 +35,43 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
body: z.object({
profileId: z.string().uuid(),
commonName: validateTemplateRegexField,
ttl: z.string().refine((val) => ms(val) > 0, "TTL must be a positive number"),
keyUsages: z.nativeEnum(CertKeyUsage).array().optional(),
extendedKeyUsages: z.nativeEnum(CertExtendedKeyUsage).array().optional(),
notBefore: validateCaDateField.optional(),
notAfter: validateCaDateField.optional(),
altNames: validateAltNamesField.optional(),
signatureAlgorithm: z.string().optional(),
keyAlgorithm: z.string().optional()
}),
body: z
.object({
profileId: z.string().uuid(),
commonName: validateTemplateRegexField,
ttl: z.string().refine((val) => ms(val) > 0, "TTL must be a positive number"),
keyUsages: z.nativeEnum(CertKeyUsageType).array().optional(),
extendedKeyUsages: z.nativeEnum(CertExtendedKeyUsageType).array().optional(),
notBefore: validateCaDateField.optional(),
notAfter: validateCaDateField.optional(),
subjectAltNames: validateAltNamesField.optional(),
signatureAlgorithm: z.nativeEnum(CertSignatureAlgorithm).optional(),
keyAlgorithm: z.nativeEnum(CertKeyAlgorithm).optional()
})
.refine(
(data) => {
const hasDateFields = data.notBefore || data.notAfter;
const hasTtl = data.ttl;
return !(hasDateFields && hasTtl);
},
{
message:
"Cannot specify both TTL and notBefore/notAfter. Use either TTL for duration-based validity or notBefore/notAfter for explicit date range."
}
)
.refine(
(data) => {
if (data.notBefore && data.notAfter) {
const notBefore = new Date(data.notBefore);
const notAfter = new Date(data.notAfter);
return notBefore < notAfter;
}
return true;
},
{
message: "notBefore must be earlier than notAfter"
}
),
response: {
200: z.object({
certificate: z.string().trim(),
@@ -54,8 +89,8 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
commonName: req.body.commonName,
keyUsages: req.body.keyUsages,
extendedKeyUsages: req.body.extendedKeyUsages,
subjectAlternativeNames: req.body.altNames
? req.body.altNames
altNames: req.body.subjectAltNames
? req.body.subjectAltNames
.split(", ")
.map((name) => name.trim())
.map((name) => {
@@ -68,7 +103,7 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
url: "uri"
} as const;
return {
type: typeMapping[mappedType.type] as "dns_name" | "ip_address" | "email" | "uri",
type: typeMapping[mappedType.type] as CertSubjectAlternativeNameType,
value: mappedType.value
};
})
@@ -94,23 +129,16 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
certificateRequest: mappedCertificateRequest
});
const profile = await server.services.certificateProfile.getProfileById({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
profileId: req.body.profileId
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
projectId: profile.projectId,
projectId: data.projectId,
event: {
type: EventType.ISSUE_CERTIFICATE_FROM_PROFILE,
metadata: {
certificateProfileId: req.body.profileId,
certificateId: data.certificateId,
commonName: req.body.commonName || ""
commonName: req.body.commonName || "",
profileName: data.profileName
}
}
});
@@ -128,13 +156,38 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
body: z.object({
profileId: z.string().uuid(),
csr: z.string().trim().min(1).max(4096),
ttl: z.string().refine((val) => ms(val) > 0, "TTL must be a positive number"),
notBefore: validateCaDateField.optional(),
notAfter: validateCaDateField.optional()
}),
body: z
.object({
profileId: z.string().uuid(),
csr: z.string().trim().min(1).max(4096),
ttl: z.string().refine((val) => ms(val) > 0, "TTL must be a positive number"),
notBefore: validateCaDateField.optional(),
notAfter: validateCaDateField.optional()
})
.refine(
(data) => {
const hasDateFields = data.notBefore || data.notAfter;
const hasTtl = data.ttl;
return !(hasDateFields && hasTtl);
},
{
message:
"Cannot specify both TTL and notBefore/notAfter. Use either TTL for duration-based validity or notBefore/notAfter for explicit date range."
}
)
.refine(
(data) => {
if (data.notBefore && data.notAfter) {
const notBefore = new Date(data.notBefore);
const notAfter = new Date(data.notAfter);
return notBefore < notAfter;
}
return true;
},
{
message: "notBefore must be earlier than notAfter"
}
),
response: {
200: z.object({
certificate: z.string().trim(),
@@ -161,22 +214,16 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
notAfter: req.body.notAfter ? new Date(req.body.notAfter) : undefined
});
const profile = await server.services.certificateProfile.getProfileById({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
profileId: req.body.profileId
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
projectId: profile.projectId,
projectId: data.projectId,
event: {
type: EventType.SIGN_CERTIFICATE_FROM_PROFILE,
metadata: {
certificateProfileId: req.body.profileId,
certificateId: data.certificateId
certificateId: data.certificateId,
profileName: data.profileName,
commonName: req.body.csr || ""
}
}
});
@@ -194,48 +241,73 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
schema: {
hide: false,
tags: [ApiDocsTags.PkiCertificates],
body: z.object({
profileId: z.string().uuid(),
subjectAlternativeNames: z
.array(
z.object({
type: z.enum(["dns", "ip"]),
value: z.string()
})
)
.min(1),
ttl: z.string().refine((val) => ms(val) > 0, "TTL must be a positive number"),
keyUsages: z.nativeEnum(CertKeyUsage).array().optional(),
extendedKeyUsages: z.nativeEnum(CertExtendedKeyUsage).array().optional(),
notBefore: validateCaDateField.optional(),
notAfter: validateCaDateField.optional(),
commonName: validateTemplateRegexField.optional(),
signatureAlgorithm: z.string().optional(),
keyAlgorithm: z.string().optional()
}),
body: z
.object({
profileId: z.string().uuid(),
subjectAlternativeNames: z
.array(
z.object({
type: z.nativeEnum(ACMESANType),
value: z.string()
})
)
.min(1),
ttl: z.string().refine((val) => ms(val) > 0, "TTL must be a positive number"),
keyUsages: z.nativeEnum(CertKeyUsageType).array().optional(),
extendedKeyUsages: z.nativeEnum(CertExtendedKeyUsageType).array().optional(),
notBefore: validateCaDateField.optional(),
notAfter: validateCaDateField.optional(),
commonName: validateTemplateRegexField.optional(),
signatureAlgorithm: z.nativeEnum(CertSignatureAlgorithm).optional(),
keyAlgorithm: z.nativeEnum(CertKeyAlgorithm).optional()
})
.refine(
(data) => {
const hasDateFields = data.notBefore || data.notAfter;
const hasTtl = data.ttl;
return !(hasDateFields && hasTtl);
},
{
message:
"Cannot specify both TTL and notBefore/notAfter. Use either TTL for duration-based validity or notBefore/notAfter for explicit date range."
}
)
.refine(
(data) => {
if (data.notBefore && data.notAfter) {
const notBefore = new Date(data.notBefore);
const notAfter = new Date(data.notAfter);
return notBefore < notAfter;
}
return true;
},
{
message: "notBefore must be earlier than notAfter"
}
),
response: {
200: z.object({
orderId: z.string(),
status: z.enum(["pending", "processing", "valid", "invalid"]),
status: z.nativeEnum(CertificateOrderStatus),
subjectAlternativeNames: z.array(
z.object({
type: z.enum(["dns", "ip"]),
type: z.nativeEnum(ACMESANType),
value: z.string(),
status: z.enum(["pending", "processing", "valid", "invalid"])
status: z.nativeEnum(CertificateOrderStatus)
})
),
authorizations: z.array(
z.object({
identifier: z.object({
type: z.enum(["dns", "ip"]),
type: z.nativeEnum(ACMESANType),
value: z.string()
}),
status: z.enum(["pending", "processing", "valid", "invalid"]),
status: z.nativeEnum(CertificateOrderStatus),
expires: z.string().optional(),
challenges: z.array(
z.object({
type: z.string(),
status: z.enum(["pending", "processing", "valid", "invalid"]),
status: z.nativeEnum(CertificateOrderStatus),
url: z.string(),
token: z.string()
})
@@ -256,7 +328,7 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
actorOrgId: req.permission.orgId,
profileId: req.body.profileId,
certificateOrder: {
subjectAlternativeNames: req.body.subjectAlternativeNames,
altNames: req.body.subjectAlternativeNames,
validity: {
ttl: req.body.ttl
},
@@ -270,23 +342,15 @@ export const registerCertificatesRouter = async (server: FastifyZodProvider) =>
}
});
const profile = await server.services.certificateProfile.getProfileById({
actor: req.permission.type,
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
profileId: req.body.profileId
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
projectId: profile.projectId,
projectId: data.projectId,
event: {
type: EventType.ORDER_CERTIFICATE_FROM_PROFILE,
metadata: {
certificateProfileId: req.body.profileId,
orderId: data.orderId,
subjectAlternativeNames: req.body.subjectAlternativeNames.map((san) => `${san.type}:${san.value}`)
profileName: data.profileName
}
}
});