diff --git a/backend/src/server/routes/v1/deprecated-certificate-authority-routers/acme-certificate-authority-router.ts b/backend/src/server/routes/v1/deprecated-certificate-authority-routers/acme-certificate-authority-router.ts new file mode 100644 index 000000000..3c549ac1b --- /dev/null +++ b/backend/src/server/routes/v1/deprecated-certificate-authority-routers/acme-certificate-authority-router.ts @@ -0,0 +1,18 @@ +import { AcmeCertificateAuthoritySchema } from "@app/services/certificate-authority/acme/acme-certificate-authority-schemas"; +import { + CreateAcmeCertificateAuthoritySchema, + UpdateAcmeCertificateAuthoritySchema +} from "@app/services/certificate-authority/acme/deprecated-acme-certificate-authority-schemas"; +import { CaType } from "@app/services/certificate-authority/certificate-authority-enums"; + +import { registerCertificateAuthorityEndpoints } from "./certificate-authority-endpoints"; + +export const registerAcmeCertificateAuthorityRouter = async (server: FastifyZodProvider) => { + registerCertificateAuthorityEndpoints({ + caType: CaType.ACME, + server, + responseSchema: AcmeCertificateAuthoritySchema, + createSchema: CreateAcmeCertificateAuthoritySchema, + updateSchema: UpdateAcmeCertificateAuthoritySchema + }); +}; diff --git a/backend/src/server/routes/v1/deprecated-certificate-authority-routers/azure-ad-cs-certificate-authority-router.ts b/backend/src/server/routes/v1/deprecated-certificate-authority-routers/azure-ad-cs-certificate-authority-router.ts new file mode 100644 index 000000000..9407ee681 --- /dev/null +++ b/backend/src/server/routes/v1/deprecated-certificate-authority-routers/azure-ad-cs-certificate-authority-router.ts @@ -0,0 +1,78 @@ +import { z } from "zod"; + +import { EventType } from "@app/ee/services/audit-log/audit-log-types"; +import { readLimit } from "@app/server/config/rateLimiter"; +import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; +import { AuthMode } from "@app/services/auth/auth-type"; +import { AzureAdCsCertificateAuthoritySchema } from "@app/services/certificate-authority/azure-ad-cs/azure-ad-cs-certificate-authority-schemas"; +import { + CreateAzureAdCsCertificateAuthoritySchema, + UpdateAzureAdCsCertificateAuthoritySchema +} from "@app/services/certificate-authority/azure-ad-cs/deprecated-azure-ad-cs-certificate-authority-schemas"; +import { CaType } from "@app/services/certificate-authority/certificate-authority-enums"; + +import { registerCertificateAuthorityEndpoints } from "./certificate-authority-endpoints"; + +export const registerAzureAdCsCertificateAuthorityRouter = async (server: FastifyZodProvider) => { + registerCertificateAuthorityEndpoints({ + caType: CaType.AZURE_AD_CS, + server, + responseSchema: AzureAdCsCertificateAuthoritySchema, + createSchema: CreateAzureAdCsCertificateAuthoritySchema, + updateSchema: UpdateAzureAdCsCertificateAuthoritySchema + }); + + server.route({ + method: "GET", + url: "/:caId/templates", + config: { + rateLimit: readLimit + }, + schema: { + hide: false, + description: "Get available certificate templates from Azure AD CS CA", + params: z.object({ + caId: z.string().describe("Azure AD CS CA ID") + }), + querystring: z.object({ + projectId: z.string().describe("Project ID") + }), + response: { + 200: z.object({ + templates: z.array( + z.object({ + id: z.string().describe("Template identifier"), + name: z.string().describe("Template display name"), + description: z.string().optional().describe("Template description") + }) + ) + }) + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const templates = await server.services.certificateAuthority.getAzureAdcsTemplates({ + caId: req.params.caId, + projectId: req.query.projectId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: req.query.projectId, + event: { + type: EventType.GET_AZURE_AD_TEMPLATES, + metadata: { + caId: req.params.caId, + amount: templates.length + } + } + }); + + return { templates }; + } + }); +}; diff --git a/backend/src/server/routes/v1/deprecated-certificate-authority-routers/certificate-authority-endpoints.ts b/backend/src/server/routes/v1/deprecated-certificate-authority-routers/certificate-authority-endpoints.ts new file mode 100644 index 000000000..dd0f8b215 --- /dev/null +++ b/backend/src/server/routes/v1/deprecated-certificate-authority-routers/certificate-authority-endpoints.ts @@ -0,0 +1,258 @@ +import { z } from "zod"; + +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 { verifyAuth } from "@app/server/plugins/auth/verify-auth"; +import { AuthMode } from "@app/services/auth/auth-type"; +import { CaStatus, CaType } from "@app/services/certificate-authority/certificate-authority-enums"; +import { + TCertificateAuthority, + TCertificateAuthorityInput +} from "@app/services/certificate-authority/certificate-authority-types"; + +export const registerCertificateAuthorityEndpoints = < + T extends TCertificateAuthority, + I extends TCertificateAuthorityInput +>({ + server, + caType, + createSchema, + updateSchema, + responseSchema +}: { + caType: CaType; + server: FastifyZodProvider; + createSchema: z.ZodType<{ + name: string; + projectId: string; + status: CaStatus; + configuration: I["configuration"]; + enableDirectIssuance: boolean; + }>; + updateSchema: z.ZodType<{ + projectId: string; + name?: string; + status?: CaStatus; + configuration?: I["configuration"]; + enableDirectIssuance?: boolean; + }>; + responseSchema: z.ZodTypeAny; +}) => { + server.route({ + method: "GET", + url: `/`, + config: { + rateLimit: readLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + querystring: z.object({ + projectId: z.string().trim().min(1, "Project ID required") + }), + response: { + 200: responseSchema.array() + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const { + query: { projectId } + } = req; + + const certificateAuthorities = (await server.services.certificateAuthority.listCertificateAuthoritiesByProjectId( + { projectId, type: caType }, + req.permission + )) as T[]; + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId, + event: { + type: EventType.GET_CAS, + metadata: { + caIds: certificateAuthorities.map((ca) => ca.id) + } + } + }); + + return certificateAuthorities; + } + }); + + server.route({ + method: "GET", + url: "/:caName", + config: { + rateLimit: readLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + params: z.object({ + caName: z.string() + }), + querystring: z.object({ + projectId: z.string().uuid() + }), + response: { + 200: responseSchema + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const { caName } = req.params; + const { projectId } = req.query; + + const certificateAuthority = + (await server.services.certificateAuthority.findCertificateAuthorityByNameAndProjectId( + { caName, type: caType, projectId }, + req.permission + )) as T; + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: certificateAuthority.projectId, + event: { + type: EventType.GET_CA, + metadata: { + caId: certificateAuthority.id, + name: certificateAuthority.name + } + } + }); + + return certificateAuthority; + } + }); + + server.route({ + method: "POST", + url: "/", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + body: createSchema, + response: { + 200: responseSchema + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const certificateAuthority = (await server.services.certificateAuthority.createCertificateAuthority( + { ...req.body, type: caType }, + req.permission + )) as T; + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: certificateAuthority.projectId, + event: { + type: EventType.CREATE_CA, + metadata: { + name: certificateAuthority.name, + caId: certificateAuthority.id + } + } + }); + + return certificateAuthority; + } + }); + + server.route({ + method: "PATCH", + url: "/:caName", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + params: z.object({ + caName: z.string() + }), + body: updateSchema, + response: { + 200: responseSchema + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const { caName } = req.params; + + const certificateAuthority = (await server.services.certificateAuthority.deprecatedUpdateCertificateAuthority( + { + ...req.body, + type: caType, + caName + }, + req.permission + )) as T; + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: certificateAuthority.projectId, + event: { + type: EventType.UPDATE_CA, + metadata: { + name: certificateAuthority.name, + caId: certificateAuthority.id, + status: certificateAuthority.status + } + } + }); + + return certificateAuthority; + } + }); + + server.route({ + method: "DELETE", + url: "/:caName", + config: { + rateLimit: writeLimit + }, + schema: { + hide: false, + tags: [ApiDocsTags.PkiCertificateAuthorities], + params: z.object({ + caName: z.string() + }), + body: z.object({ + projectId: z.string().uuid() + }), + response: { + 200: responseSchema + } + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + handler: async (req) => { + const { caName } = req.params; + const { projectId } = req.body; + + const certificateAuthority = (await server.services.certificateAuthority.deprecatedDeleteCertificateAuthority( + { caName, type: caType, projectId }, + req.permission + )) as T; + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: certificateAuthority.projectId, + event: { + type: EventType.DELETE_CA, + metadata: { + name: certificateAuthority.name, + caId: certificateAuthority.id + } + } + }); + + return certificateAuthority; + } + }); +}; diff --git a/backend/src/server/routes/v1/deprecated-certificate-authority-routers/index.ts b/backend/src/server/routes/v1/deprecated-certificate-authority-routers/index.ts new file mode 100644 index 000000000..69a783620 --- /dev/null +++ b/backend/src/server/routes/v1/deprecated-certificate-authority-routers/index.ts @@ -0,0 +1,16 @@ +import { CaType } from "@app/services/certificate-authority/certificate-authority-enums"; + +import { registerAcmeCertificateAuthorityRouter } from "./acme-certificate-authority-router"; +import { registerAzureAdCsCertificateAuthorityRouter } from "./azure-ad-cs-certificate-authority-router"; +import { registerInternalCertificateAuthorityRouter } from "./internal-certificate-authority-router"; + +export * from "./internal-certificate-authority-router"; + +export const DEPRECATED_CERTIFICATE_AUTHORITY_REGISTER_ROUTER_MAP: Record< + CaType, + (server: FastifyZodProvider) => Promise +> = { + [CaType.INTERNAL]: registerInternalCertificateAuthorityRouter, + [CaType.ACME]: registerAcmeCertificateAuthorityRouter, + [CaType.AZURE_AD_CS]: registerAzureAdCsCertificateAuthorityRouter +}; diff --git a/backend/src/server/routes/v1/deprecated-certificate-authority-routers/internal-certificate-authority-router.ts b/backend/src/server/routes/v1/deprecated-certificate-authority-routers/internal-certificate-authority-router.ts new file mode 100644 index 000000000..848367d70 --- /dev/null +++ b/backend/src/server/routes/v1/deprecated-certificate-authority-routers/internal-certificate-authority-router.ts @@ -0,0 +1,18 @@ +import { CaType } from "@app/services/certificate-authority/certificate-authority-enums"; +import { + CreateInternalCertificateAuthoritySchema, + UpdateInternalCertificateAuthoritySchema +} from "@app/services/certificate-authority/internal/deprecated-internal-certificate-authority-schemas"; +import { InternalCertificateAuthoritySchema } from "@app/services/certificate-authority/internal/internal-certificate-authority-schemas"; + +import { registerCertificateAuthorityEndpoints } from "./certificate-authority-endpoints"; + +export const registerInternalCertificateAuthorityRouter = async (server: FastifyZodProvider) => { + registerCertificateAuthorityEndpoints({ + caType: CaType.INTERNAL, + server, + responseSchema: InternalCertificateAuthoritySchema, + createSchema: CreateInternalCertificateAuthoritySchema, + updateSchema: UpdateInternalCertificateAuthoritySchema + }); +}; diff --git a/backend/src/server/routes/v1/index.ts b/backend/src/server/routes/v1/index.ts index fc509a5ab..c27399453 100644 --- a/backend/src/server/routes/v1/index.ts +++ b/backend/src/server/routes/v1/index.ts @@ -15,6 +15,7 @@ import { registerGeneralCertificateAuthorityRouter } from "./certificate-authori import { registerCertificateProfilesRouter } from "./certificate-profiles-router"; import { registerCertificateRouter } from "./certificate-router"; import { registerCertificateTemplateRouter } from "./certificate-template-router"; +import { DEPRECATED_CERTIFICATE_AUTHORITY_REGISTER_ROUTER_MAP } from "./deprecated-certificate-authority-routers"; import { registerDeprecatedCertRouter } from "./deprecated-certificate-router"; import { registerDeprecatedCertificateTemplateRouter } from "./deprecated-certificate-template-router"; import { registerDeprecatedIdentityProjectMembershipRouter } from "./deprecated-identity-project-membership-router"; @@ -190,7 +191,7 @@ export const registerV1Routes = async (server: FastifyZodProvider) => { await pkiRouter.register(registerCaRouter, { prefix: "/ca" }); await pkiRouter.register( async (caRouter) => { - for await (const [caType, router] of Object.entries(CERTIFICATE_AUTHORITY_REGISTER_ROUTER_MAP)) { + for await (const [caType, router] of Object.entries(DEPRECATED_CERTIFICATE_AUTHORITY_REGISTER_ROUTER_MAP)) { await caRouter.register(router, { prefix: `/${caType}` }); } }, diff --git a/backend/src/services/certificate-authority/acme/deprecated-acme-certificate-authority-schemas.ts b/backend/src/services/certificate-authority/acme/deprecated-acme-certificate-authority-schemas.ts new file mode 100644 index 000000000..232475380 --- /dev/null +++ b/backend/src/services/certificate-authority/acme/deprecated-acme-certificate-authority-schemas.ts @@ -0,0 +1,14 @@ +import { CaType } from "../certificate-authority-enums"; +import { + GenericCreateCertificateAuthorityFieldsSchema, + GenericUpdateCertificateAuthorityFieldsSchema +} from "../deprecated-certificate-authority-schemas"; +import { AcmeCertificateAuthorityConfigurationSchema } from "./acme-certificate-authority-schemas"; + +export const CreateAcmeCertificateAuthoritySchema = GenericCreateCertificateAuthorityFieldsSchema(CaType.ACME).extend({ + configuration: AcmeCertificateAuthorityConfigurationSchema +}); + +export const UpdateAcmeCertificateAuthoritySchema = GenericUpdateCertificateAuthorityFieldsSchema(CaType.ACME).extend({ + configuration: AcmeCertificateAuthorityConfigurationSchema.optional() +}); diff --git a/backend/src/services/certificate-authority/azure-ad-cs/deprecated-azure-ad-cs-certificate-authority-schemas.ts b/backend/src/services/certificate-authority/azure-ad-cs/deprecated-azure-ad-cs-certificate-authority-schemas.ts new file mode 100644 index 000000000..a695fcec4 --- /dev/null +++ b/backend/src/services/certificate-authority/azure-ad-cs/deprecated-azure-ad-cs-certificate-authority-schemas.ts @@ -0,0 +1,18 @@ +import { CaType } from "../certificate-authority-enums"; +import { + GenericCreateCertificateAuthorityFieldsSchema, + GenericUpdateCertificateAuthorityFieldsSchema +} from "../deprecated-certificate-authority-schemas"; +import { AzureAdCsCertificateAuthorityConfigurationSchema } from "./azure-ad-cs-certificate-authority-schemas"; + +export const CreateAzureAdCsCertificateAuthoritySchema = GenericCreateCertificateAuthorityFieldsSchema( + CaType.AZURE_AD_CS +).extend({ + configuration: AzureAdCsCertificateAuthorityConfigurationSchema +}); + +export const UpdateAzureAdCsCertificateAuthoritySchema = GenericUpdateCertificateAuthorityFieldsSchema( + CaType.AZURE_AD_CS +).extend({ + configuration: AzureAdCsCertificateAuthorityConfigurationSchema.optional() +}); diff --git a/backend/src/services/certificate-authority/certificate-authority-service.ts b/backend/src/services/certificate-authority/certificate-authority-service.ts index 715400b5f..b9b3b8d42 100644 --- a/backend/src/services/certificate-authority/certificate-authority-service.ts +++ b/backend/src/services/certificate-authority/certificate-authority-service.ts @@ -37,6 +37,7 @@ import { CaType } from "./certificate-authority-enums"; import { TCertificateAuthority, TCreateCertificateAuthorityDTO, + TDeprecatedUpdateCertificateAuthorityDTO, TUpdateCertificateAuthorityDTO } from "./certificate-authority-types"; import { TExternalCertificateAuthorityDALFactory } from "./external-certificate-authority-dal"; @@ -245,6 +246,69 @@ export const certificateAuthorityServiceFactory = ({ throw new BadRequestError({ message: "Invalid certificate authority type" }); }; + const findCertificateAuthorityByNameAndProjectId = async ( + { caName, type, projectId }: { caName: string; type: CaType; projectId: string }, + actor: OrgServiceActor + ) => { + const certificateAuthority = await certificateAuthorityDAL.findByNameAndProjectIdWithAssociatedCa( + caName, + projectId + ); + + if (!certificateAuthority) + throw new NotFoundError({ + message: `Could not find certificate authority with name "${caName}" in project "${projectId}"` + }); + + const { permission } = await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, + projectId: certificateAuthority.projectId, + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.CertificateManager + }); + + ForbiddenError.from(permission).throwUnlessCan( + ProjectPermissionActions.Read, + ProjectPermissionSub.CertificateAuthorities + ); + + if (type === CaType.INTERNAL) { + if (!certificateAuthority.internalCa?.id) { + throw new NotFoundError({ + message: `Internal certificate authority with name "${caName}" in project "${projectId}" not found` + }); + } + + return { + id: certificateAuthority.id, + type, + enableDirectIssuance: certificateAuthority.enableDirectIssuance, + name: certificateAuthority.name, + projectId: certificateAuthority.projectId, + configuration: certificateAuthority.internalCa, + status: certificateAuthority.status + } as TCertificateAuthority; + } + + if (certificateAuthority.externalCa?.type !== type) { + throw new NotFoundError({ + message: `Could not find external certificate authority with name "${caName}" in project "${projectId}" and type "${type}"` + }); + } + + if (type === CaType.ACME) { + return castDbEntryToAcmeCertificateAuthority(certificateAuthority); + } + + if (type === CaType.AZURE_AD_CS) { + return castDbEntryToAzureAdCsCertificateAuthority(certificateAuthority); + } + + throw new BadRequestError({ message: "Invalid certificate authority type" }); + }; + const listCertificateAuthoritiesByProjectId = async ( { projectId, type }: { projectId: string; type: CaType }, actor: OrgServiceActor @@ -431,6 +495,153 @@ export const certificateAuthorityServiceFactory = ({ throw new BadRequestError({ message: "Invalid certificate authority type" }); }; + const deprecatedUpdateCertificateAuthority = async ( + { caName, type, configuration, status, name, projectId }: TDeprecatedUpdateCertificateAuthorityDTO, + actor: OrgServiceActor + ) => { + const certificateAuthority = await certificateAuthorityDAL.findByNameAndProjectIdWithAssociatedCa( + caName, + projectId + ); + + if (!certificateAuthority) + throw new NotFoundError({ + message: `Could not find certificate authority with name "${caName}" in project "${projectId}"` + }); + + const { permission } = await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, + projectId: certificateAuthority.projectId, + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.CertificateManager + }); + + ForbiddenError.from(permission).throwUnlessCan( + ProjectPermissionActions.Edit, + ProjectPermissionSub.CertificateAuthorities + ); + + if (type === CaType.INTERNAL) { + if (!certificateAuthority.internalCa?.id) { + throw new NotFoundError({ + message: `Internal certificate authority with name "${caName}" in project "${projectId}" not found` + }); + } + + const updatedCa = await internalCertificateAuthorityService.updateCaById({ + isInternal: true, + caId: certificateAuthority.id, + status, + name + }); + + if (!updatedCa.internalCa) { + throw new BadRequestError({ + message: "Failed to update internal certificate authority" + }); + } + + return { + id: updatedCa.id, + type, + enableDirectIssuance: updatedCa.enableDirectIssuance, + name: updatedCa.name, + projectId: updatedCa.projectId, + configuration: updatedCa.internalCa, + status: updatedCa.status + } as TCertificateAuthority; + } + + if (type === CaType.ACME) { + return acmeFns.updateCertificateAuthority({ + id: certificateAuthority.id, + configuration: configuration as TUpdateAcmeCertificateAuthorityDTO["configuration"], + actor, + status, + name + }); + } + + if (type === CaType.AZURE_AD_CS) { + return azureAdCsFns.updateCertificateAuthority({ + id: certificateAuthority.id, + configuration: configuration as TUpdateAzureAdCsCertificateAuthorityDTO["configuration"], + actor, + status, + name + }); + } + + throw new BadRequestError({ message: "Invalid certificate authority type" }); + }; + + const deprecatedDeleteCertificateAuthority = async ( + { caName, type, projectId }: { caName: string; type: CaType; projectId: string }, + actor: OrgServiceActor + ) => { + const certificateAuthority = await certificateAuthorityDAL.findByNameAndProjectIdWithAssociatedCa( + caName, + projectId + ); + + if (!certificateAuthority) + throw new NotFoundError({ + message: `Could not find certificate authority with name "${caName}" in project "${projectId}"` + }); + + const { permission } = await permissionService.getProjectPermission({ + actor: actor.type, + actorId: actor.id, + projectId: certificateAuthority.projectId, + actorAuthMethod: actor.authMethod, + actorOrgId: actor.orgId, + actionProjectType: ActionProjectType.CertificateManager + }); + + ForbiddenError.from(permission).throwUnlessCan( + ProjectPermissionActions.Delete, + ProjectPermissionSub.CertificateAuthorities + ); + + if (!certificateAuthority.internalCa?.id && type === CaType.INTERNAL) { + throw new BadRequestError({ + message: "Internal certificate authority cannot be deleted" + }); + } + + if (certificateAuthority.externalCa?.id && certificateAuthority.externalCa.type !== type) { + throw new BadRequestError({ + message: "External certificate authority cannot be deleted" + }); + } + + await certificateAuthorityDAL.deleteById(certificateAuthority.id); + + if (type === CaType.INTERNAL) { + return { + id: certificateAuthority.id, + type, + enableDirectIssuance: certificateAuthority.enableDirectIssuance, + name: certificateAuthority.name, + projectId: certificateAuthority.projectId, + configuration: certificateAuthority.internalCa, + status: certificateAuthority.status + } as TCertificateAuthority; + } + + if (type === CaType.ACME) { + return castDbEntryToAcmeCertificateAuthority(certificateAuthority); + } + + if (type === CaType.AZURE_AD_CS) { + return castDbEntryToAzureAdCsCertificateAuthority(certificateAuthority); + } + + throw new BadRequestError({ message: "Invalid certificate authority type" }); + }; + const getAzureAdcsTemplates = async ({ caId, projectId, @@ -470,8 +681,11 @@ export const certificateAuthorityServiceFactory = ({ createCertificateAuthority, findCertificateAuthorityById, listCertificateAuthoritiesByProjectId, + findCertificateAuthorityByNameAndProjectId, updateCertificateAuthority, deleteCertificateAuthority, - getAzureAdcsTemplates + getAzureAdcsTemplates, + deprecatedUpdateCertificateAuthority, + deprecatedDeleteCertificateAuthority }; }; diff --git a/backend/src/services/certificate-authority/certificate-authority-types.ts b/backend/src/services/certificate-authority/certificate-authority-types.ts index 4f1a67c0e..029c9a760 100644 --- a/backend/src/services/certificate-authority/certificate-authority-types.ts +++ b/backend/src/services/certificate-authority/certificate-authority-types.ts @@ -25,3 +25,9 @@ export type TUpdateCertificateAuthorityDTO = Partial> & { + type: CaType; + caName: string; + projectId: string; +}; diff --git a/backend/src/services/certificate-authority/deprecated-certificate-authority-schemas.ts b/backend/src/services/certificate-authority/deprecated-certificate-authority-schemas.ts new file mode 100644 index 000000000..5ecc50a4b --- /dev/null +++ b/backend/src/services/certificate-authority/deprecated-certificate-authority-schemas.ts @@ -0,0 +1,32 @@ +import z from "zod"; + +import { CertificateAuthoritiesSchema } from "@app/db/schemas"; +import { CertificateAuthorities } from "@app/lib/api-docs/constants"; +import { slugSchema } from "@app/server/lib/schemas"; + +import { CaStatus, CaType } from "./certificate-authority-enums"; + +export const BaseCertificateAuthoritySchema = CertificateAuthoritiesSchema.pick({ + projectId: true, + enableDirectIssuance: true, + name: true, + id: true +}).extend({ + status: z.nativeEnum(CaStatus) +}); + +export const GenericCreateCertificateAuthorityFieldsSchema = (type: CaType) => + z.object({ + name: slugSchema({ field: "name" }).describe(CertificateAuthorities.CREATE(type).name), + projectId: z.string().uuid("Project ID must be valid").describe(CertificateAuthorities.CREATE(type).projectId), + enableDirectIssuance: z.boolean().describe(CertificateAuthorities.CREATE(type).enableDirectIssuance), + status: z.nativeEnum(CaStatus).describe(CertificateAuthorities.CREATE(type).status) + }); + +export const GenericUpdateCertificateAuthorityFieldsSchema = (type: CaType) => + z.object({ + name: slugSchema({ field: "name" }).optional().describe(CertificateAuthorities.UPDATE(type).name), + projectId: z.string().uuid("Project ID must be valid").describe(CertificateAuthorities.UPDATE(type).projectId), + enableDirectIssuance: z.boolean().optional().describe(CertificateAuthorities.UPDATE(type).enableDirectIssuance), + status: z.nativeEnum(CaStatus).optional().describe(CertificateAuthorities.UPDATE(type).status) + }); diff --git a/backend/src/services/certificate-authority/internal/deprecated-internal-certificate-authority-schemas.ts b/backend/src/services/certificate-authority/internal/deprecated-internal-certificate-authority-schemas.ts new file mode 100644 index 000000000..292af17c9 --- /dev/null +++ b/backend/src/services/certificate-authority/internal/deprecated-internal-certificate-authority-schemas.ts @@ -0,0 +1,14 @@ +import { CaType } from "../certificate-authority-enums"; +import { + GenericCreateCertificateAuthorityFieldsSchema, + GenericUpdateCertificateAuthorityFieldsSchema +} from "../deprecated-certificate-authority-schemas"; +import { InternalCertificateAuthorityConfigurationSchema } from "./internal-certificate-authority-schemas"; + +export const CreateInternalCertificateAuthoritySchema = GenericCreateCertificateAuthorityFieldsSchema( + CaType.INTERNAL +).extend({ + configuration: InternalCertificateAuthorityConfigurationSchema +}); + +export const UpdateInternalCertificateAuthoritySchema = GenericUpdateCertificateAuthorityFieldsSchema(CaType.INTERNAL); diff --git a/backend/src/services/certificate-authority/internal/internal-certificate-authority-schemas.ts b/backend/src/services/certificate-authority/internal/internal-certificate-authority-schemas.ts index 1cf9a8597..e3b6b4b21 100644 --- a/backend/src/services/certificate-authority/internal/internal-certificate-authority-schemas.ts +++ b/backend/src/services/certificate-authority/internal/internal-certificate-authority-schemas.ts @@ -11,7 +11,7 @@ import { } from "../certificate-authority-schemas"; import { validateCaDateField } from "../certificate-authority-validators"; -const InternalCertificateAuthorityConfigurationSchema = z +export const InternalCertificateAuthorityConfigurationSchema = z .object({ type: z.nativeEnum(InternalCaType).describe(CertificateAuthorities.CONFIGURATIONS.INTERNAL.type), friendlyName: z.string().optional().describe(CertificateAuthorities.CONFIGURATIONS.INTERNAL.friendlyName),