Use the same find by account and order id to always have valid obj ownership check

This commit is contained in:
Fang-Pen Lin
2025-10-30 09:55:59 -07:00
parent 6b85ab54a4
commit 0ed464308f
4 changed files with 44 additions and 46 deletions

View File

@@ -371,11 +371,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
return sendAcmeResponse(
res,
profileId,
await server.services.pkiAcme.downloadAcmeCertificate({
profileId,
accountId,
orderId: req.params.orderId
})
await server.services.pkiAcme.downloadAcmeCertificate({ profileId, accountId, orderId: req.params.orderId })
);
}
});

View File

@@ -51,7 +51,7 @@ export const pkiAcmeOrderDALFactory = (db: TDbClient) => {
}
};
const findByIdWithAuthorizations = async (id: string, tx?: Knex) => {
const findByAccountAndOrderIdWithAuthorizations = async (accountId: string, orderId: string, tx?: Knex) => {
try {
const order = await (tx || db)(TableName.PkiAcmeOrder)
.join(TableName.PkiAcmeOrderAuth, `${TableName.PkiAcmeOrderAuth}.orderId`, `${TableName.PkiAcmeOrder}.id`)
@@ -63,7 +63,8 @@ export const pkiAcmeOrderDALFactory = (db: TDbClient) => {
db.ref("identifierValue").withSchema(TableName.PkiAcmeAuth).as("identifierValue"),
db.ref("expiresAt").withSchema(TableName.PkiAcmeAuth).as("expiresAt")
)
.where(`${TableName.PkiAcmeOrder}.id`, id)
.where(`${TableName.PkiAcmeOrder}.id`, orderId)
.where(`${TableName.PkiAcmeOrder}.accountId`, accountId)
.first();
if (!order) {
@@ -88,6 +89,6 @@ export const pkiAcmeOrderDALFactory = (db: TDbClient) => {
create,
updateById,
findById,
findByIdWithAuthorizations
findByAccountAndOrderIdWithAuthorizations
};
};

View File

@@ -53,7 +53,7 @@ import {
type TPkiAcmeServiceFactoryDep = {
certificateProfileDAL: Pick<TCertificateProfileDALFactory, "findById">;
acmeAccountDAL: Pick<TPkiAcmeAccountDALFactory, "findByProjectIdAndAccountId" | "findByPublicKey" | "create">;
acmeOrderDAL: Pick<TPkiAcmeOrderDALFactory, "create" | "transaction" | "findByIdWithAuthorizations">;
acmeOrderDAL: Pick<TPkiAcmeOrderDALFactory, "create" | "transaction" | "findByAccountAndOrderIdWithAuthorizations">;
acmeAuthDAL: Pick<TPkiAcmeAuthDALFactory, "create" | "findById">;
acmeOrderAuthDAL: Pick<TPkiAcmeOrderAuthDALFactory, "insertMany">;
};
@@ -396,8 +396,8 @@ export const pkiAcmeServiceFactory = ({
accountId: string;
orderId: string;
}): Promise<TAcmeResponse<TAcmeOrderResource>> => {
const order = await acmeOrderDAL.findByIdWithAuthorizations(orderId);
if (!order || order.accountId !== accountId) {
const order = await acmeOrderDAL.findByAccountAndOrderIdWithAuthorizations(accountId, orderId);
if (!order) {
throw new NotFoundError({ message: "ACME order not found" });
}
return {
@@ -418,25 +418,45 @@ export const pkiAcmeServiceFactory = ({
orderId: string;
payload: TFinalizeAcmeOrderPayload;
}): Promise<TAcmeResponse<TAcmeOrderResource>> => {
const profile = await validateAcmeProfile(profileId);
const order = await acmeOrderDAL.findByAccountAndOrderIdWithAuthorizations(accountId, orderId);
if (!order) {
throw new NotFoundError({ message: "ACME order not found" });
}
const { csr } = payload;
// FIXME: Implement ACME finalize order
return {
status: 200,
body: {
status: "processing",
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
identifiers: [],
authorizations: [],
finalize: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/finalize`),
certificate: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/certificate`)
},
body: buildAcmeOrderResource({ profileId, order }),
headers: {
Location: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}`)
}
};
};
const downloadAcmeCertificate = async ({
profileId,
accountId,
orderId
}: {
profileId: string;
accountId: string;
orderId: string;
}): Promise<TAcmeResponse<string>> => {
const order = await acmeOrderDAL.findByAccountAndOrderIdWithAuthorizations(accountId, orderId);
if (!order) {
throw new NotFoundError({ message: "ACME order not found" });
}
// FIXME: Implement ACME certificate download
// Return the certificate in PEM format
return {
status: 200,
body: "FIXME-certificate-pem",
headers: {
Location: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/certificate`)
}
};
};
const listAcmeOrders = async ({
profileId,
accountId
@@ -457,25 +477,6 @@ export const pkiAcmeServiceFactory = ({
};
};
const downloadAcmeCertificate = async ({
profileId,
orderId
}: {
profileId: string;
orderId: string;
}): Promise<TAcmeResponse<string>> => {
const profile = await validateAcmeProfile(profileId);
// FIXME: Implement ACME certificate download
// Return the certificate in PEM format
return {
status: 200,
body: "FIXME-certificate-pem",
headers: {
Location: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/certificate`)
}
};
};
/** --------------------------------------------------------------
* ACME Authorization
* -------------------------------------------------------------- */

View File

@@ -123,13 +123,6 @@ export type TPkiAcmeServiceFactory = {
orderId: string;
payload: TFinalizeAcmeOrderPayload;
}) => Promise<TAcmeResponse<TAcmeOrderResource>>;
listAcmeOrders: ({
profileId,
accountId
}: {
profileId: string;
accountId: string;
}) => Promise<TAcmeResponse<TListAcmeOrdersResponse>>;
downloadAcmeCertificate: ({
profileId,
accountId,
@@ -139,6 +132,13 @@ export type TPkiAcmeServiceFactory = {
accountId: string;
orderId: string;
}) => Promise<TAcmeResponse<string>>;
listAcmeOrders: ({
profileId,
accountId
}: {
profileId: string;
accountId: string;
}) => Promise<TAcmeResponse<TListAcmeOrdersResponse>>;
getAcmeAuthorization: ({
profileId,
accountId,