mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-09 19:28:33 +00:00
Refactor code
This commit is contained in:
@@ -12,7 +12,9 @@ export const PkiAcmeOrdersSchema = z.object({
|
|||||||
accountId: z.string().uuid(),
|
accountId: z.string().uuid(),
|
||||||
status: z.string(),
|
status: z.string(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date()
|
updatedAt: z.date(),
|
||||||
|
notBefore: z.date().nullable().optional(),
|
||||||
|
notAfter: z.date().nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TPkiAcmeOrders = z.infer<typeof PkiAcmeOrdersSchema>;
|
export type TPkiAcmeOrders = z.infer<typeof PkiAcmeOrdersSchema>;
|
||||||
|
|||||||
@@ -4,16 +4,14 @@ import { FastifyReply } from "fastify";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
AcmeOrderResourceSchema,
|
||||||
CreateAcmeAccountResponseSchema,
|
CreateAcmeAccountResponseSchema,
|
||||||
CreateAcmeOrderBodySchema,
|
CreateAcmeOrderBodySchema,
|
||||||
CreateAcmeOrderResponseSchema,
|
|
||||||
DeactivateAcmeAccountBodySchema,
|
DeactivateAcmeAccountBodySchema,
|
||||||
DeactivateAcmeAccountResponseSchema,
|
DeactivateAcmeAccountResponseSchema,
|
||||||
FinalizeAcmeOrderBodySchema,
|
FinalizeAcmeOrderBodySchema,
|
||||||
FinalizeAcmeOrderResponseSchema,
|
|
||||||
GetAcmeAuthorizationResponseSchema,
|
GetAcmeAuthorizationResponseSchema,
|
||||||
GetAcmeDirectoryResponseSchema,
|
GetAcmeDirectoryResponseSchema,
|
||||||
GetAcmeOrderResponseSchema,
|
|
||||||
ListAcmeOrdersPayloadSchema,
|
ListAcmeOrdersPayloadSchema,
|
||||||
ListAcmeOrdersResponseSchema,
|
ListAcmeOrdersResponseSchema,
|
||||||
RawJwsPayloadSchema,
|
RawJwsPayloadSchema,
|
||||||
@@ -138,46 +136,6 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// POST /api/v1/pki/acme/profiles/<profile_id>/new-order
|
|
||||||
// New Certificate Order (RFC 8555 Section 7.4)
|
|
||||||
server.route({
|
|
||||||
method: "POST",
|
|
||||||
url: "/profiles/:profileId/new-order",
|
|
||||||
config: {
|
|
||||||
rateLimit: writeLimit
|
|
||||||
},
|
|
||||||
schema: {
|
|
||||||
hide: false,
|
|
||||||
tags: [ApiDocsTags.PkiAcme],
|
|
||||||
description: "ACME New Order - apply for a new certificate",
|
|
||||||
params: z.object({
|
|
||||||
profileId: z.string().uuid()
|
|
||||||
}),
|
|
||||||
body: RawJwsPayloadSchema,
|
|
||||||
response: {
|
|
||||||
201: CreateAcmeOrderResponseSchema
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// TODO: replace with verify ACME signature here instead
|
|
||||||
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
|
||||||
handler: async (req, res) => {
|
|
||||||
const { profileId, accountId, payload } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
|
||||||
profileId: req.params.profileId,
|
|
||||||
rawJwsPayload: req.body,
|
|
||||||
schema: CreateAcmeOrderBodySchema
|
|
||||||
});
|
|
||||||
return sendAcmeResponse(
|
|
||||||
res,
|
|
||||||
profileId,
|
|
||||||
await server.services.pkiAcme.createAcmeOrder({
|
|
||||||
profileId,
|
|
||||||
accountId,
|
|
||||||
payload
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// POST /api/v1/pki/acme/profiles/<profile_id>/accounts/<account_id>
|
// POST /api/v1/pki/acme/profiles/<profile_id>/accounts/<account_id>
|
||||||
// Account Deactivation (RFC 8555 Section 7.3.6)
|
// Account Deactivation (RFC 8555 Section 7.3.6)
|
||||||
server.route({
|
server.route({
|
||||||
@@ -220,42 +178,41 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// POST /api/v1/pki/acme/profiles/<profile_id>/accounts/<account_id>/orders
|
// POST /api/v1/pki/acme/profiles/<profile_id>/new-order
|
||||||
// List Orders (RFC 8555 Section 7.1.2.1)
|
// New Certificate Order (RFC 8555 Section 7.4)
|
||||||
server.route({
|
server.route({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: "/profiles/:profileId/accounts/:accountId/orders",
|
url: "/profiles/:profileId/new-order",
|
||||||
config: {
|
config: {
|
||||||
rateLimit: readLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
hide: false,
|
hide: false,
|
||||||
tags: [ApiDocsTags.PkiAcme],
|
tags: [ApiDocsTags.PkiAcme],
|
||||||
description: "ACME List Orders - get existing orders from current account",
|
description: "ACME New Order - apply for a new certificate",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
profileId: z.string().uuid(),
|
profileId: z.string().uuid()
|
||||||
accountId: z.string()
|
|
||||||
}),
|
}),
|
||||||
body: RawJwsPayloadSchema,
|
body: RawJwsPayloadSchema,
|
||||||
response: {
|
response: {
|
||||||
200: ListAcmeOrdersResponseSchema
|
201: AcmeOrderResourceSchema
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// TODO: replace with verify ACME signature here instead
|
// TODO: replace with verify ACME signature here instead
|
||||||
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const { profileId, accountId } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
const { profileId, accountId, payload } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
||||||
profileId: req.params.profileId,
|
profileId: req.params.profileId,
|
||||||
rawJwsPayload: req.body,
|
rawJwsPayload: req.body,
|
||||||
schema: ListAcmeOrdersPayloadSchema,
|
schema: CreateAcmeOrderBodySchema
|
||||||
expectedAccountId: req.params.accountId
|
|
||||||
});
|
});
|
||||||
return sendAcmeResponse(
|
return sendAcmeResponse(
|
||||||
res,
|
res,
|
||||||
profileId,
|
profileId,
|
||||||
await server.services.pkiAcme.listAcmeOrders({
|
await server.services.pkiAcme.createAcmeOrder({
|
||||||
profileId,
|
profileId,
|
||||||
accountId
|
accountId,
|
||||||
|
payload
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -279,7 +236,7 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
body: RawJwsPayloadSchema,
|
body: RawJwsPayloadSchema,
|
||||||
response: {
|
response: {
|
||||||
200: GetAcmeOrderResponseSchema
|
200: AcmeOrderResourceSchema
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// TODO: replace with verify ACME signature here instead
|
// TODO: replace with verify ACME signature here instead
|
||||||
@@ -319,16 +276,16 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
body: RawJwsPayloadSchema,
|
body: RawJwsPayloadSchema,
|
||||||
response: {
|
response: {
|
||||||
200: FinalizeAcmeOrderResponseSchema
|
200: AcmeOrderResourceSchema
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// TODO: replace with verify ACME signature here instead
|
// TODO: replace with verify ACME signature here instead
|
||||||
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const { profileId, accountId, payload } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
const { profileId, accountId, payload } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
||||||
profileId: req.params.profileId,
|
profileId: req.params.profileId,
|
||||||
rawJwsPayload: req.body
|
rawJwsPayload: req.body,
|
||||||
schema: FinalizeAcmeOrderBodySchema,
|
schema: FinalizeAcmeOrderBodySchema
|
||||||
});
|
});
|
||||||
return sendAcmeResponse(
|
return sendAcmeResponse(
|
||||||
res,
|
res,
|
||||||
@@ -342,6 +299,46 @@ export const registerPkiAcmeRouter = async (server: FastifyZodProvider) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// POST /api/v1/pki/acme/profiles/<profile_id>/accounts/<account_id>/orders
|
||||||
|
// List Orders (RFC 8555 Section 7.1.2.1)
|
||||||
|
server.route({
|
||||||
|
method: "POST",
|
||||||
|
url: "/profiles/:profileId/accounts/:accountId/orders",
|
||||||
|
config: {
|
||||||
|
rateLimit: readLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiAcme],
|
||||||
|
description: "ACME List Orders - get existing orders from current account",
|
||||||
|
params: z.object({
|
||||||
|
profileId: z.string().uuid(),
|
||||||
|
accountId: z.string()
|
||||||
|
}),
|
||||||
|
body: RawJwsPayloadSchema,
|
||||||
|
response: {
|
||||||
|
200: ListAcmeOrdersResponseSchema
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// TODO: replace with verify ACME signature here instead
|
||||||
|
// onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
|
handler: async (req, res) => {
|
||||||
|
const { profileId, accountId } = await server.services.pkiAcme.validateExistingAccountJwsPayload({
|
||||||
|
profileId: req.params.profileId,
|
||||||
|
rawJwsPayload: req.body,
|
||||||
|
schema: ListAcmeOrdersPayloadSchema,
|
||||||
|
expectedAccountId: req.params.accountId
|
||||||
|
});
|
||||||
|
return sendAcmeResponse(
|
||||||
|
res,
|
||||||
|
profileId,
|
||||||
|
await server.services.pkiAcme.listAcmeOrders({
|
||||||
|
profileId,
|
||||||
|
accountId
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// POST /api/v1/pki/acme/profiles/<profile_id>/orders/<order_id>/certificate
|
// POST /api/v1/pki/acme/profiles/<profile_id>/orders/<order_id>/certificate
|
||||||
// Download Certificate (RFC 8555 Section 7.4.2)
|
// Download Certificate (RFC 8555 Section 7.4.2)
|
||||||
|
|||||||
@@ -90,9 +90,11 @@ export const CreateAcmeOrderBodySchema = z.object({
|
|||||||
notAfter: z.string().optional()
|
notAfter: z.string().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export const CreateAcmeOrderResponseSchema = z.object({
|
export const AcmeOrderResourceSchema = z.object({
|
||||||
status: z.string(),
|
status: z.enum(Object.values(AcmeOrderStatus) as [string, ...string[]]),
|
||||||
expires: z.string(),
|
expires: z.string().optional(),
|
||||||
|
notBefore: z.string().optional(),
|
||||||
|
notAfter: z.string().optional(),
|
||||||
identifiers: z.array(
|
identifiers: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
type: z.string(),
|
type: z.string(),
|
||||||
@@ -120,39 +122,11 @@ export const ListAcmeOrdersResponseSchema = z.object({
|
|||||||
orders: z.array(z.string())
|
orders: z.array(z.string())
|
||||||
});
|
});
|
||||||
|
|
||||||
export const GetAcmeOrderResponseSchema = z.object({
|
|
||||||
status: z.enum(Object.values(AcmeOrderStatus) as [string, ...string[]]),
|
|
||||||
expires: z.string().optional(),
|
|
||||||
identifiers: z.array(
|
|
||||||
z.object({
|
|
||||||
type: z.string(),
|
|
||||||
value: z.string()
|
|
||||||
})
|
|
||||||
),
|
|
||||||
authorizations: z.array(z.string()),
|
|
||||||
finalize: z.string(),
|
|
||||||
certificate: z.string().optional()
|
|
||||||
});
|
|
||||||
|
|
||||||
// Finalize Order payload schema
|
// Finalize Order payload schema
|
||||||
export const FinalizeAcmeOrderBodySchema = z.object({
|
export const FinalizeAcmeOrderBodySchema = z.object({
|
||||||
csr: z.string()
|
csr: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
export const FinalizeAcmeOrderResponseSchema = z.object({
|
|
||||||
status: z.enum(Object.values(AcmeOrderStatus) as [string, ...string[]]),
|
|
||||||
expires: z.string().optional(),
|
|
||||||
identifiers: z.array(
|
|
||||||
z.object({
|
|
||||||
type: z.string(),
|
|
||||||
value: z.string()
|
|
||||||
})
|
|
||||||
),
|
|
||||||
authorizations: z.array(z.string()),
|
|
||||||
finalize: z.string(),
|
|
||||||
certificate: z.string().optional()
|
|
||||||
});
|
|
||||||
|
|
||||||
export const GetAcmeAuthorizationResponseSchema = z.object({
|
export const GetAcmeAuthorizationResponseSchema = z.object({
|
||||||
status: z.enum(Object.values(AcmeAuthStatus) as [string, ...string[]]),
|
status: z.enum(Object.values(AcmeAuthStatus) as [string, ...string[]]),
|
||||||
expires: z.string().optional(),
|
expires: z.string().optional(),
|
||||||
|
|||||||
@@ -37,16 +37,14 @@ import {
|
|||||||
TCreateAcmeAccountPayload,
|
TCreateAcmeAccountPayload,
|
||||||
TCreateAcmeAccountResponse,
|
TCreateAcmeAccountResponse,
|
||||||
TCreateAcmeOrderPayload,
|
TCreateAcmeOrderPayload,
|
||||||
TCreateAcmeOrderResponse,
|
|
||||||
TDeactivateAcmeAccountPayload,
|
TDeactivateAcmeAccountPayload,
|
||||||
TDeactivateAcmeAccountResponse,
|
TDeactivateAcmeAccountResponse,
|
||||||
TFinalizeAcmeOrderPayload,
|
TFinalizeAcmeOrderPayload,
|
||||||
TFinalizeAcmeOrderResponse,
|
|
||||||
TGetAcmeAuthorizationResponse,
|
TGetAcmeAuthorizationResponse,
|
||||||
TGetAcmeDirectoryResponse,
|
TGetAcmeDirectoryResponse,
|
||||||
TGetAcmeOrderResponse,
|
|
||||||
TJwsPayload,
|
TJwsPayload,
|
||||||
TListAcmeOrdersResponse,
|
TListAcmeOrdersResponse,
|
||||||
|
TAcmeOrderResource,
|
||||||
TPkiAcmeServiceFactory,
|
TPkiAcmeServiceFactory,
|
||||||
TRawJwsPayload,
|
TRawJwsPayload,
|
||||||
TRespondToAcmeChallengeResponse
|
TRespondToAcmeChallengeResponse
|
||||||
@@ -206,6 +204,36 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const buildAcmeOrderResource = ({
|
||||||
|
profileId,
|
||||||
|
order
|
||||||
|
}: {
|
||||||
|
order: {
|
||||||
|
id: string;
|
||||||
|
status: string;
|
||||||
|
expiresAt: Date;
|
||||||
|
notBefore?: Date | null;
|
||||||
|
notAfter?: Date | null;
|
||||||
|
authorizations: TPkiAcmeAuths[];
|
||||||
|
};
|
||||||
|
profileId: string;
|
||||||
|
}) => {
|
||||||
|
return {
|
||||||
|
status: order.status,
|
||||||
|
expires: order.expiresAt.toISOString(),
|
||||||
|
notBefore: order.notBefore?.toISOString(),
|
||||||
|
notAfter: order.notAfter?.toISOString(),
|
||||||
|
identifiers: order.authorizations.map((auth: TPkiAcmeAuths) => ({
|
||||||
|
type: auth.identifierType,
|
||||||
|
value: auth.identifierValue
|
||||||
|
})),
|
||||||
|
authorizations: order.authorizations.map((auth: TPkiAcmeAuths) =>
|
||||||
|
buildUrl(`/api/v1/pki/acme/profiles/${profileId}/authorizations/${auth.id}`)
|
||||||
|
),
|
||||||
|
finalize: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${order.id}/finalize`)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const getAcmeNewNonce = async (profileId: string): Promise<string> => {
|
const getAcmeNewNonce = async (profileId: string): Promise<string> => {
|
||||||
const profile = await validateAcmeProfile(profileId);
|
const profile = await validateAcmeProfile(profileId);
|
||||||
// FIXME: Implement ACME new nonce generation
|
// FIXME: Implement ACME new nonce generation
|
||||||
@@ -213,6 +241,9 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
return "FIXME-generate-nonce";
|
return "FIXME-generate-nonce";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** --------------------------------------------------------------
|
||||||
|
* ACME Account
|
||||||
|
* -------------------------------------------------------------- */
|
||||||
const createAcmeAccount = async ({
|
const createAcmeAccount = async ({
|
||||||
profileId,
|
profileId,
|
||||||
alg,
|
alg,
|
||||||
@@ -251,6 +282,7 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
publicKey: jwk,
|
publicKey: jwk,
|
||||||
emails: contact ?? []
|
emails: contact ?? []
|
||||||
});
|
});
|
||||||
|
// TODO: create audit log here
|
||||||
// TODO: check EAB authentication here
|
// TODO: check EAB authentication here
|
||||||
return {
|
return {
|
||||||
status: 201,
|
status: 201,
|
||||||
@@ -265,6 +297,31 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const deactivateAcmeAccount = async ({
|
||||||
|
profileId,
|
||||||
|
accountId,
|
||||||
|
payload: { status } = { status: "deactivated" }
|
||||||
|
}: {
|
||||||
|
profileId: string;
|
||||||
|
accountId: string;
|
||||||
|
payload?: TDeactivateAcmeAccountPayload;
|
||||||
|
}): Promise<TAcmeResponse<TDeactivateAcmeAccountResponse>> => {
|
||||||
|
const profile = await validateAcmeProfile(profileId);
|
||||||
|
// FIXME: Implement ACME account deactivation
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: {
|
||||||
|
status: "deactivated"
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
Location: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/accounts/${accountId}`)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** --------------------------------------------------------------
|
||||||
|
* ACME Order
|
||||||
|
* -------------------------------------------------------------- */
|
||||||
const createAcmeOrder = async ({
|
const createAcmeOrder = async ({
|
||||||
profileId,
|
profileId,
|
||||||
accountId,
|
accountId,
|
||||||
@@ -273,7 +330,7 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
profileId: string;
|
profileId: string;
|
||||||
accountId: string;
|
accountId: string;
|
||||||
payload: TCreateAcmeOrderPayload;
|
payload: TCreateAcmeOrderPayload;
|
||||||
}): Promise<TAcmeResponse<TCreateAcmeOrderResponse>> => {
|
}): Promise<TAcmeResponse<TAcmeOrderResource>> => {
|
||||||
// TODO: check and see if we have existing orders for this account that meet the criteria
|
// TODO: check and see if we have existing orders for this account that meet the criteria
|
||||||
// if we do, return the existing order
|
// if we do, return the existing order
|
||||||
|
|
||||||
@@ -314,47 +371,68 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
})),
|
})),
|
||||||
tx
|
tx
|
||||||
);
|
);
|
||||||
|
// TODO: create audit log here
|
||||||
return { ...createdOrder, authorizations, account };
|
return { ...createdOrder, authorizations, account };
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: 201,
|
status: 201,
|
||||||
body: {
|
body: buildAcmeOrderResource({
|
||||||
status: order.status,
|
profileId,
|
||||||
expires: order.expiresAt.toISOString(),
|
order
|
||||||
identifiers: order.authorizations.map((auth: TPkiAcmeAuths) => ({
|
}),
|
||||||
type: auth.identifierType,
|
|
||||||
value: auth.identifierValue
|
|
||||||
})),
|
|
||||||
authorizations: order.authorizations.map((auth: TPkiAcmeAuths) =>
|
|
||||||
buildUrl(`/api/v1/pki/acme/profiles/${order.account.profileId}/authorizations/${auth.id}`)
|
|
||||||
),
|
|
||||||
finalize: buildUrl(`/api/v1/pki/acme/profiles/${order.account.profileId}/orders/${order.id}/finalize`)
|
|
||||||
},
|
|
||||||
headers: {
|
headers: {
|
||||||
Location: buildUrl(`/api/v1/pki/acme/profiles/${order.account.profileId}/orders/${order.id}`)
|
Location: buildUrl(`/api/v1/pki/acme/profiles/${order.account.profileId}/orders/${order.id}`)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const deactivateAcmeAccount = async ({
|
const getAcmeOrder = async ({
|
||||||
profileId,
|
profileId,
|
||||||
accountId,
|
accountId,
|
||||||
payload: { status } = { status: "deactivated" }
|
orderId
|
||||||
}: {
|
}: {
|
||||||
profileId: string;
|
profileId: string;
|
||||||
accountId: string;
|
accountId: string;
|
||||||
payload?: TDeactivateAcmeAccountPayload;
|
orderId: string;
|
||||||
}): Promise<TAcmeResponse<TDeactivateAcmeAccountResponse>> => {
|
}): Promise<TAcmeResponse<TAcmeOrderResource>> => {
|
||||||
|
const order = await acmeOrderDAL.findByIdWithAuthorizations(orderId);
|
||||||
|
if (!order || order.accountId !== accountId) {
|
||||||
|
throw new NotFoundError({ message: "ACME order not found" });
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: buildAcmeOrderResource({ profileId, order }),
|
||||||
|
headers: { Location: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}`) }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const finalizeAcmeOrder = async ({
|
||||||
|
profileId,
|
||||||
|
accountId,
|
||||||
|
orderId,
|
||||||
|
payload
|
||||||
|
}: {
|
||||||
|
profileId: string;
|
||||||
|
accountId: string;
|
||||||
|
orderId: string;
|
||||||
|
payload: TFinalizeAcmeOrderPayload;
|
||||||
|
}): Promise<TAcmeResponse<TAcmeOrderResource>> => {
|
||||||
const profile = await validateAcmeProfile(profileId);
|
const profile = await validateAcmeProfile(profileId);
|
||||||
// FIXME: Implement ACME account deactivation
|
const { csr } = payload;
|
||||||
|
// FIXME: Implement ACME finalize order
|
||||||
return {
|
return {
|
||||||
status: 200,
|
status: 200,
|
||||||
body: {
|
body: {
|
||||||
status: "deactivated"
|
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}/accounts/${accountId}`)
|
Location: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}`)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -379,67 +457,6 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAcmeOrder = async ({
|
|
||||||
profileId,
|
|
||||||
accountId,
|
|
||||||
orderId
|
|
||||||
}: {
|
|
||||||
profileId: string;
|
|
||||||
accountId: string;
|
|
||||||
orderId: string;
|
|
||||||
}): Promise<TAcmeResponse<TGetAcmeOrderResponse>> => {
|
|
||||||
const order = await acmeOrderDAL.findByIdWithAuthorizations(orderId);
|
|
||||||
if (!order || order.accountId !== accountId) {
|
|
||||||
throw new NotFoundError({ message: "ACME order not found" });
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
status: 200,
|
|
||||||
body: {
|
|
||||||
status: order.status,
|
|
||||||
expires: order.expiresAt.toISOString(),
|
|
||||||
identifiers: order.authorizations.map((auth: TPkiAcmeAuths) => ({
|
|
||||||
type: auth.identifierType,
|
|
||||||
value: auth.identifierValue
|
|
||||||
})),
|
|
||||||
authorizations: order.authorizations.map((auth: TPkiAcmeAuths) =>
|
|
||||||
buildUrl(`/api/v1/pki/acme/profiles/${profileId}/authorizations/${auth.id}`)
|
|
||||||
),
|
|
||||||
finalize: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/finalize`)
|
|
||||||
},
|
|
||||||
headers: { Location: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}`) }
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const finalizeAcmeOrder = async ({
|
|
||||||
profileId,
|
|
||||||
accountId,
|
|
||||||
orderId,
|
|
||||||
payload
|
|
||||||
}: {
|
|
||||||
profileId: string;
|
|
||||||
accountId: string;
|
|
||||||
orderId: string;
|
|
||||||
payload: TFinalizeAcmeOrderPayload;
|
|
||||||
}): Promise<TAcmeResponse<TFinalizeAcmeOrderResponse>> => {
|
|
||||||
const profile = await validateAcmeProfile(profileId);
|
|
||||||
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`)
|
|
||||||
},
|
|
||||||
headers: {
|
|
||||||
Location: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}`)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const downloadAcmeCertificate = async ({
|
const downloadAcmeCertificate = async ({
|
||||||
profileId,
|
profileId,
|
||||||
orderId
|
orderId
|
||||||
@@ -459,6 +476,9 @@ export const pkiAcmeServiceFactory = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** --------------------------------------------------------------
|
||||||
|
* ACME Authorization
|
||||||
|
* -------------------------------------------------------------- */
|
||||||
const getAcmeAuthorization = async ({
|
const getAcmeAuthorization = async ({
|
||||||
profileId,
|
profileId,
|
||||||
accountId,
|
accountId,
|
||||||
|
|||||||
@@ -2,17 +2,15 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { JWSHeaderParameters } from "jose";
|
import { JWSHeaderParameters } from "jose";
|
||||||
import {
|
import {
|
||||||
|
AcmeOrderResourceSchema,
|
||||||
CreateAcmeAccountBodySchema,
|
CreateAcmeAccountBodySchema,
|
||||||
CreateAcmeAccountResponseSchema,
|
CreateAcmeAccountResponseSchema,
|
||||||
CreateAcmeOrderBodySchema,
|
CreateAcmeOrderBodySchema,
|
||||||
CreateAcmeOrderResponseSchema,
|
|
||||||
DeactivateAcmeAccountBodySchema,
|
DeactivateAcmeAccountBodySchema,
|
||||||
DeactivateAcmeAccountResponseSchema,
|
DeactivateAcmeAccountResponseSchema,
|
||||||
FinalizeAcmeOrderBodySchema,
|
FinalizeAcmeOrderBodySchema,
|
||||||
FinalizeAcmeOrderResponseSchema,
|
|
||||||
GetAcmeAuthorizationResponseSchema,
|
GetAcmeAuthorizationResponseSchema,
|
||||||
GetAcmeDirectoryResponseSchema,
|
GetAcmeDirectoryResponseSchema,
|
||||||
GetAcmeOrderResponseSchema,
|
|
||||||
ListAcmeOrdersResponseSchema,
|
ListAcmeOrdersResponseSchema,
|
||||||
ProtectedHeaderSchema,
|
ProtectedHeaderSchema,
|
||||||
RawJwsPayloadSchema,
|
RawJwsPayloadSchema,
|
||||||
@@ -21,11 +19,9 @@ import {
|
|||||||
|
|
||||||
export type TGetAcmeDirectoryResponse = z.infer<typeof GetAcmeDirectoryResponseSchema>;
|
export type TGetAcmeDirectoryResponse = z.infer<typeof GetAcmeDirectoryResponseSchema>;
|
||||||
export type TCreateAcmeAccountResponse = z.infer<typeof CreateAcmeAccountResponseSchema>;
|
export type TCreateAcmeAccountResponse = z.infer<typeof CreateAcmeAccountResponseSchema>;
|
||||||
export type TCreateAcmeOrderResponse = z.infer<typeof CreateAcmeOrderResponseSchema>;
|
export type TAcmeOrderResource = z.infer<typeof AcmeOrderResourceSchema>;
|
||||||
export type TDeactivateAcmeAccountResponse = z.infer<typeof DeactivateAcmeAccountResponseSchema>;
|
export type TDeactivateAcmeAccountResponse = z.infer<typeof DeactivateAcmeAccountResponseSchema>;
|
||||||
export type TListAcmeOrdersResponse = z.infer<typeof ListAcmeOrdersResponseSchema>;
|
export type TListAcmeOrdersResponse = z.infer<typeof ListAcmeOrdersResponseSchema>;
|
||||||
export type TGetAcmeOrderResponse = z.infer<typeof GetAcmeOrderResponseSchema>;
|
|
||||||
export type TFinalizeAcmeOrderResponse = z.infer<typeof FinalizeAcmeOrderResponseSchema>;
|
|
||||||
export type TDownloadAcmeCertificateDTO = string;
|
export type TDownloadAcmeCertificateDTO = string;
|
||||||
export type TGetAcmeAuthorizationResponse = z.infer<typeof GetAcmeAuthorizationResponseSchema>;
|
export type TGetAcmeAuthorizationResponse = z.infer<typeof GetAcmeAuthorizationResponseSchema>;
|
||||||
export type TRespondToAcmeChallengeResponse = z.infer<typeof RespondToAcmeChallengeResponseSchema>;
|
export type TRespondToAcmeChallengeResponse = z.infer<typeof RespondToAcmeChallengeResponseSchema>;
|
||||||
@@ -89,15 +85,6 @@ export type TPkiAcmeServiceFactory = {
|
|||||||
jwk: JsonWebKey;
|
jwk: JsonWebKey;
|
||||||
payload: TCreateAcmeAccountPayload;
|
payload: TCreateAcmeAccountPayload;
|
||||||
}) => Promise<TAcmeResponse<TCreateAcmeAccountResponse>>;
|
}) => Promise<TAcmeResponse<TCreateAcmeAccountResponse>>;
|
||||||
createAcmeOrder: ({
|
|
||||||
profileId,
|
|
||||||
accountId,
|
|
||||||
payload
|
|
||||||
}: {
|
|
||||||
profileId: string;
|
|
||||||
accountId: string;
|
|
||||||
payload: TCreateAcmeOrderPayload;
|
|
||||||
}) => Promise<TAcmeResponse<TCreateAcmeOrderResponse>>;
|
|
||||||
deactivateAcmeAccount: ({
|
deactivateAcmeAccount: ({
|
||||||
profileId,
|
profileId,
|
||||||
accountId,
|
accountId,
|
||||||
@@ -107,13 +94,15 @@ export type TPkiAcmeServiceFactory = {
|
|||||||
accountId: string;
|
accountId: string;
|
||||||
payload?: TDeactivateAcmeAccountPayload;
|
payload?: TDeactivateAcmeAccountPayload;
|
||||||
}) => Promise<TAcmeResponse<TDeactivateAcmeAccountResponse>>;
|
}) => Promise<TAcmeResponse<TDeactivateAcmeAccountResponse>>;
|
||||||
listAcmeOrders: ({
|
createAcmeOrder: ({
|
||||||
profileId,
|
profileId,
|
||||||
accountId
|
accountId,
|
||||||
|
payload
|
||||||
}: {
|
}: {
|
||||||
profileId: string;
|
profileId: string;
|
||||||
accountId: string;
|
accountId: string;
|
||||||
}) => Promise<TAcmeResponse<TListAcmeOrdersResponse>>;
|
payload: TCreateAcmeOrderPayload;
|
||||||
|
}) => Promise<TAcmeResponse<TAcmeOrderResource>>;
|
||||||
getAcmeOrder: ({
|
getAcmeOrder: ({
|
||||||
profileId,
|
profileId,
|
||||||
accountId,
|
accountId,
|
||||||
@@ -122,7 +111,7 @@ export type TPkiAcmeServiceFactory = {
|
|||||||
profileId: string;
|
profileId: string;
|
||||||
accountId: string;
|
accountId: string;
|
||||||
orderId: string;
|
orderId: string;
|
||||||
}) => Promise<TAcmeResponse<TGetAcmeOrderResponse>>;
|
}) => Promise<TAcmeResponse<TAcmeOrderResource>>;
|
||||||
finalizeAcmeOrder: ({
|
finalizeAcmeOrder: ({
|
||||||
profileId,
|
profileId,
|
||||||
accountId,
|
accountId,
|
||||||
@@ -133,12 +122,21 @@ export type TPkiAcmeServiceFactory = {
|
|||||||
accountId: string;
|
accountId: string;
|
||||||
orderId: string;
|
orderId: string;
|
||||||
payload: TFinalizeAcmeOrderPayload;
|
payload: TFinalizeAcmeOrderPayload;
|
||||||
}) => Promise<TAcmeResponse<TFinalizeAcmeOrderResponse>>;
|
}) => Promise<TAcmeResponse<TAcmeOrderResource>>;
|
||||||
|
listAcmeOrders: ({
|
||||||
|
profileId,
|
||||||
|
accountId
|
||||||
|
}: {
|
||||||
|
profileId: string;
|
||||||
|
accountId: string;
|
||||||
|
}) => Promise<TAcmeResponse<TListAcmeOrdersResponse>>;
|
||||||
downloadAcmeCertificate: ({
|
downloadAcmeCertificate: ({
|
||||||
profileId,
|
profileId,
|
||||||
|
accountId,
|
||||||
orderId
|
orderId
|
||||||
}: {
|
}: {
|
||||||
profileId: string;
|
profileId: string;
|
||||||
|
accountId: string;
|
||||||
orderId: string;
|
orderId: string;
|
||||||
}) => Promise<TAcmeResponse<string>>;
|
}) => Promise<TAcmeResponse<string>>;
|
||||||
getAcmeAuthorization: ({
|
getAcmeAuthorization: ({
|
||||||
|
|||||||
Reference in New Issue
Block a user