Extract common stuff

This commit is contained in:
Fang-Pen Lin
2025-11-07 09:18:04 -08:00
parent 806e11a5b2
commit a37f8445ad
@@ -3,6 +3,10 @@ import { NotFoundError } from "@app/lib/errors";
import { TCertificateProfileDALFactory } from "@app/services/certificate-profile/certificate-profile-dal"; import { TCertificateProfileDALFactory } from "@app/services/certificate-profile/certificate-profile-dal";
import {
EnrollmentType,
TCertificateProfileWithConfigs
} from "@app/services/certificate-profile/certificate-profile-types";
import { import {
TCreateAcmeAccountPayload, TCreateAcmeAccountPayload,
TCreateAcmeAccountResponse, TCreateAcmeAccountResponse,
@@ -10,7 +14,6 @@ import {
TCreateAcmeOrderResponse, TCreateAcmeOrderResponse,
TDeactivateAcmeAccountPayload, TDeactivateAcmeAccountPayload,
TDeactivateAcmeAccountResponse, TDeactivateAcmeAccountResponse,
TDownloadAcmeCertificateDTO,
TFinalizeAcmeOrderPayload, TFinalizeAcmeOrderPayload,
TFinalizeAcmeOrderResponse, TFinalizeAcmeOrderResponse,
TGetAcmeAuthorizationResponse, TGetAcmeAuthorizationResponse,
@@ -28,26 +31,39 @@ type TPkiAcmeServiceFactoryDep = {
export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeServiceFactoryDep): TPkiAcmeServiceFactory => { export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeServiceFactoryDep): TPkiAcmeServiceFactory => {
const appCfg = getConfig(); const appCfg = getConfig();
const validateAcmeProfile = async (profileId: string): Promise<TCertificateProfileWithConfigs> => {
const profile = await certificateProfileDAL.findById(profileId);
if (!profile) {
throw new NotFoundError({ message: "Certificate profile not found" });
}
if (profile.enrollmentType !== EnrollmentType.ACME) {
throw new NotFoundError({ message: "Certificate profile is not configured for ACME enrollment" });
}
return profile;
};
const buildUrl = (path: string): string => {
const baseUrl = appCfg.SITE_URL ?? "";
return `${baseUrl}${path}`;
};
const getAcmeDirectory = async (profileId: string): Promise<TGetAcmeDirectoryResponse> => { const getAcmeDirectory = async (profileId: string): Promise<TGetAcmeDirectoryResponse> => {
// FIXME: Implement ACME directory endpoint // FIXME: Implement ACME directory endpoint
// Validate profile exists and is for ACME enrollment // Validate profile exists and is for ACME enrollment
// const profile = await certificateProfileDAL.findById(profileId); const profile = await validateAcmeProfile(profileId);
// if (!profile) {
// throw new NotFoundError({ message: "Certificate profile not found" });
// }
// FIXME: Validate profile is configured for ACME enrollment // FIXME: Validate profile is configured for ACME enrollment
// Return absolute URLs using SITE_URL // Return absolute URLs using SITE_URL
const baseUrl = appCfg.SITE_URL ?? "";
return { return {
newNonce: `${baseUrl}/api/v1/pki/acme/profiles/${profileId}/new-nonce`, newNonce: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/new-nonce`),
newAccount: `${baseUrl}/api/v1/pki/acme/profiles/${profileId}/new-account`, newAccount: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/new-account`),
newOrder: `${baseUrl}/api/v1/pki/acme/profiles/${profileId}/new-order` newOrder: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/new-order`)
}; };
}; };
const getAcmeNewNonce = async (profileId: string): Promise<string> => { const getAcmeNewNonce = async (profileId: string): Promise<string> => {
const profile = await validateAcmeProfile(profileId);
// FIXME: Implement ACME new nonce generation // FIXME: Implement ACME new nonce generation
// Generate a new nonce, store it, and return it // Generate a new nonce, store it, and return it
return "FIXME-generate-nonce"; return "FIXME-generate-nonce";
@@ -57,16 +73,16 @@ export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeService
profileId: string, profileId: string,
body: TCreateAcmeAccountPayload body: TCreateAcmeAccountPayload
): Promise<TCreateAcmeAccountResponse> => { ): Promise<TCreateAcmeAccountResponse> => {
const profile = await validateAcmeProfile(profileId);
// FIXME: Implement ACME new account registration // FIXME: Implement ACME new account registration
// Use EAB authentication to find corresponding Infisical machine identity // Use EAB authentication to find corresponding Infisical machine identity
// Check permissions and return account information // Check permissions and return account information
const baseUrl = appCfg.SITE_URL || "";
const accountId = "FIXME-account-id"; const accountId = "FIXME-account-id";
return { return {
status: "valid", status: "valid",
accountUrl: `${baseUrl}/api/v1/pki/acme/profiles/${profileId}/accounts/${accountId}`, accountUrl: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/accounts/${accountId}`),
contact: [], contact: [],
orders: `${baseUrl}/api/v1/pki/acme/profiles/${profileId}/accounts/${accountId}/orders` orders: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/accounts/${accountId}/orders`)
}; };
}; };
@@ -74,15 +90,15 @@ export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeService
profileId: string, profileId: string,
body: TCreateAcmeOrderPayload body: TCreateAcmeOrderPayload
): Promise<TCreateAcmeOrderResponse> => { ): Promise<TCreateAcmeOrderResponse> => {
const profile = await validateAcmeProfile(profileId);
// FIXME: Implement ACME new order creation // FIXME: Implement ACME new order creation
const orderId = "FIXME-order-id"; const orderId = "FIXME-order-id";
const baseUrl = appCfg.SITE_URL || "";
return { return {
status: "pending", status: "pending",
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(), expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
identifiers: [], identifiers: [],
authorizations: [], authorizations: [],
finalize: `${baseUrl}/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/finalize` finalize: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/finalize`)
}; };
}; };
@@ -91,6 +107,7 @@ export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeService
accountId: string, accountId: string,
body?: TDeactivateAcmeAccountPayload body?: TDeactivateAcmeAccountPayload
): Promise<TDeactivateAcmeAccountResponse> => { ): Promise<TDeactivateAcmeAccountResponse> => {
const profile = await validateAcmeProfile(profileId);
// FIXME: Implement ACME account deactivation // FIXME: Implement ACME account deactivation
return { return {
status: "deactivated" status: "deactivated"
@@ -98,6 +115,7 @@ export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeService
}; };
const listAcmeOrders = async (profileId: string, accountId: string): Promise<TListAcmeOrdersResponse> => { const listAcmeOrders = async (profileId: string, accountId: string): Promise<TListAcmeOrdersResponse> => {
const profile = await validateAcmeProfile(profileId);
// FIXME: Implement ACME list orders // FIXME: Implement ACME list orders
return { return {
orders: [] orders: []
@@ -105,14 +123,14 @@ export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeService
}; };
const getAcmeOrder = async (profileId: string, orderId: string): Promise<TGetAcmeOrderResponse> => { const getAcmeOrder = async (profileId: string, orderId: string): Promise<TGetAcmeOrderResponse> => {
const profile = await validateAcmeProfile(profileId);
// FIXME: Implement ACME get order // FIXME: Implement ACME get order
const baseUrl = appCfg.SITE_URL || "";
return { return {
status: "pending", status: "pending",
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(), expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
identifiers: [], identifiers: [],
authorizations: [], authorizations: [],
finalize: `${baseUrl}/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/finalize` finalize: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/finalize`)
}; };
}; };
@@ -121,28 +139,29 @@ export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeService
orderId: string, orderId: string,
body: TFinalizeAcmeOrderPayload body: TFinalizeAcmeOrderPayload
): Promise<TFinalizeAcmeOrderResponse> => { ): Promise<TFinalizeAcmeOrderResponse> => {
const profile = await validateAcmeProfile(profileId);
const { csr } = body; const { csr } = body;
// FIXME: Implement ACME finalize order // FIXME: Implement ACME finalize order
const baseUrl = appCfg.SITE_URL || "";
return { return {
status: "processing", status: "processing",
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(), expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
identifiers: [], identifiers: [],
authorizations: [], authorizations: [],
finalize: `${baseUrl}/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/finalize`, finalize: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/finalize`),
certificate: `${baseUrl}/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/certificate` certificate: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/certificate`)
}; };
}; };
const downloadAcmeCertificate = async (profileId: string, orderId: string): Promise<string> => { const downloadAcmeCertificate = async (profileId: string, orderId: string): Promise<string> => {
const profile = await validateAcmeProfile(profileId);
// FIXME: Implement ACME certificate download // FIXME: Implement ACME certificate download
// Return the certificate in PEM format // Return the certificate in PEM format
return "FIXME-certificate-pem"; return "FIXME-certificate-pem";
}; };
const getAcmeAuthorization = async (profileId: string, authzId: string): Promise<TGetAcmeAuthorizationResponse> => { const getAcmeAuthorization = async (profileId: string, authzId: string): Promise<TGetAcmeAuthorizationResponse> => {
const profile = await validateAcmeProfile(profileId);
// FIXME: Implement ACME authorization retrieval // FIXME: Implement ACME authorization retrieval
const baseUrl = appCfg.SITE_URL || "";
return { return {
status: "pending", status: "pending",
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(), expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
@@ -153,7 +172,7 @@ export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeService
challenges: [ challenges: [
{ {
type: "http-01", type: "http-01",
url: `${baseUrl}/api/v1/pki/acme/profiles/${profileId}/authorizations/${authzId}/challenges/http-01`, url: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/authorizations/${authzId}/challenges/http-01`),
status: "pending", status: "pending",
token: "FIXME-challenge-token" token: "FIXME-challenge-token"
} }
@@ -165,12 +184,12 @@ export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeService
profileId: string, profileId: string,
authzId: string authzId: string
): Promise<TRespondToAcmeChallengeResponse> => { ): Promise<TRespondToAcmeChallengeResponse> => {
const profile = await validateAcmeProfile(profileId);
// FIXME: Implement ACME challenge response // FIXME: Implement ACME challenge response
// Trigger verification process // Trigger verification process
const baseUrl = appCfg.SITE_URL || "";
return { return {
type: "http-01", type: "http-01",
url: `${baseUrl}/api/v1/pki/acme/profiles/${profileId}/authorizations/${authzId}/challenges/http-01`, url: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/authorizations/${authzId}/challenges/http-01`),
status: "pending", status: "pending",
token: "FIXME-challenge-token" token: "FIXME-challenge-token"
}; };