diff --git a/backend/src/ee/services/pki-acme/pki-acme-service.ts b/backend/src/ee/services/pki-acme/pki-acme-service.ts index 1ef8f4c6e..46f67ac17 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-service.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-service.ts @@ -16,11 +16,11 @@ import { EnrollmentType, TCertificateProfileWithConfigs } from "@app/services/certificate-profile/certificate-profile-types"; -import { errors, flattenedVerify, FlattenedVerifyResult, importJWK, JWK, JWSHeaderParameters } from "jose"; +import { errors, flattenedVerify, FlattenedVerifyResult, importJWK, JWSHeaderParameters } from "jose"; import { z, ZodError } from "zod"; import { TPkiAcmeAccountDALFactory } from "./pki-acme-account-dal"; import { TPkiAcmeOrderDALFactory } from "./pki-acme-order-dal"; -import { ProtectedHeaderSchema } from "./pki-acme-schemas"; +import { CreateAcmeAccountBodySchema, ProtectedHeaderSchema } from "./pki-acme-schemas"; import { TAcmeResponse, TCreateAcmeAccountPayload, @@ -49,7 +49,8 @@ type TPkiAcmeServiceFactoryDep = { export const pkiAcmeServiceFactory = ({ certificateProfileDAL, - acmeAccountDAL + acmeAccountDAL, + acmeOrderDAL }: TPkiAcmeServiceFactoryDep): TPkiAcmeServiceFactory => { const validateAcmeProfile = async (profileId: string): Promise => { const profile = await certificateProfileDAL.findById(profileId); @@ -112,6 +113,21 @@ export const pkiAcmeServiceFactory = ({ } }; + const validateNewAccountJwsPayload = async ( + rawJwsPayload: TRawJwsPayload + ): Promise> => { + return await validateJwsPayload( + rawJwsPayload, + async (protectedHeader) => { + if (!protectedHeader.jwk) { + throw new AcmeBadPublicKeyError({ detail: "JWK is required in the protected header" }); + } + return protectedHeader.jwk as unknown as JsonWebKey; + }, + CreateAcmeAccountBodySchema + ); + }; + const getAcmeDirectory = async (profileId: string): Promise => { await validateAcmeProfile(profileId); return { @@ -128,12 +144,17 @@ export const pkiAcmeServiceFactory = ({ return "FIXME-generate-nonce"; }; - const createAcmeAccount = async ( - profileId: string, - alg: string, - jwk: JWK, - { onlyReturnExisting, contact }: TCreateAcmeAccountPayload - ): Promise> => { + const createAcmeAccount = async ({ + profileId, + alg, + jwk, + payload: { onlyReturnExisting, contact } + }: { + profileId: string; + alg: string; + jwk: JsonWebKey; + payload: TCreateAcmeAccountPayload; + }): Promise> => { const profile = await validateAcmeProfile(profileId); const existingAccount: TPkiAcmeAccounts | null = await acmeAccountDAL.findByPublicKey(profileId, alg, jwk); if (onlyReturnExisting && !existingAccount) { @@ -176,6 +197,7 @@ export const pkiAcmeServiceFactory = ({ const createAcmeOrder = async ( profileId: string, + account: TPkiAcmeAccounts, payload: TCreateAcmeOrderPayload ): Promise> => { const profile = await validateAcmeProfile(profileId); @@ -292,6 +314,7 @@ export const pkiAcmeServiceFactory = ({ return { validateJwsPayload, + validateNewAccountJwsPayload, getAcmeDirectory, getAcmeNewNonce, createAcmeAccount, diff --git a/backend/src/ee/services/pki-acme/pki-acme-types.ts b/backend/src/ee/services/pki-acme/pki-acme-types.ts index f5908a922..3bb03f6a6 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-types.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-types.ts @@ -54,14 +54,20 @@ export type TPkiAcmeServiceFactory = { getJWK: (protectedHeader: JWSHeaderParameters) => Promise, schema: z.ZodSchema ) => Promise>; + validateNewAccountJwsPayload: (rawJwsPayload: TRawJwsPayload) => Promise>; getAcmeDirectory: (profileId: string) => Promise; getAcmeNewNonce: (profileId: string) => Promise; - createAcmeAccount: ( - profileId: string, - alg: string, - jwk: JsonWebKey, - body: TCreateAcmeAccountPayload - ) => Promise>; + createAcmeAccount: ({ + profileId, + alg, + jwk, + payload + }: { + profileId: string; + alg: string; + jwk: JsonWebKey; + payload: TCreateAcmeAccountPayload; + }) => Promise>; createAcmeOrder: ( profileId: string, body: TCreateAcmeOrderPayload