From 1145210145a0a445dc272f018d4f45f4a653554a Mon Sep 17 00:00:00 2001 From: Carlos Monastyrski Date: Mon, 1 Dec 2025 10:16:21 -0300 Subject: [PATCH] Improve external configs schema --- .../routes/v1/certificate-profiles-router.ts | 19 +++---- ...ificate-profile-external-config-schemas.ts | 50 +++++++++++++++++++ 2 files changed, 60 insertions(+), 9 deletions(-) create mode 100644 backend/src/services/certificate-profile/certificate-profile-external-config-schemas.ts diff --git a/backend/src/server/routes/v1/certificate-profiles-router.ts b/backend/src/server/routes/v1/certificate-profiles-router.ts index 371ee1d77..685050e5c 100644 --- a/backend/src/server/routes/v1/certificate-profiles-router.ts +++ b/backend/src/server/routes/v1/certificate-profiles-router.ts @@ -8,6 +8,7 @@ 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 { CertStatus } from "@app/services/certificate/certificate-types"; +import { ExternalConfigUnionSchema } from "@app/services/certificate-profile/certificate-profile-external-config-schemas"; import { EnrollmentType, IssuerType } from "@app/services/certificate-profile/certificate-profile-types"; export const registerCertificateProfilesRouter = async (server: FastifyZodProvider) => { @@ -47,7 +48,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid }) .optional(), acmeConfig: z.object({}).optional(), - externalConfigs: z.record(z.unknown()).nullable().optional() + externalConfigs: ExternalConfigUnionSchema }) .refine( (data) => { @@ -151,7 +152,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid response: { 200: z.object({ certificateProfile: PkiCertificateProfilesSchema.extend({ - externalConfigs: z.record(z.unknown()).nullable().optional() + externalConfigs: ExternalConfigUnionSchema }) }) } @@ -247,7 +248,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid directoryUrl: z.string() }) .optional(), - externalConfigs: z.record(z.unknown()).nullable().optional() + externalConfigs: ExternalConfigUnionSchema }).array(), totalCount: z.number() }) @@ -293,7 +294,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid response: { 200: z.object({ certificateProfile: PkiCertificateProfilesSchema.extend({ - externalConfigs: z.record(z.unknown()).nullable().optional() + externalConfigs: ExternalConfigUnionSchema }).extend({ certificateAuthority: z .object({ @@ -328,7 +329,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid renewBeforeDays: z.number().optional() }) .optional(), - externalConfigs: z.record(z.unknown()).nullable().optional() + externalConfigs: ExternalConfigUnionSchema }) }) } @@ -377,7 +378,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid response: { 200: z.object({ certificateProfile: PkiCertificateProfilesSchema.extend({ - externalConfigs: z.record(z.unknown()).nullable().optional() + externalConfigs: ExternalConfigUnionSchema }) }) } @@ -433,7 +434,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid renewBeforeDays: z.number().min(1).max(30).optional() }) .optional(), - externalConfigs: z.record(z.unknown()).nullable().optional() + externalConfigs: ExternalConfigUnionSchema }) .refine( (data) => { @@ -456,7 +457,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid response: { 200: z.object({ certificateProfile: PkiCertificateProfilesSchema.extend({ - externalConfigs: z.record(z.unknown()).nullable().optional() + externalConfigs: ExternalConfigUnionSchema }) }) } @@ -503,7 +504,7 @@ export const registerCertificateProfilesRouter = async (server: FastifyZodProvid response: { 200: z.object({ certificateProfile: PkiCertificateProfilesSchema.extend({ - externalConfigs: z.record(z.unknown()).nullable().optional() + externalConfigs: ExternalConfigUnionSchema }) }) } diff --git a/backend/src/services/certificate-profile/certificate-profile-external-config-schemas.ts b/backend/src/services/certificate-profile/certificate-profile-external-config-schemas.ts new file mode 100644 index 000000000..2d54d0d4f --- /dev/null +++ b/backend/src/services/certificate-profile/certificate-profile-external-config-schemas.ts @@ -0,0 +1,50 @@ +import { z } from "zod"; + +import { CaType } from "@app/services/certificate-authority/certificate-authority-enums"; + +/** + * External configuration schema for Azure AD CS Certificate Authority + */ +export const AzureAdCsExternalConfigSchema = z.object({ + template: z + .string() + .min(1, "Template name is required for Azure AD CS") + .describe("Certificate template name for Azure AD CS") +}); + +/** + * External configuration schema for ACME Certificate Authority + */ +export const AcmeExternalConfigSchema = z.object({}); + +/** + * Map of CA types to their corresponding external configuration schemas + */ +export const ExternalConfigSchemaMap = { + [CaType.AZURE_AD_CS]: AzureAdCsExternalConfigSchema, + [CaType.ACME]: AcmeExternalConfigSchema, + [CaType.INTERNAL]: z.object({}).optional() // Internal CAs don't use external configs +} as const; + +export const createExternalConfigSchema = (caType?: CaType | null) => { + if (!caType || caType === CaType.INTERNAL) { + return z.object({}).nullable().optional(); + } + + const schema = ExternalConfigSchemaMap[caType]; + if (!schema) { + return z.object({}).nullable().optional(); + } + + return schema.nullable().optional(); +}; + +/** + * Union type of all possible external configuration schemas + */ +export const ExternalConfigUnionSchema = z + .union([AzureAdCsExternalConfigSchema, AcmeExternalConfigSchema, z.object({})]) + .nullable() + .optional(); + +export type TExternalConfig = z.infer;