mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-21 03:50:10 +00:00
Refine routers
This commit is contained in:
@@ -1,5 +1,26 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export enum AcmeIdentifierType {
|
||||
DNS = "dns"
|
||||
}
|
||||
|
||||
export enum AcmeOrderStatus {
|
||||
Pending = "pending",
|
||||
Processing = "processing",
|
||||
Ready = "ready",
|
||||
Valid = "valid",
|
||||
Invalid = "invalid"
|
||||
}
|
||||
|
||||
export enum AcmeAuthStatus {
|
||||
Pending = "pending",
|
||||
Valid = "valid",
|
||||
Invalid = "invalid",
|
||||
Deactivated = "deactivated",
|
||||
Expired = "expired",
|
||||
Revoked = "revoked"
|
||||
}
|
||||
|
||||
export const ProtectedHeaderSchema = z
|
||||
.object({
|
||||
alg: z.string(),
|
||||
@@ -20,13 +41,6 @@ export const RawJwsPayloadSchema = z.object({
|
||||
signature: z.string()
|
||||
});
|
||||
|
||||
// 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(),
|
||||
@@ -34,13 +48,6 @@ export const GetAcmeDirectoryResponseSchema = z.object({
|
||||
revokeCert: z.string().optional()
|
||||
});
|
||||
|
||||
// New Nonce endpoint
|
||||
export const GetAcmeNewNonceSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid()
|
||||
})
|
||||
});
|
||||
|
||||
// New Account payload schema
|
||||
export const CreateAcmeAccountBodySchema = z.object({
|
||||
contact: z.array(z.string()).optional(),
|
||||
@@ -73,22 +80,16 @@ export const CreateAcmeAccountResponseSchema = z.object({
|
||||
export const CreateAcmeOrderBodySchema = z.object({
|
||||
identifiers: z.array(
|
||||
z.object({
|
||||
type: z.string(),
|
||||
value: z.string()
|
||||
type: z
|
||||
.string()
|
||||
.regex(/^(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.(?!-)[A-Za-z0-9-]{1,63}(?<!-))*$/, "Invalid DNS identifier"),
|
||||
value: z.enum(Object.values(AcmeIdentifierType) as [string, ...string[]])
|
||||
})
|
||||
),
|
||||
notBefore: z.string().optional(),
|
||||
notAfter: z.string().optional()
|
||||
});
|
||||
|
||||
// New Order endpoint
|
||||
export const CreateAcmeOrderSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid()
|
||||
}),
|
||||
body: CreateAcmeOrderBodySchema
|
||||
});
|
||||
|
||||
export const CreateAcmeOrderResponseSchema = z.object({
|
||||
status: z.string(),
|
||||
expires: z.string(),
|
||||
@@ -108,41 +109,17 @@ export const DeactivateAcmeAccountBodySchema = z.object({
|
||||
status: z.literal("deactivated")
|
||||
});
|
||||
|
||||
// Account Deactivation endpoint
|
||||
export const DeactivateAcmeAccountSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid(),
|
||||
accountId: z.string()
|
||||
}),
|
||||
body: DeactivateAcmeAccountBodySchema
|
||||
});
|
||||
|
||||
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(),
|
||||
status: z.enum(Object.values(AcmeOrderStatus) as [string, ...string[]]),
|
||||
expires: z.string().optional(),
|
||||
identifiers: z.array(
|
||||
z.object({
|
||||
@@ -160,17 +137,8 @@ export const FinalizeAcmeOrderBodySchema = z.object({
|
||||
csr: z.string()
|
||||
});
|
||||
|
||||
// Finalize Order endpoint
|
||||
export const FinalizeAcmeOrderSchema = z.object({
|
||||
params: z.object({
|
||||
profileId: z.string().uuid(),
|
||||
orderId: z.string()
|
||||
}),
|
||||
body: FinalizeAcmeOrderBodySchema
|
||||
});
|
||||
|
||||
export const FinalizeAcmeOrderResponseSchema = z.object({
|
||||
status: z.string(),
|
||||
status: z.enum(Object.values(AcmeOrderStatus) as [string, ...string[]]),
|
||||
expires: z.string().optional(),
|
||||
identifiers: z.array(
|
||||
z.object({
|
||||
@@ -183,24 +151,8 @@ export const FinalizeAcmeOrderResponseSchema = z.object({
|
||||
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(),
|
||||
status: z.enum(Object.values(AcmeAuthStatus) as [string, ...string[]]),
|
||||
expires: z.string().optional(),
|
||||
identifier: z.object({
|
||||
type: z.string(),
|
||||
@@ -217,14 +169,6 @@ export const GetAcmeAuthorizationResponseSchema = z.object({
|
||||
)
|
||||
});
|
||||
|
||||
// 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(),
|
||||
|
||||
@@ -19,8 +19,15 @@ import {
|
||||
import { errors, flattenedVerify, FlattenedVerifyResult, importJWK, JWSHeaderParameters } from "jose";
|
||||
import { z, ZodError } from "zod";
|
||||
import { TPkiAcmeAccountDALFactory } from "./pki-acme-account-dal";
|
||||
import { TPkiAcmeAuthDALFactory } from "./pki-acme-auth-dal";
|
||||
import { TPkiAcmeOrderDALFactory } from "./pki-acme-order-dal";
|
||||
import { CreateAcmeAccountBodySchema, ProtectedHeaderSchema } from "./pki-acme-schemas";
|
||||
import {
|
||||
AcmeAuthStatus,
|
||||
AcmeIdentifierType,
|
||||
AcmeOrderStatus,
|
||||
CreateAcmeAccountBodySchema,
|
||||
ProtectedHeaderSchema
|
||||
} from "./pki-acme-schemas";
|
||||
import {
|
||||
TAcmeResponse,
|
||||
TAuthenciatedJwsPayload,
|
||||
@@ -46,12 +53,14 @@ type TPkiAcmeServiceFactoryDep = {
|
||||
certificateProfileDAL: Pick<TCertificateProfileDALFactory, "findById">;
|
||||
acmeAccountDAL: Pick<TPkiAcmeAccountDALFactory, "findById" | "findByPublicKey" | "create">;
|
||||
acmeOrderDAL: Pick<TPkiAcmeOrderDALFactory, "create">;
|
||||
acmeAuthDAL: Pick<TPkiAcmeAuthDALFactory, "create">;
|
||||
};
|
||||
|
||||
export const pkiAcmeServiceFactory = ({
|
||||
certificateProfileDAL,
|
||||
acmeAccountDAL,
|
||||
acmeOrderDAL
|
||||
acmeOrderDAL,
|
||||
acmeAuthDAL
|
||||
}: TPkiAcmeServiceFactoryDep): TPkiAcmeServiceFactory => {
|
||||
const validateAcmeProfile = async (profileId: string): Promise<TCertificateProfileWithConfigs> => {
|
||||
const profile = await certificateProfileDAL.findById(profileId);
|
||||
@@ -168,11 +177,11 @@ export const pkiAcmeServiceFactory = ({
|
||||
};
|
||||
|
||||
const getAcmeDirectory = async (profileId: string): Promise<TGetAcmeDirectoryResponse> => {
|
||||
await validateAcmeProfile(profileId);
|
||||
const profile = await validateAcmeProfile(profileId);
|
||||
return {
|
||||
newNonce: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/new-nonce`),
|
||||
newAccount: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/new-account`),
|
||||
newOrder: buildUrl(`/api/v1/pki/acme/profiles/${profileId}/new-order`)
|
||||
newNonce: buildUrl(`/api/v1/pki/acme/profiles/${profile.id}/new-nonce`),
|
||||
newAccount: buildUrl(`/api/v1/pki/acme/profiles/${profile.id}/new-account`),
|
||||
newOrder: buildUrl(`/api/v1/pki/acme/profiles/${profile.id}/new-order`)
|
||||
};
|
||||
};
|
||||
|
||||
@@ -244,15 +253,29 @@ export const pkiAcmeServiceFactory = ({
|
||||
payload: TCreateAcmeOrderPayload;
|
||||
}): Promise<TAcmeResponse<TCreateAcmeOrderResponse>> => {
|
||||
const account = await acmeAccountDAL.findById(profileId, accountId)!;
|
||||
|
||||
// TODO: check and see if we have existing orders for this account that meet the criteria
|
||||
// if we do, return the existing order
|
||||
|
||||
orders = await acmeOrderDAL.create({
|
||||
profileId,
|
||||
accountId,
|
||||
status: "pending"
|
||||
const order = await acmeOrderDAL.create({
|
||||
accountId: account.id,
|
||||
status: AcmeOrderStatus.Pending
|
||||
});
|
||||
payload.identifiers.forEach(async (identifier) => {
|
||||
if (identifier.type === AcmeIdentifierType.DNS) {
|
||||
// TODO: reuse existing authorizations for this identifier if they exist
|
||||
const auth = await acmeAuthDAL.create({
|
||||
accountId: account.id,
|
||||
status: AcmeAuthStatus.Pending,
|
||||
identifierType: identifier.type,
|
||||
identifierValue: identifier.value,
|
||||
// TODO: read config from the profile to get the expiration time instead
|
||||
expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000)
|
||||
});
|
||||
} else {
|
||||
throw new AcmeMalformedError({ detail: "Only DNS identifiers are supported" });
|
||||
}
|
||||
});
|
||||
|
||||
// FIXME: Implement ACME new order creation
|
||||
const orderId = "FIXME-order-id";
|
||||
return {
|
||||
@@ -262,10 +285,10 @@ export const pkiAcmeServiceFactory = ({
|
||||
expires: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
||||
identifiers: [],
|
||||
authorizations: [],
|
||||
finalize: buildUrl(`/api/v1/pki/acme/profiles/${profile.id}/orders/${orderId}/finalize`)
|
||||
finalize: buildUrl(`/api/v1/pki/acme/profiles/${account.profileId}/orders/${orderId}/finalize`)
|
||||
},
|
||||
headers: {
|
||||
Location: buildUrl(`/api/v1/pki/acme/profiles/${profile.id}/orders/${orderId}`)
|
||||
Location: buildUrl(`/api/v1/pki/acme/profiles/${account.profileId}/orders/${orderId}`)
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user