misc: added route for acme

This commit is contained in:
Sheen Capadngan
2025-05-15 04:18:01 +08:00
parent 6faad102e2
commit c2949964b3
16 changed files with 457 additions and 37 deletions

View File

@@ -78,6 +78,7 @@ export async function up(knex: Knex): Promise<void> {
.onDelete("CASCADE");
t.binary("credentials");
t.json("configuration");
t.string("status").notNullable();
});
}
}

View File

@@ -17,7 +17,8 @@ export const ExternalCertificateAuthoritiesSchema = z.object({
dnsAppConnectionId: z.string().uuid().nullable().optional(),
certificateAuthorityId: z.string().uuid(),
credentials: zodBuffer.nullable().optional(),
configuration: z.unknown().nullable().optional()
configuration: z.unknown().nullable().optional(),
status: z.string()
});
export type TExternalCertificateAuthorities = z.infer<typeof ExternalCertificateAuthoritiesSchema>;

View File

@@ -133,6 +133,7 @@ import { certificateAuthorityDALFactory } from "@app/services/certificate-author
import { certificateAuthorityQueueFactory } from "@app/services/certificate-authority/certificate-authority-queue";
import { certificateAuthoritySecretDALFactory } from "@app/services/certificate-authority/certificate-authority-secret-dal";
import { certificateAuthorityServiceFactory } from "@app/services/certificate-authority/certificate-authority-service";
import { externalCertificateAuthorityDALFactory } from "@app/services/certificate-authority/external-certificate-authority-dal";
import { internalCertificateAuthorityDALFactory } from "@app/services/certificate-authority/internal/internal-certificate-authority-dal";
import { internalCertificateAuthorityServiceFactory } from "@app/services/certificate-authority/internal/internal-certificate-authority-service";
import { certificateTemplateDALFactory } from "@app/services/certificate-template/certificate-template-dal";
@@ -820,6 +821,7 @@ export const registerRoutes = async (
const certificateAuthorityDAL = certificateAuthorityDALFactory(db);
const internalCertificateAuthorityDAL = internalCertificateAuthorityDALFactory(db);
const externalCertificateAuthorityDAL = externalCertificateAuthorityDALFactory(db);
const certificateAuthorityCertDAL = certificateAuthorityCertDALFactory(db);
const certificateAuthoritySecretDAL = certificateAuthoritySecretDALFactory(db);
const certificateAuthorityCrlDAL = certificateAuthorityCrlDALFactory(db);
@@ -904,23 +906,6 @@ export const registerRoutes = async (
groupDAL
});
const certificateAuthorityService = certificateAuthorityServiceFactory({
certificateAuthorityDAL,
certificateAuthorityCertDAL,
certificateAuthoritySecretDAL,
certificateAuthorityCrlDAL,
certificateTemplateDAL,
certificateAuthorityQueue,
certificateDAL,
certificateBodyDAL,
certificateSecretDAL,
pkiCollectionDAL,
pkiCollectionItemDAL,
projectDAL,
kmsService,
permissionService
});
const internalCertificateAuthorityService = internalCertificateAuthorityServiceFactory({
certificateAuthorityDAL,
certificateAuthorityCertDAL,
@@ -1695,6 +1680,16 @@ export const registerRoutes = async (
appConnectionDAL
});
const certificateAuthorityService = certificateAuthorityServiceFactory({
certificateAuthorityDAL,
projectDAL,
permissionService,
appConnectionDAL,
appConnectionService,
externalCertificateAuthorityDAL,
internalCertificateAuthorityService
});
await secretRotationV2QueueServiceFactory({
secretRotationV2Service,
secretRotationV2DAL,

View File

@@ -0,0 +1,18 @@
import {
AcmeCertificateAuthoritySchema,
CreateAcmeCertificateAuthoritySchema,
UpdateAcmeCertificateAuthoritySchema
} from "@app/services/certificate-authority/acme/acme-certificate-authority-schemas";
import { CaType } from "@app/services/certificate-authority/certificate-authority-enums";
import { registerCertificateAuthorityEndpoints } from "./certificate-authority-endpoints";
export const registerAcmeCertificateAuthorityRouter = async (server: FastifyZodProvider) => {
registerCertificateAuthorityEndpoints({
caType: CaType.ACME,
server,
responseSchema: AcmeCertificateAuthoritySchema,
createSchema: CreateAcmeCertificateAuthoritySchema,
updateSchema: UpdateAcmeCertificateAuthoritySchema
});
};

View File

@@ -1,5 +1,6 @@
import { CaType } from "@app/services/certificate-authority/certificate-authority-enums";
import { registerAcmeCertificateAuthorityRouter } from "./acme-certificate-authority-router";
import { registerInternalCertificateAuthorityRouter } from "./internal-certificate-authority-router";
export * from "./internal-certificate-authority-router";
@@ -7,5 +8,5 @@ export * from "./internal-certificate-authority-router";
export const CERTIFICATE_AUTHORITY_REGISTER_ROUTER_MAP: Record<CaType, (server: FastifyZodProvider) => Promise<void>> =
{
[CaType.INTERNAL]: registerInternalCertificateAuthorityRouter,
[CaType.ACME]: registerInternalCertificateAuthorityRouter
[CaType.ACME]: registerAcmeCertificateAuthorityRouter
};

View File

@@ -0,0 +1,3 @@
export enum AcmeDnsProvider {
Route53 = "route53"
}

View File

@@ -0,0 +1,199 @@
import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { OrgServiceActor } from "@app/lib/types";
import { TAppConnectionDALFactory } from "@app/services/app-connection/app-connection-dal";
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
import { TAppConnectionServiceFactory } from "@app/services/app-connection/app-connection-service";
import { TCertificateAuthorityDALFactory } from "../certificate-authority-dal";
import { CaStatus, CaType } from "../certificate-authority-enums";
import { TCertificateAuthority } from "../certificate-authority-types";
import { TExternalCertificateAuthorityDALFactory } from "../external-certificate-authority-dal";
import { AcmeDnsProvider } from "./acme-certificate-authority-enums";
import {
TCreateAcmeCertificateAuthorityDTO,
TUpdateAcmeCertificateAuthorityDTO
} from "./acme-certificate-authority-types";
type TAcmeCertificateAuthorityFnsDeps = {
appConnectionDAL: Pick<TAppConnectionDALFactory, "findById">;
appConnectionService: Pick<TAppConnectionServiceFactory, "connectAppConnectionById">;
certificateAuthorityDAL: Pick<
TCertificateAuthorityDALFactory,
"create" | "transaction" | "findByIdWithAssociatedCa" | "updateById"
>;
externalCertificateAuthorityDAL: Pick<TExternalCertificateAuthorityDALFactory, "create" | "update">;
};
export const AcmeCertificateAuthorityFns = ({
appConnectionDAL,
appConnectionService,
certificateAuthorityDAL,
externalCertificateAuthorityDAL
}: TAcmeCertificateAuthorityFnsDeps) => {
const createCertificateAuthority = async ({
name,
projectId,
configuration,
disableDirectIssuance,
actor,
status
}: {
status: CaStatus;
name: string;
projectId: string;
configuration: TCreateAcmeCertificateAuthorityDTO["configuration"];
disableDirectIssuance: boolean;
actor: OrgServiceActor;
}) => {
const { dnsAppConnectionId, directoryUrl, accountEmail, dnsProvider } = configuration;
const appConnection = await appConnectionDAL.findById(dnsAppConnectionId);
if (!appConnection) {
throw new NotFoundError({ message: `App connection with ID '${dnsAppConnectionId}' not found` });
}
if (dnsProvider === AcmeDnsProvider.Route53 && appConnection.app !== AppConnection.AWS) {
throw new BadRequestError({
message: `App connection with ID '${dnsAppConnectionId}' is not an AWS connection`
});
}
// validates permission to connect
await appConnectionService.connectAppConnectionById(appConnection.app as AppConnection, dnsAppConnectionId, actor);
const caEntity = await certificateAuthorityDAL.transaction(async (tx) => {
const ca = await certificateAuthorityDAL.create(
{
projectId,
disableDirectIssuance
},
tx
);
await externalCertificateAuthorityDAL.create(
{
certificateAuthorityId: ca.id,
dnsAppConnectionId,
type: CaType.ACME,
name,
configuration: {
directoryUrl,
accountEmail,
dnsProvider
},
status
},
tx
);
return certificateAuthorityDAL.findByIdWithAssociatedCa(ca.id, tx);
});
if (!caEntity.externalCa) {
throw new BadRequestError({ message: "Failed to create external certificate authority" });
}
return {
id: caEntity.id,
type: CaType.ACME,
disableDirectIssuance: caEntity.disableDirectIssuance,
name: caEntity.externalCa.name,
projectId,
status,
configuration: caEntity.externalCa.configuration
} as TCertificateAuthority;
};
const updateCertificateAuthority = async ({
id,
status,
configuration,
disableDirectIssuance,
actor
}: {
id: string;
status?: CaStatus;
configuration: TUpdateAcmeCertificateAuthorityDTO["configuration"];
disableDirectIssuance?: boolean;
actor: OrgServiceActor;
}) => {
const updatedCa = await certificateAuthorityDAL.transaction(async (tx) => {
if (configuration) {
const { dnsAppConnectionId, directoryUrl, accountEmail, dnsProvider } = configuration;
const appConnection = await appConnectionDAL.findById(dnsAppConnectionId);
if (!appConnection) {
throw new NotFoundError({ message: `App connection with ID '${dnsAppConnectionId}' not found` });
}
if (dnsProvider === AcmeDnsProvider.Route53 && appConnection.app !== AppConnection.AWS) {
throw new BadRequestError({
message: `App connection with ID '${dnsAppConnectionId}' is not an AWS connection`
});
}
// validates permission to connect
await appConnectionService.connectAppConnectionById(
appConnection.app as AppConnection,
dnsAppConnectionId,
actor
);
await externalCertificateAuthorityDAL.update(
{
certificateAuthorityId: id,
type: CaType.ACME
},
{
configuration: { directoryUrl, accountEmail, dnsProvider, dnsAppConnectionId }
},
tx
);
}
if (status) {
await externalCertificateAuthorityDAL.update(
{
certificateAuthorityId: id,
type: CaType.ACME
},
{
status
},
tx
);
}
if (disableDirectIssuance !== undefined) {
await certificateAuthorityDAL.updateById(
id,
{
disableDirectIssuance
},
tx
);
}
return certificateAuthorityDAL.findByIdWithAssociatedCa(id, tx);
});
if (!updatedCa.externalCa) {
throw new BadRequestError({ message: "Failed to update external certificate authority" });
}
return {
id: updatedCa.id,
type: CaType.ACME,
disableDirectIssuance: updatedCa.disableDirectIssuance,
name: updatedCa.externalCa.name,
projectId: updatedCa.projectId,
status: updatedCa.externalCa.status,
configuration: updatedCa.externalCa.configuration
};
};
return {
createCertificateAuthority,
updateCertificateAuthority
};
};

View File

@@ -0,0 +1,29 @@
import { z } from "zod";
import { CaType } from "../certificate-authority-enums";
import {
BaseCertificateAuthoritySchema,
GenericCreateCertificateAuthorityFieldsSchema,
GenericUpdateCertificateAuthorityFieldsSchema
} from "../certificate-authority-schemas";
import { AcmeDnsProvider } from "./acme-certificate-authority-enums";
export const AcmeCertificateAuthorityConfigurationSchema = z.object({
dnsAppConnectionId: z.string().trim(),
dnsProvider: z.nativeEnum(AcmeDnsProvider),
directoryUrl: z.string().trim(),
accountEmail: z.string().trim()
});
export const AcmeCertificateAuthoritySchema = BaseCertificateAuthoritySchema(CaType.ACME).extend({
type: z.literal(CaType.ACME),
configuration: AcmeCertificateAuthorityConfigurationSchema
});
export const CreateAcmeCertificateAuthoritySchema = GenericCreateCertificateAuthorityFieldsSchema(CaType.ACME).extend({
configuration: AcmeCertificateAuthorityConfigurationSchema
});
export const UpdateAcmeCertificateAuthoritySchema = GenericUpdateCertificateAuthorityFieldsSchema(CaType.ACME).extend({
configuration: AcmeCertificateAuthorityConfigurationSchema.optional()
});

View File

@@ -0,0 +1,15 @@
import { z } from "zod";
import {
AcmeCertificateAuthoritySchema,
CreateAcmeCertificateAuthoritySchema,
UpdateAcmeCertificateAuthoritySchema
} from "./acme-certificate-authority-schemas";
export type TAcmeCertificateAuthority = z.infer<typeof AcmeCertificateAuthoritySchema>;
export type TAcmeCertificateAuthorityInput = z.infer<typeof CreateAcmeCertificateAuthoritySchema>;
export type TCreateAcmeCertificateAuthorityDTO = z.infer<typeof CreateAcmeCertificateAuthoritySchema>;
export type TUpdateAcmeCertificateAuthorityDTO = z.infer<typeof UpdateAcmeCertificateAuthoritySchema>;

View File

@@ -21,6 +21,11 @@ export const certificateAuthorityDALFactory = (db: TDbClient) => {
`${TableName.CertificateAuthority}.id`,
`${TableName.InternalCertificateAuthority}.certificateAuthorityId`
)
.leftJoin(
TableName.ExternalCertificateAuthority,
`${TableName.CertificateAuthority}.id`,
`${TableName.ExternalCertificateAuthority}.certificateAuthorityId`
)
.where(`${TableName.CertificateAuthority}.id`, caId)
.select(selectAllTableCols(TableName.CertificateAuthority))
.select(
@@ -47,6 +52,18 @@ export const certificateAuthorityDALFactory = (db: TDbClient) => {
.withSchema(TableName.InternalCertificateAuthority)
.as("internalCertificateAuthorityId")
)
.select(
db.ref("id").withSchema(TableName.ExternalCertificateAuthority).as("externalCaId"),
db.ref("name").withSchema(TableName.ExternalCertificateAuthority).as("externalName"),
db.ref("type").withSchema(TableName.ExternalCertificateAuthority).as("externalType"),
db.ref("status").withSchema(TableName.ExternalCertificateAuthority).as("externalStatus"),
db.ref("configuration").withSchema(TableName.ExternalCertificateAuthority).as("externalConfiguration"),
db
.ref("dnsAppConnectionId")
.withSchema(TableName.ExternalCertificateAuthority)
.as("externalDnsAppConnectionId"),
db.ref("appConnectionId").withSchema(TableName.ExternalCertificateAuthority).as("externalAppConnectionId")
)
.first();
const data = {
@@ -73,6 +90,17 @@ export const certificateAuthorityDALFactory = (db: TDbClient) => {
activeCaCertId: result.internalActiveCaCertId,
certificateAuthorityId: result.internalCertificateAuthorityId
}
: undefined,
externalCa: result
? {
id: result.externalCaId,
name: result.externalName,
type: result.externalType,
status: result.externalStatus,
configuration: result.externalConfiguration,
dnsAppConnectionId: result.externalDnsAppConnectionId,
appConnectionId: result.externalAppConnectionId
}
: undefined
};
@@ -158,11 +186,15 @@ export const certificateAuthorityDALFactory = (db: TDbClient) => {
)
.select(
db.ref("id").withSchema(TableName.ExternalCertificateAuthority).as("externalCaId"),
db.ref("name").withSchema(TableName.ExternalCertificateAuthority).as("externalName"),
db.ref("type").withSchema(TableName.ExternalCertificateAuthority).as("externalType"),
db.ref("status").withSchema(TableName.ExternalCertificateAuthority).as("externalStatus"),
db.ref("configuration").withSchema(TableName.ExternalCertificateAuthority).as("externalConfiguration"),
db
.ref("certificateAuthorityId")
.ref("dnsAppConnectionId")
.withSchema(TableName.ExternalCertificateAuthority)
.as("externalCertificateAuthorityId")
.as("externalDnsAppConnectionId"),
db.ref("appConnectionId").withSchema(TableName.ExternalCertificateAuthority).as("externalAppConnectionId")
);
if (limit) void query.limit(limit);
@@ -201,6 +233,17 @@ export const certificateAuthorityDALFactory = (db: TDbClient) => {
activeCaCertId: ca.internalActiveCaCertId,
certificateAuthorityId: ca.internalCertificateAuthorityId
}
: undefined,
externalCa: ca
? {
id: ca.externalCaId,
name: ca.externalName,
type: ca.externalType,
status: ca.externalStatus,
configuration: ca.externalConfiguration,
dnsAppConnectionId: ca.externalDnsAppConnectionId,
appConnectionId: ca.externalAppConnectionId
}
: undefined
}));
} catch (error) {

View File

@@ -3,7 +3,7 @@ import z from "zod";
import { CertificateAuthoritiesSchema } from "@app/db/schemas";
import { slugSchema } from "@app/server/lib/schemas";
import { CaType } from "./certificate-authority-enums";
import { CaStatus, CaType } from "./certificate-authority-enums";
// SHEEN TODO: add description mapping using type
export const BaseCertificateAuthoritySchema = (type: CaType) =>
@@ -12,18 +12,21 @@ export const BaseCertificateAuthoritySchema = (type: CaType) =>
disableDirectIssuance: true,
id: true
}).extend({
name: z.string()
name: z.string(),
status: z.nativeEnum(CaStatus)
});
export const GenericCreateCertificateAuthorityFieldsSchema = (type: CaType) =>
z.object({
name: slugSchema({ field: "name" }),
projectId: z.string().trim().min(1, "Project ID required"),
disableDirectIssuance: z.boolean()
disableDirectIssuance: z.boolean(),
status: z.nativeEnum(CaStatus)
});
export const GenericUpdateCertificateAuthorityFieldsSchema = (type: CaType) =>
z.object({
name: slugSchema({ field: "name" }).optional(),
disableDirectIssuance: z.boolean().optional()
disableDirectIssuance: z.boolean().optional(),
status: z.nativeEnum(CaStatus).optional()
});

