mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-20 00:37:35 +00:00
Extract things as service instead
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
import { z } from "zod";
|
||||
|
||||
// Directory endpoint
|
||||
export const GetAcmeDirectorySchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid()
|
||||
})
|
||||
});
|
||||
|
||||
export const GetAcmeDirectoryResponseSchema = z.object({
|
||||
newNonce: z.string(),
|
||||
newAccount: z.string(),
|
||||
newOrder: z.string(),
|
||||
revokeCert: z.string()
|
||||
});
|
||||
|
||||
// New Nonce endpoint
|
||||
export const GetAcmeNewNonceSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid()
|
||||
})
|
||||
});
|
||||
|
||||
// New Account endpoint
|
||||
export const CreateAcmeAccountSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid()
|
||||
}),
|
||||
body: z.object({
|
||||
contact: z.array(z.string()).optional(),
|
||||
termsOfServiceAgreed: z.boolean().optional(),
|
||||
onlyReturnExisting: z.boolean().optional(),
|
||||
externalAccountBinding: z
|
||||
.object({
|
||||
protected: z.string(),
|
||||
payload: z.string(),
|
||||
signature: z.string()
|
||||
})
|
||||
.optional()
|
||||
})
|
||||
});
|
||||
|
||||
export const CreateAcmeAccountResponseSchema = z.object({
|
||||
status: z.string(),
|
||||
contact: z.array(z.string()).optional(),
|
||||
orders: z.string().optional(),
|
||||
accountUrl: z.string()
|
||||
});
|
||||
|
||||
// New Order endpoint
|
||||
export const CreateAcmeOrderSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid()
|
||||
}),
|
||||
body: z.object({
|
||||
identifiers: z.array(
|
||||
z.object({
|
||||
type: z.string(),
|
||||
value: z.string()
|
||||
})
|
||||
),
|
||||
notBefore: z.string().optional(),
|
||||
notAfter: z.string().optional()
|
||||
})
|
||||
});
|
||||
|
||||
export const CreateAcmeOrderResponseSchema = z.object({
|
||||
status: z.string(),
|
||||
expires: z.string(),
|
||||
identifiers: z.array(
|
||||
z.object({
|
||||
type: z.string(),
|
||||
value: z.string()
|
||||
})
|
||||
),
|
||||
authorizations: z.array(z.string()),
|
||||
finalize: z.string(),
|
||||
certificate: z.string().optional()
|
||||
});
|
||||
|
||||
// Account Deactivation endpoint
|
||||
export const DeactivateAcmeAccountSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid(),
|
||||
accountId: z.string()
|
||||
}),
|
||||
body: z.object({
|
||||
status: z.literal("deactivated")
|
||||
})
|
||||
});
|
||||
|
||||
export const DeactivateAcmeAccountResponseSchema = z.object({
|
||||
status: z.string()
|
||||
});
|
||||
|
||||
// List Orders endpoint
|
||||
export const ListAcmeOrdersSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid(),
|
||||
accountId: z.string()
|
||||
})
|
||||
});
|
||||
|
||||
export const ListAcmeOrdersResponseSchema = z.object({
|
||||
orders: z.array(z.string())
|
||||
});
|
||||
|
||||
// Get Order endpoint
|
||||
export const GetAcmeOrderSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid(),
|
||||
orderId: z.string()
|
||||
})
|
||||
});
|
||||
|
||||
export const GetAcmeOrderResponseSchema = z.object({
|
||||
status: z.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 endpoint
|
||||
export const FinalizeAcmeOrderSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid(),
|
||||
orderId: z.string()
|
||||
}),
|
||||
body: z.object({
|
||||
csr: z.string()
|
||||
})
|
||||
});
|
||||
|
||||
export const FinalizeAcmeOrderResponseSchema = z.object({
|
||||
status: z.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()
|
||||
});
|
||||
|
||||
// Download Certificate endpoint
|
||||
export const DownloadAcmeCertificateSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid(),
|
||||
orderId: z.string()
|
||||
})
|
||||
});
|
||||
|
||||
// Get Authorization endpoint
|
||||
export const GetAcmeAuthorizationSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid(),
|
||||
authzId: z.string()
|
||||
})
|
||||
});
|
||||
|
||||
export const GetAcmeAuthorizationResponseSchema = z.object({
|
||||
status: z.string(),
|
||||
expires: z.string().optional(),
|
||||
identifier: z.object({
|
||||
type: z.string(),
|
||||
value: z.string()
|
||||
}),
|
||||
challenges: z.array(
|
||||
z.object({
|
||||
type: z.string(),
|
||||
url: z.string(),
|
||||
status: z.string(),
|
||||
token: z.string(),
|
||||
validated: z.string().optional()
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
// Respond to Challenge endpoint
|
||||
export const RespondToAcmeChallengeSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid(),
|
||||
authzId: z.string()
|
||||
})
|
||||
});
|
||||
|
||||
export const RespondToAcmeChallengeResponseSchema = z.object({
|
||||
type: z.string(),
|
||||
url: z.string(),
|
||||
status: z.string(),
|
||||
token: z.string(),
|
||||
validated: z.string().optional(),
|
||||
error: z
|
||||
.object({
|
||||
type: z.string(),
|
||||
detail: z.string(),
|
||||
status: z.number()
|
||||
})
|
||||
.optional()
|
||||
});
|
||||
@@ -0,0 +1,168 @@
|
||||
import { NotFoundError } from "@app/lib/errors";
|
||||
|
||||
import { TCertificateProfileDALFactory } from "@app/services/certificate-profile/certificate-profile-dal";
|
||||
|
||||
import {
|
||||
TCreateAcmeAccountResponse,
|
||||
TCreateAcmeOrderResponse,
|
||||
TDeactivateAcmeAccountResponse,
|
||||
TDownloadAcmeCertificateDTO,
|
||||
TFinalizeAcmeOrderResponse,
|
||||
TGetAcmeAuthorizationResponse,
|
||||
TGetAcmeDirectoryResponse,
|
||||
TGetAcmeOrderResponse,
|
||||
TListAcmeOrdersResponse,
|
||||
TPkiAcmeServiceFactory,
|
||||
TRespondToAcmeChallengeResponse
|
||||
} from "./pki-acme-types";
|
||||
|
||||
type TPkiAcmeServiceFactoryDep = {
|
||||
certificateProfileDAL: Pick<TCertificateProfileDALFactory, "findById">;
|
||||
};
|
||||
|
||||
export const pkiAcmeServiceFactory = ({ certificateProfileDAL }: TPkiAcmeServiceFactoryDep): TPkiAcmeServiceFactory => {
|
||||
const getAcmeDirectory = async (profileId: string): Promise<TGetAcmeDirectoryResponse> => {
|
||||
// FIXME: Implement ACME directory endpoint
|
||||
// Validate profile exists and is for ACME enrollment
|
||||
const profile = await certificateProfileDAL.findById(profileId);
|
||||
if (!profile) {
|
||||
throw new NotFoundError({ message: "Certificate profile not found" });
|
||||
}
|
||||
|
||||
// FIXME: Validate profile is configured for ACME enrollment
|
||||
return {
|
||||
newNonce: `/api/v1/pki/acme/profiles/${profileId}/new-nonce`,
|
||||
newAccount: `/api/v1/pki/acme/profiles/${profileId}/new-account`,
|
||||
newOrder: `/api/v1/pki/acme/profiles/${profileId}/new-order`,
|
||||
revokeCert: `/api/v1/pki/acme/profiles/${profileId}/revoke-cert`
|
||||
};
|
||||
};
|
||||
|
||||
const getAcmeNewNonce = async (profileId: string): Promise<string> => {
|
||||
// FIXME: Implement ACME new nonce generation
|
||||
// Generate a new nonce, store it, and return it
|
||||
return "FIXME-generate-nonce";
|
||||
};
|
||||
|
||||
const createAcmeAccount = async (profileId: string, body: unknown): Promise<TCreateAcmeAccountResponse> => {
|
||||
// FIXME: Implement ACME new account registration
|
||||
// Use EAB authentication to find corresponding Infisical machine identity
|
||||
// Check permissions and return account information
|
||||
return {
|
||||
status: "valid",
|
||||
accountUrl: `/api/v1/pki/acme/profiles/${profileId}/accounts/FIXME-account-id`,
|
||||
contact: [],
|
||||
orders: `/api/v1/pki/acme/profiles/${profileId}/accounts/FIXME-account-id/orders`
|
||||
};
|
||||
};
|
||||
|
||||
const createAcmeOrder = async (profileId: string, body: unknown): Promise<TCreateAcmeOrderResponse> => {
|
||||
// FIXME: Implement ACME new order creation
|
||||
const orderId = "FIXME-order-id";
|
||||
return {
|
||||
status: "pending",
|
||||
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
||||
identifiers: [],
|
||||
authorizations: [],
|
||||
finalize: `/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/finalize`
|
||||
};
|
||||
};
|
||||
|
||||
const deactivateAcmeAccount = async (
|
||||
profileId: string,
|
||||
accountId: string
|
||||
): Promise<TDeactivateAcmeAccountResponse> => {
|
||||
// FIXME: Implement ACME account deactivation
|
||||
return {
|
||||
status: "deactivated"
|
||||
};
|
||||
};
|
||||
|
||||
const listAcmeOrders = async (profileId: string, accountId: string): Promise<TListAcmeOrdersResponse> => {
|
||||
// FIXME: Implement ACME list orders
|
||||
return {
|
||||
orders: []
|
||||
};
|
||||
};
|
||||
|
||||
const getAcmeOrder = async (profileId: string, orderId: string): Promise<TGetAcmeOrderResponse> => {
|
||||
// FIXME: Implement ACME get order
|
||||
return {
|
||||
status: "pending",
|
||||
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
||||
identifiers: [],
|
||||
authorizations: [],
|
||||
finalize: `/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/finalize`
|
||||
};
|
||||
};
|
||||
|
||||
const finalizeAcmeOrder = async (
|
||||
profileId: string,
|
||||
orderId: string,
|
||||
csr: string
|
||||
): Promise<TFinalizeAcmeOrderResponse> => {
|
||||
// FIXME: Implement ACME finalize order
|
||||
return {
|
||||
status: "processing",
|
||||
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
||||
identifiers: [],
|
||||
authorizations: [],
|
||||
finalize: `/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/finalize`,
|
||||
certificate: `/api/v1/pki/acme/profiles/${profileId}/orders/${orderId}/certificate`
|
||||
};
|
||||
};
|
||||
|
||||
const downloadAcmeCertificate = async (profileId: string, orderId: string): Promise<string> => {
|
||||
// FIXME: Implement ACME certificate download
|
||||
// Return the certificate in PEM format
|
||||
return "FIXME-certificate-pem";
|
||||
};
|
||||
|
||||
const getAcmeAuthorization = async (profileId: string, authzId: string): Promise<TGetAcmeAuthorizationResponse> => {
|
||||
// FIXME: Implement ACME authorization retrieval
|
||||
return {
|
||||
status: "pending",
|
||||
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
||||
identifier: {
|
||||
type: "dns",
|
||||
value: "FIXME-domain-name"
|
||||
},
|
||||
challenges: [
|
||||
{
|
||||
type: "http-01",
|
||||
url: `/api/v1/pki/acme/profiles/${profileId}/authorizations/${authzId}/challenges/http-01`,
|
||||
status: "pending",
|
||||
token: "FIXME-challenge-token"
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
const respondToAcmeChallenge = async (
|
||||
profileId: string,
|
||||
authzId: string
|
||||
): Promise<TRespondToAcmeChallengeResponse> => {
|
||||
// FIXME: Implement ACME challenge response
|
||||
// Trigger verification process
|
||||
return {
|
||||
type: "http-01",
|
||||
url: `/api/v1/pki/acme/profiles/${profileId}/authorizations/${authzId}/challenges/http-01`,
|
||||
status: "pending",
|
||||
token: "FIXME-challenge-token"
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
getAcmeDirectory,
|
||||
getAcmeNewNonce,
|
||||
createAcmeAccount,
|
||||
createAcmeOrder,
|
||||
deactivateAcmeAccount,
|
||||
listAcmeOrders,
|
||||
getAcmeOrder,
|
||||
finalizeAcmeOrder,
|
||||
downloadAcmeCertificate,
|
||||
getAcmeAuthorization,
|
||||
respondToAcmeChallenge
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
CreateAcmeAccountResponseSchema,
|
||||
CreateAcmeOrderResponseSchema,
|
||||
DeactivateAcmeAccountResponseSchema,
|
||||
FinalizeAcmeOrderResponseSchema,
|
||||
GetAcmeAuthorizationResponseSchema,
|
||||
GetAcmeDirectoryResponseSchema,
|
||||
GetAcmeOrderResponseSchema,
|
||||
ListAcmeOrdersResponseSchema,
|
||||
RespondToAcmeChallengeResponseSchema
|
||||
} from "./pki-acme-schemas";
|
||||
|
||||
export type TGetAcmeDirectoryResponse = z.infer<typeof GetAcmeDirectoryResponseSchema>;
|
||||
export type TCreateAcmeAccountResponse = z.infer<typeof CreateAcmeAccountResponseSchema>;
|
||||
export type TCreateAcmeOrderResponse = z.infer<typeof CreateAcmeOrderResponseSchema>;
|
||||
export type TDeactivateAcmeAccountResponse = z.infer<typeof DeactivateAcmeAccountResponseSchema>;
|
||||
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 TGetAcmeAuthorizationResponse = z.infer<typeof GetAcmeAuthorizationResponseSchema>;
|
||||
export type TRespondToAcmeChallengeResponse = z.infer<typeof RespondToAcmeChallengeResponseSchema>;
|
||||
|
||||
export type TPkiAcmeServiceFactory = {
|
||||
getAcmeDirectory: (profileId: string) => Promise<TGetAcmeDirectoryResponse>;
|
||||
getAcmeNewNonce: (profileId: string) => Promise<string>;
|
||||
createAcmeAccount: (profileId: string, body: unknown) => Promise<TCreateAcmeAccountResponse>;
|
||||
createAcmeOrder: (profileId: string, body: unknown) => Promise<TCreateAcmeOrderResponse>;
|
||||
deactivateAcmeAccount: (profileId: string, accountId: string) => Promise<TDeactivateAcmeAccountResponse>;
|
||||
listAcmeOrders: (profileId: string, accountId: string) => Promise<TListAcmeOrdersResponse>;
|
||||
getAcmeOrder: (profileId: string, orderId: string) => Promise<TGetAcmeOrderResponse>;
|
||||
finalizeAcmeOrder: (profileId: string, orderId: string, csr: string) => Promise<TFinalizeAcmeOrderResponse>;
|
||||
downloadAcmeCertificate: (profileId: string, orderId: string) => Promise<string>;
|
||||
getAcmeAuthorization: (profileId: string, authzId: string) => Promise<TGetAcmeAuthorizationResponse>;
|
||||
respondToAcmeChallenge: (profileId: string, authzId: string) => Promise<TRespondToAcmeChallengeResponse>;
|
||||
};
|
||||
Reference in New Issue
Block a user