diff --git a/backend/src/ee/services/pki-acme/pki-acme-account-dal.ts b/backend/src/ee/services/pki-acme/pki-acme-account-dal.ts index e7979826d..a460ddacc 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-account-dal.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-account-dal.ts @@ -26,7 +26,7 @@ export const pkiAcmeAccountDALFactory = (db: TDbClient) => { } }; - const findById = async (profileId: string, id: string, tx?: Knex) => { + const findByProjectIdAndAccountId = async (profileId: string, id: string, tx?: Knex) => { try { const account = await (tx || db)(TableName.PkiAcmeAccount).where({ profileId, id }).first(); @@ -49,7 +49,7 @@ export const pkiAcmeAccountDALFactory = (db: TDbClient) => { return { ...pkiAcmeAccountOrm, create, - findById, + findByProjectIdAndAccountId, findByPublicKey }; }; diff --git a/backend/src/ee/services/pki-acme/pki-acme-schemas.ts b/backend/src/ee/services/pki-acme/pki-acme-schemas.ts index ec2197466..a10476ca4 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-schemas.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-schemas.ts @@ -114,6 +114,8 @@ export const DeactivateAcmeAccountResponseSchema = z.object({ }); // List Orders endpoint +export const ListAcmeOrdersPayloadSchema = z.object({}).strict(); + export const ListAcmeOrdersResponseSchema = z.object({ orders: z.array(z.string()) }); 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 6f35aa15d..ba9197b33 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-service.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-service.ts @@ -53,7 +53,7 @@ import { type TPkiAcmeServiceFactoryDep = { certificateProfileDAL: Pick; - acmeAccountDAL: Pick; + acmeAccountDAL: Pick; acmeOrderDAL: Pick; acmeAuthDAL: Pick; acmeOrderAuthDAL: Pick; @@ -150,11 +150,17 @@ export const pkiAcmeServiceFactory = ({ ); }; - const validateExistingAccountJwsPayload = async ( - profileId: string, - rawJwsPayload: TRawJwsPayload, - schema: z.ZodSchema - ): Promise> => { + const validateExistingAccountJwsPayload = async ({ + profileId, + rawJwsPayload, + schema, + expectedAccountId + }: { + profileId: string; + rawJwsPayload: TRawJwsPayload; + schema: z.ZodSchema; + expectedAccountId?: string; + }): Promise> => { const profile = await validateAcmeProfile(profileId); const result = await validateJwsPayload( rawJwsPayload, @@ -163,7 +169,10 @@ export const pkiAcmeServiceFactory = ({ throw new AcmeMalformedError({ detail: "KID is required in the protected header" }); } const accountId = extractAccountIdFromKid(protectedHeader.kid, profileId); - const account = await acmeAccountDAL.findById(profile.id, accountId); + if (expectedAccountId && accountId !== expectedAccountId) { + throw new AcmeAccountDoesNotExistError({ message: "ACME account ID mismatch" }); + } + const account = await acmeAccountDAL.findByProjectIdAndAccountId(profile.id, accountId); if (!account) { throw new AcmeAccountDoesNotExistError({ message: "ACME account not found" }); } @@ -261,7 +270,7 @@ export const pkiAcmeServiceFactory = ({ // if we do, return the existing order const order = await acmeOrderDAL.transaction(async (tx) => { - const account = await acmeAccountDAL.findById(profileId, accountId)!; + const account = await acmeAccountDAL.findByProjectIdAndAccountId(profileId, accountId)!; const createdOrder = await acmeOrderDAL.create( { accountId: account.id, 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 811d121ad..827e28c7e 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-types.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-types.ts @@ -58,11 +58,17 @@ export type TPkiAcmeServiceFactory = { schema: z.ZodSchema ) => Promise>; validateNewAccountJwsPayload: (rawJwsPayload: TRawJwsPayload) => Promise>; - validateExistingAccountJwsPayload: ( - profileId: string, - rawJwsPayload: TRawJwsPayload, - schema: z.ZodSchema - ) => Promise>; + validateExistingAccountJwsPayload: ({ + profileId, + rawJwsPayload, + schema, + expectedAccountId + }: { + profileId: string; + rawJwsPayload: TRawJwsPayload; + schema: z.ZodSchema; + expectedAccountId?: string; + }) => Promise>; getAcmeDirectory: (profileId: string) => Promise; getAcmeNewNonce: (profileId: string) => Promise; createAcmeAccount: ({