View File

@@ -6,7 +6,14 @@ import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services
import { BadRequestError, NotFoundError } from "@app/lib/errors";
import { OrgServiceActor } from "@app/lib/types";
import { TAppConnectionDALFactory } from "../app-connection/app-connection-dal";
import { TAppConnectionServiceFactory } from "../app-connection/app-connection-service";
import { TProjectDALFactory } from "../project/project-dal";
import { AcmeCertificateAuthorityFns } from "./acme/acme-certificate-authority-fns";
import {
TCreateAcmeCertificateAuthorityDTO,
TUpdateAcmeCertificateAuthorityDTO
} from "./acme/acme-certificate-authority-types";
import { TCertificateAuthorityDALFactory } from "./certificate-authority-dal";
import { CaType } from "./certificate-authority-enums";
import {
@@ -14,9 +21,13 @@ import {
TCreateCertificateAuthorityDTO,
TUpdateCertificateAuthorityDTO
} from "./certificate-authority-types";
import { TExternalCertificateAuthorityDALFactory } from "./external-certificate-authority-dal";
import { TInternalCertificateAuthorityServiceFactory } from "./internal/internal-certificate-authority-service";
import { TCreateInternalCertificateAuthorityDTO } from "./internal/internal-certificate-authority-types";
type TCertificateAuthorityServiceFactoryDep = {
appConnectionDAL: Pick<TAppConnectionDALFactory, "findById" | "update">;
appConnectionService: Pick<TAppConnectionServiceFactory, "connectAppConnectionById">;
certificateAuthorityDAL: Pick<
TCertificateAuthorityDALFactory,
| "transaction"
@@ -28,6 +39,7 @@ type TCertificateAuthorityServiceFactoryDep = {
| "findByIdWithAssociatedCa"
| "findWithAssociatedCa"
>;
externalCertificateAuthorityDAL: Pick<TExternalCertificateAuthorityDALFactory, "create" | "update">;
internalCertificateAuthorityService: TInternalCertificateAuthorityServiceFactory;
projectDAL: Pick<
TProjectDALFactory,
@@ -42,10 +54,20 @@ export const certificateAuthorityServiceFactory = ({
certificateAuthorityDAL,
projectDAL,
permissionService,
internalCertificateAuthorityService
internalCertificateAuthorityService,
appConnectionDAL,
appConnectionService,
externalCertificateAuthorityDAL
}: TCertificateAuthorityServiceFactoryDep) => {
const acmeFns = AcmeCertificateAuthorityFns({
appConnectionDAL,
appConnectionService,
certificateAuthorityDAL,
externalCertificateAuthorityDAL
});
const createCertificateAuthority = async (
{ type, projectId, configuration, disableDirectIssuance }: TCreateCertificateAuthorityDTO,
{ type, projectId, name, disableDirectIssuance, configuration, status }: TCreateCertificateAuthorityDTO,
actor: OrgServiceActor
) => {
let finalProjectId: string = projectId;
@@ -74,7 +96,7 @@ export const certificateAuthorityServiceFactory = ({
if (type === CaType.INTERNAL) {
const ca = await internalCertificateAuthorityService.createCa({
...configuration,
...(configuration as TCreateInternalCertificateAuthorityDTO["configuration"]),
isInternal: true,
projectId: finalProjectId,
requireTemplateForIssuance: disableDirectIssuance
@@ -92,9 +114,21 @@ export const certificateAuthorityServiceFactory = ({
disableDirectIssuance: ca.disableDirectIssuance,
name: ca.internalCa?.friendlyName,
projectId,
status,
configuration: ca.internalCa
} as TCertificateAuthority;
}
if (type === CaType.ACME) {
return acmeFns.createCertificateAuthority({
name,
projectId: finalProjectId,
configuration: configuration as TCreateAcmeCertificateAuthorityDTO["configuration"],
disableDirectIssuance,
status,
actor
});
}
};
const findCertificateAuthorityById = async (
@@ -135,9 +169,25 @@ export const certificateAuthorityServiceFactory = ({
disableDirectIssuance: certificateAuthority.disableDirectIssuance,
name: certificateAuthority.internalCa.friendlyName,
projectId: certificateAuthority.projectId,
configuration: certificateAuthority.internalCa
configuration: certificateAuthority.internalCa,
status: certificateAuthority.internalCa.status
} as TCertificateAuthority;
}
if (certificateAuthority.externalCa?.type !== type) {
throw new NotFoundError({
message: `Could not find external certificate authority with ID "${certificateAuthorityId}" and type "${type}"`
});
}
return {
id: certificateAuthority.id,
type,
disableDirectIssuance: certificateAuthority.disableDirectIssuance,
name: certificateAuthority.externalCa.name,
projectId: certificateAuthority.projectId,
configuration: certificateAuthority.externalCa.configuration
} as TCertificateAuthority;
};
const listCertificateAuthoritiesByProjectId = async (
@@ -187,13 +237,26 @@ export const certificateAuthorityServiceFactory = ({
disableDirectIssuance: ca.disableDirectIssuance,
name: ca.internalCa.friendlyName,
projectId: ca.projectId,
configuration: ca.internalCa
configuration: ca.internalCa,
status: ca.internalCa.status
})) as TCertificateAuthority[];
}
return cas
.filter((ca): ca is typeof ca & { externalCa: NonNullable<typeof ca.externalCa> } => Boolean(ca.externalCa))
.map((ca) => ({
id: ca.id,
type,
disableDirectIssuance: ca.disableDirectIssuance,
name: ca.externalCa.name,
projectId: ca.projectId,
configuration: ca.externalCa.configuration,
status: ca.externalCa.status
})) as TCertificateAuthority[];
};
const updateCertificateAuthority = async (
{ id, type, configuration, disableDirectIssuance }: TUpdateCertificateAuthorityDTO,
{ id, type, configuration, disableDirectIssuance, status }: TUpdateCertificateAuthorityDTO,
actor: OrgServiceActor
) => {
const certificateAuthority = await certificateAuthorityDAL.findByIdWithAssociatedCa(id);
@@ -243,9 +306,22 @@ export const certificateAuthorityServiceFactory = ({
disableDirectIssuance: updatedCa.disableDirectIssuance,
name: updatedCa.internalCa?.friendlyName,
projectId: updatedCa.projectId,
configuration: updatedCa.internalCa
configuration: updatedCa.internalCa,
status: updatedCa.internalCa?.status
} as TCertificateAuthority;
}
if (type === CaType.ACME) {
return acmeFns.updateCertificateAuthority({
id,
configuration: configuration as TUpdateAcmeCertificateAuthorityDTO["configuration"],
disableDirectIssuance,
actor,
status
});
}
throw new BadRequestError({ message: "Invalid certificate authority type" });
};
const deleteCertificateAuthority = async ({ id, type }: { id: string; type: CaType }, actor: OrgServiceActor) => {
@@ -276,6 +352,12 @@ export const certificateAuthorityServiceFactory = ({
});
}
if (certificateAuthority.externalCa && certificateAuthority.externalCa.type !== type) {
throw new BadRequestError({
message: "Certificate authority cannot be deleted due to mismatching type"
});
}
await certificateAuthorityDAL.deleteById(id);
if (type === CaType.INTERNAL) {
@@ -285,9 +367,20 @@ export const certificateAuthorityServiceFactory = ({
disableDirectIssuance: certificateAuthority.disableDirectIssuance,
name: certificateAuthority.internalCa?.friendlyName,
projectId: certificateAuthority.projectId,
configuration: certificateAuthority.internalCa
configuration: certificateAuthority.internalCa,
status: certificateAuthority.internalCa?.status
} as TCertificateAuthority;
}
return {
id: certificateAuthority.id,
type,
disableDirectIssuance: certificateAuthority.disableDirectIssuance,
name: certificateAuthority.externalCa?.name,
projectId: certificateAuthority.projectId,
configuration: certificateAuthority.externalCa?.configuration,
status: certificateAuthority.externalCa?.status
} as TCertificateAuthority;
};
return {

View File

@@ -1,12 +1,13 @@
import { TAcmeCertificateAuthority, TAcmeCertificateAuthorityInput } from "./acme/acme-certificate-authority-types";
import { CaType } from "./certificate-authority-enums";
import {
TInternalCertificateAuthority,
TInternalCertificateAuthorityInput
} from "./internal/internal-certificate-authority-types";
export type TCertificateAuthority = TInternalCertificateAuthority;
export type TCertificateAuthority = TInternalCertificateAuthority | TAcmeCertificateAuthority;
export type TCertificateAuthorityInput = TInternalCertificateAuthorityInput;
export type TCertificateAuthorityInput = TInternalCertificateAuthorityInput | TAcmeCertificateAuthorityInput;
export type TCreateCertificateAuthorityDTO = Omit<TCertificateAuthority, "type" | "id"> & {
type: CaType;

View File

@@ -0,0 +1,13 @@
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { ormify } from "@app/lib/knex";
export type TExternalCertificateAuthorityDALFactory = ReturnType<typeof externalCertificateAuthorityDALFactory>;
export const externalCertificateAuthorityDALFactory = (db: TDbClient) => {
const caOrm = ormify(db, TableName.ExternalCertificateAuthority);
return {
...caOrm
};
};

View File

@@ -13,13 +13,18 @@ import { CaRenewalType, CaStatus, InternalCaType } from "../certificate-authorit
import { TCertificateAuthoritySecretDALFactory } from "../certificate-authority-secret-dal";
import {
CreateInternalCertificateAuthoritySchema,
InternalCertificateAuthoritySchema
InternalCertificateAuthoritySchema,
UpdateInternalCertificateAuthoritySchema
} from "./internal-certificate-authority-schemas";
export type TInternalCertificateAuthority = z.infer<typeof InternalCertificateAuthoritySchema>;
export type TInternalCertificateAuthorityInput = z.infer<typeof CreateInternalCertificateAuthoritySchema>;
export type TCreateInternalCertificateAuthorityDTO = z.infer<typeof CreateInternalCertificateAuthoritySchema>;
export type TUpdateInternalCertificateAuthorityDTO = z.infer<typeof UpdateInternalCertificateAuthoritySchema>;
export type TCreateCaDTO =
| {
isInternal: true;

View File

@@ -17,7 +17,7 @@ export const CertificateAuthoritiesPage = () => {
<div className="mx-auto mb-6 w-full max-w-7xl">
<PageHeader
title="Certificate Authorities"
description="Manage internal private certificate authorities for issuing and signing certificates, including root and intermediate CAs."
description="Manage certificate authorities for issuing and signing certificates"
/>
<ProjectPermissionCan
renderGuardBanner