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-11-07 09:18:39 -08:00
parent 6b85ab54a4
commit 0ed464308f
4 changed files with 44 additions and 46 deletions
+1 -5
View File
@@ -371,11 +371,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
return sendAcmeResponse( return sendAcmeResponse(
res, res,
profileId, profileId,
await server.services.pkiAcme.downloadAcmeCertificate({ await server.services.pkiAcme.downloadAcmeCertificate({ profileId, accountId, orderId: req.params.orderId })
profileId,
accountId,
orderId: req.params.orderId
})
); );
} }
}); });
@@ -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 { try {
const order = await (tx || db)(TableName.PkiAcmeOrder) const order = await (tx || db)(TableName.PkiAcmeOrder)
.join(TableName.PkiAcmeOrderAuth, `${TableName.PkiAcmeOrderAuth}.orderId`, `${TableName.PkiAcmeOrder}.id`) .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("identifierValue").withSchema(TableName.PkiAcmeAuth).as("identifierValue"),
db.ref("expiresAt").withSchema(TableName.PkiAcmeAuth).as("expiresAt") db.ref("expiresAt").withSchema(TableName.PkiAcmeAuth).as("expiresAt")
) )
.where(`${TableName.PkiAcmeOrder}.id`, id) .where(`${TableName.PkiAcmeOrder}.id`, orderId)
.where(`${TableName.PkiAcmeOrder}.accountId`, accountId)
.first(); .first();
if (!order) { if (!order) {
@@ -88,6 +89,6 @@ export const pkiAcmeOrderDALFactory = (db: TDbClient) => {
create, create,
updateById, updateById,
findById, findById,
findByIdWithAuthorizations findByAccountAndOrderIdWithAuthorizations
}; };
}; };
@@ -53,7 +53,7 @@ import {
type TPkiAcmeServiceFactoryDep = { type TPkiAcmeServiceFactoryDep = {
certificateProfileDAL: Pick<TCertificateProfileDALFactory, "findById">; certificateProfileDAL: Pick<TCertificateProfileDALFactory, "findById">;
acmeAccountDAL: Pick<TPkiAcmeAccountDALFactory, "findByProjectIdAndAccountId" | "findByPublicKey" | "create">; acmeAccountDAL: Pick<TPkiAcmeAccountDALFactory, "findByProjectIdAndAccountId" | "findByPublicKey" | "create">;
acmeOrderDAL: Pick<TPkiAcmeOrderDALFactory, "create" | "transaction" | "findByIdWithAuthorizations">; acmeOrderDAL: Pick<TPkiAcmeOrderDALFactory, "create" | "transaction" | "findByAccountAndOrderIdWithAuthorizations">;
acmeAuthDAL: Pick<TPkiAcmeAuthDALFactory, "create" | "findById">; acmeAuthDAL: Pick<TPkiAcmeAuthDALFactory, "create" | "findById">;
acmeOrderAuthDAL: Pick<TPkiAcmeOrderAuthDALFactory, "insertMany">; acmeOrderAuthDAL: Pick<TPkiAcmeOrderAuthDALFactory, "insertMany">;
}; };
@@ -396,8 +396,8 @@ export const pkiAcmeServiceFactory = ({
accountId: string; accountId: string;
orderId: string; orderId: string;
}): Promise<TAcmeResponse<TAcmeOrderResource>> => { }): Promise<TAcmeResponse<TAcmeOrderResource>> => {
const order = await acmeOrderDAL.findByIdWithAuthorizations(orderId); const order = await acmeOrderDAL.findByAccountAndOrderIdWithAuthorizations(accountId, orderId);
if (!order || order.accountId !== accountId) { if (!order) {
throw new NotFoundError({ message: "ACME order not found" }); throw new NotFoundError({ message: "ACME order not found" });
} }
return { return {
@@ -418,25 +418,45 @@ export const pkiAcmeServiceFactory = ({
orderId: string; orderId: string;
payload: TFinalizeAcmeOrderPayload; payload: TFinalizeAcmeOrderPayload;
}): Promise<TAcmeResponse<TAcmeOrderResource>> => { }): 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; const { csr } = payload;
// FIXME: Implement ACME finalize order // FIXME: Implement ACME finalize order
return { return {
status: 200, status: 200,
body: { body: buildAcmeOrderResource({ profileId, order }),
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`)
},
headers: { headers: {
Location: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}`) 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 ({ const listAcmeOrders = async ({
profileId, profileId,
accountId 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 * ACME Authorization
* -------------------------------------------------------------- */ * -------------------------------------------------------------- */
@@ -123,13 +123,6 @@ export type TPkiAcmeServiceFactory = {
orderId: string; orderId: string;
payload: TFinalizeAcmeOrderPayload; payload: TFinalizeAcmeOrderPayload;
}) => Promise<TAcmeResponse<TAcmeOrderResource>>; }) => Promise<TAcmeResponse<TAcmeOrderResource>>;
listAcmeOrders: ({
profileId,
accountId
}: {
profileId: string;
accountId: string;
}) => Promise<TAcmeResponse<TListAcmeOrdersResponse>>;
downloadAcmeCertificate: ({ downloadAcmeCertificate: ({
profileId, profileId,
accountId, accountId,
@@ -139,6 +132,13 @@ export type TPkiAcmeServiceFactory = {
accountId: string; accountId: string;
orderId: string; orderId: string;
}) => Promise<TAcmeResponse<string>>; }) => Promise<TAcmeResponse<string>>;
listAcmeOrders: ({
profileId,
accountId
}: {
profileId: string;
accountId: string;
}) => Promise<TAcmeResponse<TListAcmeOrdersResponse>>;
getAcmeAuthorization: ({ getAcmeAuthorization: ({
profileId, profileId,
accountId, accountId,