mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 15:26:20 +00:00
misc: continued migration to new ca structure
This commit is contained in:
+8
-6
@@ -7,6 +7,7 @@ import { TPermissionServiceFactory } from "@app/ee/services/permission/permissio
|
|||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||||
import { NotFoundError } from "@app/lib/errors";
|
import { NotFoundError } from "@app/lib/errors";
|
||||||
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
||||||
|
import { expandInternalCa } from "@app/services/certificate-authority/certificate-authority-fns";
|
||||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns";
|
import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns";
|
||||||
@@ -14,7 +15,7 @@ import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns
|
|||||||
import { TGetCaCrlsDTO, TGetCrlById } from "./certificate-authority-crl-types";
|
import { TGetCaCrlsDTO, TGetCrlById } from "./certificate-authority-crl-types";
|
||||||
|
|
||||||
type TCertificateAuthorityCrlServiceFactoryDep = {
|
type TCertificateAuthorityCrlServiceFactoryDep = {
|
||||||
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">;
|
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findByIdWithAssociatedCa">;
|
||||||
certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "find" | "findById">;
|
certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "find" | "findById">;
|
||||||
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
|
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
|
||||||
kmsService: Pick<TKmsServiceFactory, "decryptWithKmsKey" | "generateKmsKey">;
|
kmsService: Pick<TKmsServiceFactory, "decryptWithKmsKey" | "generateKmsKey">;
|
||||||
@@ -37,7 +38,8 @@ export const certificateAuthorityCrlServiceFactory = ({
|
|||||||
const caCrl = await certificateAuthorityCrlDAL.findById(crlId);
|
const caCrl = await certificateAuthorityCrlDAL.findById(crlId);
|
||||||
if (!caCrl) throw new NotFoundError({ message: `CRL with ID '${crlId}' not found` });
|
if (!caCrl) throw new NotFoundError({ message: `CRL with ID '${crlId}' not found` });
|
||||||
|
|
||||||
const ca = await certificateAuthorityDAL.findById(caCrl.caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caCrl.caId);
|
||||||
|
if (!ca?.internalCa) throw new NotFoundError({ message: `CA with ID '${caCrl.caId}' not found` });
|
||||||
|
|
||||||
const keyId = await getProjectKmsCertificateKeyId({
|
const keyId = await getProjectKmsCertificateKeyId({
|
||||||
projectId: ca.projectId,
|
projectId: ca.projectId,
|
||||||
@@ -54,7 +56,7 @@ export const certificateAuthorityCrlServiceFactory = ({
|
|||||||
const crl = new x509.X509Crl(decryptedCrl);
|
const crl = new x509.X509Crl(decryptedCrl);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ca,
|
ca: expandInternalCa(ca),
|
||||||
caCrl,
|
caCrl,
|
||||||
crl: crl.rawData
|
crl: crl.rawData
|
||||||
};
|
};
|
||||||
@@ -64,8 +66,8 @@ export const certificateAuthorityCrlServiceFactory = ({
|
|||||||
* Returns a list of CRL ids for CA with id [caId]
|
* Returns a list of CRL ids for CA with id [caId]
|
||||||
*/
|
*/
|
||||||
const getCaCrls = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaCrlsDTO) => {
|
const getCaCrls = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCaCrlsDTO) => {
|
||||||
const ca = await certificateAuthorityDAL.findById(caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId);
|
||||||
if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
if (!ca?.internalCa) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -108,7 +110,7 @@ export const certificateAuthorityCrlServiceFactory = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ca,
|
ca: expandInternalCa(ca),
|
||||||
crls: decryptedCrls
|
crls: decryptedCrls
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { isCertChainValid } from "@app/services/certificate/certificate-fns";
|
|||||||
import { TCertificateAuthorityCertDALFactory } from "@app/services/certificate-authority/certificate-authority-cert-dal";
|
import { TCertificateAuthorityCertDALFactory } from "@app/services/certificate-authority/certificate-authority-cert-dal";
|
||||||
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
||||||
import { getCaCertChain, getCaCertChains } from "@app/services/certificate-authority/certificate-authority-fns";
|
import { getCaCertChain, getCaCertChains } from "@app/services/certificate-authority/certificate-authority-fns";
|
||||||
import { TCertificateAuthorityServiceFactory } from "@app/services/certificate-authority/certificate-authority-service";
|
import { TInternalCertificateAuthorityServiceFactory } from "@app/services/certificate-authority/internal-certificate-authority-service";
|
||||||
import { TCertificateTemplateDALFactory } from "@app/services/certificate-template/certificate-template-dal";
|
import { TCertificateTemplateDALFactory } from "@app/services/certificate-template/certificate-template-dal";
|
||||||
import { TCertificateTemplateServiceFactory } from "@app/services/certificate-template/certificate-template-service";
|
import { TCertificateTemplateServiceFactory } from "@app/services/certificate-template/certificate-template-service";
|
||||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||||
@@ -16,10 +16,10 @@ import { TLicenseServiceFactory } from "../license/license-service";
|
|||||||
import { convertRawCertsToPkcs7 } from "./certificate-est-fns";
|
import { convertRawCertsToPkcs7 } from "./certificate-est-fns";
|
||||||
|
|
||||||
type TCertificateEstServiceFactoryDep = {
|
type TCertificateEstServiceFactoryDep = {
|
||||||
certificateAuthorityService: Pick<TCertificateAuthorityServiceFactory, "signCertFromCa">;
|
internalCertificateAuthorityService: Pick<TInternalCertificateAuthorityServiceFactory, "signCertFromCa">;
|
||||||
certificateTemplateService: Pick<TCertificateTemplateServiceFactory, "getEstConfiguration">;
|
certificateTemplateService: Pick<TCertificateTemplateServiceFactory, "getEstConfiguration">;
|
||||||
certificateTemplateDAL: Pick<TCertificateTemplateDALFactory, "findById">;
|
certificateTemplateDAL: Pick<TCertificateTemplateDALFactory, "findById">;
|
||||||
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">;
|
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById" | "findByIdWithAssociatedCa">;
|
||||||
certificateAuthorityCertDAL: Pick<TCertificateAuthorityCertDALFactory, "find" | "findById">;
|
certificateAuthorityCertDAL: Pick<TCertificateAuthorityCertDALFactory, "find" | "findById">;
|
||||||
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
|
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
|
||||||
kmsService: Pick<TKmsServiceFactory, "decryptWithKmsKey" | "generateKmsKey">;
|
kmsService: Pick<TKmsServiceFactory, "decryptWithKmsKey" | "generateKmsKey">;
|
||||||
@@ -29,7 +29,7 @@ type TCertificateEstServiceFactoryDep = {
|
|||||||
export type TCertificateEstServiceFactory = ReturnType<typeof certificateEstServiceFactory>;
|
export type TCertificateEstServiceFactory = ReturnType<typeof certificateEstServiceFactory>;
|
||||||
|
|
||||||
export const certificateEstServiceFactory = ({
|
export const certificateEstServiceFactory = ({
|
||||||
certificateAuthorityService,
|
internalCertificateAuthorityService,
|
||||||
certificateTemplateService,
|
certificateTemplateService,
|
||||||
certificateTemplateDAL,
|
certificateTemplateDAL,
|
||||||
certificateAuthorityCertDAL,
|
certificateAuthorityCertDAL,
|
||||||
@@ -127,7 +127,7 @@ export const certificateEstServiceFactory = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const { certificate } = await certificateAuthorityService.signCertFromCa({
|
const { certificate } = await internalCertificateAuthorityService.signCertFromCa({
|
||||||
isInternal: true,
|
isInternal: true,
|
||||||
certificateTemplateId,
|
certificateTemplateId,
|
||||||
csr
|
csr
|
||||||
@@ -188,7 +188,7 @@ export const certificateEstServiceFactory = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { certificate } = await certificateAuthorityService.signCertFromCa({
|
const { certificate } = await internalCertificateAuthorityService.signCertFromCa({
|
||||||
isInternal: true,
|
isInternal: true,
|
||||||
certificateTemplateId,
|
certificateTemplateId,
|
||||||
csr
|
csr
|
||||||
@@ -227,15 +227,15 @@ export const certificateEstServiceFactory = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const ca = await certificateAuthorityDAL.findById(certTemplate.caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(certTemplate.caId);
|
||||||
if (!ca) {
|
if (!ca?.internalCa) {
|
||||||
throw new NotFoundError({
|
throw new NotFoundError({
|
||||||
message: `Certificate Authority with ID '${certTemplate.caId}' not found`
|
message: `Certificate Authority with ID '${certTemplate.caId}' not found`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const { caCert, caCertChain } = await getCaCertChain({
|
const { caCert, caCertChain } = await getCaCertChain({
|
||||||
caCertId: ca.activeCaCertId as string,
|
caCertId: ca.internalCa.activeCaCertId as string,
|
||||||
certificateAuthorityDAL,
|
certificateAuthorityDAL,
|
||||||
certificateAuthorityCertDAL,
|
certificateAuthorityCertDAL,
|
||||||
projectDAL,
|
projectDAL,
|
||||||
|
|||||||
@@ -959,7 +959,7 @@ export const registerRoutes = async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
const certificateEstService = certificateEstServiceFactory({
|
const certificateEstService = certificateEstServiceFactory({
|
||||||
certificateAuthorityService,
|
internalCertificateAuthorityService,
|
||||||
certificateTemplateService,
|
certificateTemplateService,
|
||||||
certificateTemplateDAL,
|
certificateTemplateDAL,
|
||||||
certificateAuthorityCertDAL,
|
certificateAuthorityCertDAL,
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
CertificateAuthoritiesSchema,
|
||||||
DynamicSecretsSchema,
|
DynamicSecretsSchema,
|
||||||
IdentityProjectAdditionalPrivilegeSchema,
|
IdentityProjectAdditionalPrivilegeSchema,
|
||||||
IntegrationAuthsSchema,
|
IntegrationAuthsSchema,
|
||||||
|
InternalCertificateAuthoritiesSchema,
|
||||||
ProjectRolesSchema,
|
ProjectRolesSchema,
|
||||||
ProjectsSchema,
|
ProjectsSchema,
|
||||||
SecretApprovalPoliciesSchema,
|
SecretApprovalPoliciesSchema,
|
||||||
@@ -271,3 +273,7 @@ export const SanitizedTagSchema = SecretTagsSchema.pick({
|
|||||||
}).extend({
|
}).extend({
|
||||||
name: z.string()
|
name: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const InternalCertificateAuthorityResponseSchema = CertificateAuthoritiesSchema.merge(
|
||||||
|
InternalCertificateAuthoritiesSchema
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-floating-promises */
|
/* eslint-disable @typescript-eslint/no-floating-promises */
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { CertificateAuthoritiesSchema, CertificateTemplatesSchema } from "@app/db/schemas";
|
import { CertificateTemplatesSchema } from "@app/db/schemas";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { ApiDocsTags, CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
|
import { ApiDocsTags, CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
@@ -17,6 +17,8 @@ import {
|
|||||||
} from "@app/services/certificate-authority/certificate-authority-validators";
|
} from "@app/services/certificate-authority/certificate-authority-validators";
|
||||||
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||||
|
|
||||||
|
import { InternalCertificateAuthorityResponseSchema } from "../sanitizedSchemas";
|
||||||
|
|
||||||
export const registerCaRouter = async (server: FastifyZodProvider) => {
|
export const registerCaRouter = async (server: FastifyZodProvider) => {
|
||||||
server.route({
|
server.route({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -68,7 +70,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
),
|
),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
ca: CertificateAuthoritiesSchema
|
ca: InternalCertificateAuthorityResponseSchema
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -115,7 +117,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
ca: CertificateAuthoritiesSchema
|
ca: InternalCertificateAuthorityResponseSchema
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -198,7 +200,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
ca: CertificateAuthoritiesSchema
|
ca: InternalCertificateAuthorityResponseSchema
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -247,7 +249,7 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
ca: CertificateAuthoritiesSchema
|
ca: InternalCertificateAuthorityResponseSchema
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const { certificate, certificateChain, issuingCaCertificate, privateKey, serialNumber, ca } =
|
const { certificate, certificateChain, issuingCaCertificate, privateKey, serialNumber, ca } =
|
||||||
await server.services.certificateAuthority.issueCertFromCa({
|
await server.services.internalCertificateAuthority.issueCertFromCa({
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
@@ -355,7 +355,7 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const { certificate, certificateChain, issuingCaCertificate, serialNumber, ca, commonName } =
|
const { certificate, certificateChain, issuingCaCertificate, serialNumber, ca, commonName } =
|
||||||
await server.services.certificateAuthority.signCertFromCa({
|
await server.services.internalCertificateAuthority.signCertFromCa({
|
||||||
isInternal: false,
|
isInternal: false,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CertificateAuthoritiesSchema,
|
|
||||||
CertificatesSchema,
|
CertificatesSchema,
|
||||||
PkiAlertsSchema,
|
PkiAlertsSchema,
|
||||||
PkiCollectionsSchema,
|
PkiCollectionsSchema,
|
||||||
@@ -28,7 +27,7 @@ import { sanitizedPkiSubscriber } from "@app/services/pki-subscriber/pki-subscri
|
|||||||
import { ProjectFilterType } from "@app/services/project/project-types";
|
import { ProjectFilterType } from "@app/services/project/project-types";
|
||||||
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||||
|
|
||||||
import { SanitizedProjectSchema } from "../sanitizedSchemas";
|
import { InternalCertificateAuthorityResponseSchema, SanitizedProjectSchema } from "../sanitizedSchemas";
|
||||||
|
|
||||||
const projectWithEnv = SanitizedProjectSchema.extend({
|
const projectWithEnv = SanitizedProjectSchema.extend({
|
||||||
_id: z.string(),
|
_id: z.string(),
|
||||||
@@ -366,7 +365,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
cas: z.array(CertificateAuthoritiesSchema)
|
cas: z.array(InternalCertificateAuthorityResponseSchema)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import { Knex } from "knex";
|
import { Knex } from "knex";
|
||||||
|
|
||||||
import { TDbClient } from "@app/db";
|
import { TDbClient } from "@app/db";
|
||||||
import { CertificateAuthoritiesSchema, TableName } from "@app/db/schemas";
|
import { CertificateAuthoritiesSchema, TableName, TCertificateAuthorities } from "@app/db/schemas";
|
||||||
import { DatabaseError } from "@app/lib/errors";
|
import { DatabaseError } from "@app/lib/errors";
|
||||||
import { ormify, selectAllTableCols } from "@app/lib/knex";
|
import { ormify, selectAllTableCols, TFindOpt } from "@app/lib/knex";
|
||||||
|
|
||||||
export type TCertificateAuthorityDALFactory = ReturnType<typeof certificateAuthorityDALFactory>;
|
export type TCertificateAuthorityDALFactory = ReturnType<typeof certificateAuthorityDALFactory>;
|
||||||
|
|
||||||
|
export type TCertificateAuthorityWithAssociatedCa = Awaited<
|
||||||
|
ReturnType<TCertificateAuthorityDALFactory["findByIdWithAssociatedCa"]>
|
||||||
|
>;
|
||||||
|
|
||||||
export const certificateAuthorityDALFactory = (db: TDbClient) => {
|
export const certificateAuthorityDALFactory = (db: TDbClient) => {
|
||||||
const caOrm = ormify(db, TableName.CertificateAuthority);
|
const caOrm = ormify(db, TableName.CertificateAuthority);
|
||||||
|
|
||||||
@@ -109,8 +113,91 @@ export const certificateAuthorityDALFactory = (db: TDbClient) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const findWithAssociatedCa = async (
|
||||||
|
filter: Parameters<(typeof caOrm)["find"]>[0] & { dn?: string },
|
||||||
|
{ offset, limit, sort = [["createdAt", "desc"]] }: TFindOpt<TCertificateAuthorities> = {},
|
||||||
|
tx?: Knex
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const query = (tx || db.replicaNode())(TableName.CertificateAuthority)
|
||||||
|
.leftJoin(
|
||||||
|
TableName.InternalCertificateAuthority,
|
||||||
|
`${TableName.CertificateAuthority}.id`,
|
||||||
|
`${TableName.InternalCertificateAuthority}.certificateAuthorityId`
|
||||||
|
)
|
||||||
|
.where(filter)
|
||||||
|
.select(selectAllTableCols(TableName.CertificateAuthority))
|
||||||
|
.select(
|
||||||
|
db.ref("id").withSchema(TableName.InternalCertificateAuthority).as("internalCaId"),
|
||||||
|
db.ref("parentCaId").withSchema(TableName.InternalCertificateAuthority).as("internalParentCaId"),
|
||||||
|
db.ref("type").withSchema(TableName.InternalCertificateAuthority).as("internalType"),
|
||||||
|
db.ref("status").withSchema(TableName.InternalCertificateAuthority).as("internalStatus"),
|
||||||
|
db.ref("friendlyName").withSchema(TableName.InternalCertificateAuthority).as("internalFriendlyName"),
|
||||||
|
db.ref("organization").withSchema(TableName.InternalCertificateAuthority).as("internalOrganization"),
|
||||||
|
db.ref("ou").withSchema(TableName.InternalCertificateAuthority).as("internalOu"),
|
||||||
|
db.ref("country").withSchema(TableName.InternalCertificateAuthority).as("internalCountry"),
|
||||||
|
db.ref("province").withSchema(TableName.InternalCertificateAuthority).as("internalProvince"),
|
||||||
|
db.ref("locality").withSchema(TableName.InternalCertificateAuthority).as("internalLocality"),
|
||||||
|
db.ref("commonName").withSchema(TableName.InternalCertificateAuthority).as("internalCommonName"),
|
||||||
|
db.ref("dn").withSchema(TableName.InternalCertificateAuthority).as("internalDn"),
|
||||||
|
db.ref("serialNumber").withSchema(TableName.InternalCertificateAuthority).as("internalSerialNumber"),
|
||||||
|
db.ref("maxPathLength").withSchema(TableName.InternalCertificateAuthority).as("internalMaxPathLength"),
|
||||||
|
db.ref("keyAlgorithm").withSchema(TableName.InternalCertificateAuthority).as("internalKeyAlgorithm"),
|
||||||
|
db.ref("notBefore").withSchema(TableName.InternalCertificateAuthority).as("internalNotBefore"),
|
||||||
|
db.ref("notAfter").withSchema(TableName.InternalCertificateAuthority).as("internalNotAfter"),
|
||||||
|
db.ref("activeCaCertId").withSchema(TableName.InternalCertificateAuthority).as("internalActiveCaCertId"),
|
||||||
|
db
|
||||||
|
.ref("certificateAuthorityId")
|
||||||
|
.withSchema(TableName.InternalCertificateAuthority)
|
||||||
|
.as("internalCertificateAuthorityId")
|
||||||
|
);
|
||||||
|
|
||||||
|
if (limit) void query.limit(limit);
|
||||||
|
if (offset) void query.offset(offset);
|
||||||
|
if (sort) {
|
||||||
|
void query.orderBy(
|
||||||
|
sort.map(([column, order, nulls]) => ({
|
||||||
|
column,
|
||||||
|
order,
|
||||||
|
nulls
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (await query).map((ca) => ({
|
||||||
|
...CertificateAuthoritiesSchema.parse(ca),
|
||||||
|
internalCa: ca
|
||||||
|
? {
|
||||||
|
id: ca.internalCaId,
|
||||||
|
parentCaId: ca.internalParentCaId,
|
||||||
|
type: ca.internalType,
|
||||||
|
status: ca.internalStatus,
|
||||||
|
friendlyName: ca.internalFriendlyName,
|
||||||
|
organization: ca.internalOrganization,
|
||||||
|
ou: ca.internalOu,
|
||||||
|
country: ca.internalCountry,
|
||||||
|
province: ca.internalProvince,
|
||||||
|
locality: ca.internalLocality,
|
||||||
|
commonName: ca.internalCommonName,
|
||||||
|
dn: ca.internalDn,
|
||||||
|
serialNumber: ca.internalSerialNumber,
|
||||||
|
maxPathLength: ca.internalMaxPathLength,
|
||||||
|
keyAlgorithm: ca.internalKeyAlgorithm,
|
||||||
|
notBefore: ca.internalNotBefore,
|
||||||
|
notAfter: ca.internalNotAfter,
|
||||||
|
activeCaCertId: ca.internalActiveCaCertId,
|
||||||
|
certificateAuthorityId: ca.internalCertificateAuthorityId
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
throw new DatabaseError({ error, name: "Find - Certificate Authority" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...caOrm,
|
...caOrm,
|
||||||
|
findWithAssociatedCa,
|
||||||
buildCertificateChain,
|
buildCertificateChain,
|
||||||
findByIdWithAssociatedCa
|
findByIdWithAssociatedCa
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ export const getCaCredentials = async ({
|
|||||||
projectDAL,
|
projectDAL,
|
||||||
kmsService
|
kmsService
|
||||||
}: TGetCaCredentialsDTO) => {
|
}: TGetCaCredentialsDTO) => {
|
||||||
const ca = await certificateAuthorityDAL.findById(caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId);
|
||||||
if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
if (!ca?.internalCa) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
||||||
|
|
||||||
const caSecret = await certificateAuthoritySecretDAL.findOne({ caId });
|
const caSecret = await certificateAuthoritySecretDAL.findOne({ caId });
|
||||||
if (!caSecret) throw new NotFoundError({ message: `CA secret for CA with ID '${caId}' not found` });
|
if (!caSecret) throw new NotFoundError({ message: `CA secret for CA with ID '${caId}' not found` });
|
||||||
@@ -132,7 +132,7 @@ export const getCaCredentials = async ({
|
|||||||
cipherTextBlob: caSecret.encryptedPrivateKey
|
cipherTextBlob: caSecret.encryptedPrivateKey
|
||||||
});
|
});
|
||||||
|
|
||||||
const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
|
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||||
const skObj = crypto.createPrivateKey({ key: decryptedPrivateKey, format: "der", type: "pkcs8" });
|
const skObj = crypto.createPrivateKey({ key: decryptedPrivateKey, format: "der", type: "pkcs8" });
|
||||||
const caPrivateKey = await crypto.subtle.importKey(
|
const caPrivateKey = await crypto.subtle.importKey(
|
||||||
"pkcs8",
|
"pkcs8",
|
||||||
@@ -256,12 +256,12 @@ export const rebuildCaCrl = async ({
|
|||||||
certificateDAL,
|
certificateDAL,
|
||||||
kmsService
|
kmsService
|
||||||
}: TRebuildCaCrlDTO) => {
|
}: TRebuildCaCrlDTO) => {
|
||||||
const ca = await certificateAuthorityDAL.findById(caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId);
|
||||||
if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
if (!ca?.internalCa) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
||||||
|
|
||||||
const caSecret = await certificateAuthoritySecretDAL.findOne({ caId: ca.id });
|
const caSecret = await certificateAuthoritySecretDAL.findOne({ caId: ca.id });
|
||||||
|
|
||||||
const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
|
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||||
|
|
||||||
const keyId = await getProjectKmsCertificateKeyId({
|
const keyId = await getProjectKmsCertificateKeyId({
|
||||||
projectId: ca.projectId,
|
projectId: ca.projectId,
|
||||||
@@ -288,7 +288,7 @@ export const rebuildCaCrl = async ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const crl = await x509.X509CrlGenerator.create({
|
const crl = await x509.X509CrlGenerator.create({
|
||||||
issuer: ca.dn,
|
issuer: ca.internalCa.dn,
|
||||||
thisUpdate: new Date(),
|
thisUpdate: new Date(),
|
||||||
nextUpdate: new Date("2025/12/12"),
|
nextUpdate: new Date("2025/12/12"),
|
||||||
entries: revokedCerts.map((revokedCert) => {
|
entries: revokedCerts.map((revokedCert) => {
|
||||||
@@ -322,7 +322,12 @@ export const rebuildCaCrl = async ({
|
|||||||
|
|
||||||
export const expandInternalCa = (
|
export const expandInternalCa = (
|
||||||
ca: Awaited<ReturnType<TCertificateAuthorityDALFactory["findByIdWithAssociatedCa"]>>
|
ca: Awaited<ReturnType<TCertificateAuthorityDALFactory["findByIdWithAssociatedCa"]>>
|
||||||
) => ({
|
) => {
|
||||||
...ca,
|
if (!ca.internalCa) {
|
||||||
...ca.internalCa
|
throw new Error("Internal CA must be defined");
|
||||||
});
|
}
|
||||||
|
return {
|
||||||
|
...ca.internalCa,
|
||||||
|
...ca
|
||||||
|
} as const;
|
||||||
|
};
|
||||||
|
|||||||
@@ -75,12 +75,12 @@ export const certificateAuthorityQueueFactory = ({
|
|||||||
const { caId } = job.data;
|
const { caId } = job.data;
|
||||||
logger.info(`secretReminderQueue.process: [secretDocument=${caId}]`);
|
logger.info(`secretReminderQueue.process: [secretDocument=${caId}]`);
|
||||||
|
|
||||||
const ca = await certificateAuthorityDAL.findById(caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId);
|
||||||
if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
if (!ca.internalCa) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
||||||
|
|
||||||
const caSecret = await certificateAuthoritySecretDAL.findOne({ caId: ca.id });
|
const caSecret = await certificateAuthoritySecretDAL.findOne({ caId: ca.id });
|
||||||
|
|
||||||
const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
|
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||||
|
|
||||||
const keyId = await getProjectKmsCertificateKeyId({
|
const keyId = await getProjectKmsCertificateKeyId({
|
||||||
projectId: ca.projectId,
|
projectId: ca.projectId,
|
||||||
@@ -106,7 +106,7 @@ export const certificateAuthorityQueueFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const crl = await x509.X509CrlGenerator.create({
|
const crl = await x509.X509CrlGenerator.create({
|
||||||
issuer: ca.dn,
|
issuer: ca.internalCa.dn,
|
||||||
thisUpdate: new Date(),
|
thisUpdate: new Date(),
|
||||||
nextUpdate: new Date("2025/12/12"), // TODO: depends on configured rebuild interval
|
nextUpdate: new Date("2025/12/12"), // TODO: depends on configured rebuild interval
|
||||||
entries: revokedCerts.map((revokedCert) => {
|
entries: revokedCerts.map((revokedCert) => {
|
||||||
@@ -115,7 +115,7 @@ export const certificateAuthorityQueueFactory = ({
|
|||||||
revocationDate: new Date(revokedCert.revokedAt as Date),
|
revocationDate: new Date(revokedCert.revokedAt as Date),
|
||||||
reason: revokedCert.revocationReason as number,
|
reason: revokedCert.revocationReason as number,
|
||||||
invalidity: new Date("2022/01/01"),
|
invalidity: new Date("2022/01/01"),
|
||||||
issuer: ca.dn
|
issuer: ca.internalCa?.dn
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
signingAlgorithm: alg,
|
signingAlgorithm: alg,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -148,7 +148,7 @@ export type TDNParts = {
|
|||||||
|
|
||||||
export type TGetCaCredentialsDTO = {
|
export type TGetCaCredentialsDTO = {
|
||||||
caId: string;
|
caId: string;
|
||||||
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">;
|
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findByIdWithAssociatedCa">;
|
||||||
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
|
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
|
||||||
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
|
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
|
||||||
kmsService: Pick<TKmsServiceFactory, "decryptWithKmsKey" | "generateKmsKey">;
|
kmsService: Pick<TKmsServiceFactory, "decryptWithKmsKey" | "generateKmsKey">;
|
||||||
@@ -172,7 +172,7 @@ export type TGetCaCertChainDTO = {
|
|||||||
|
|
||||||
export type TRebuildCaCrlDTO = {
|
export type TRebuildCaCrlDTO = {
|
||||||
caId: string;
|
caId: string;
|
||||||
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">;
|
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findByIdWithAssociatedCa">;
|
||||||
certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "update">;
|
certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "update">;
|
||||||
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
|
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
|
||||||
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
|
projectDAL: Pick<TProjectDALFactory, "findOne" | "updateById" | "transaction">;
|
||||||
|
|||||||
+85
-59
@@ -4,7 +4,13 @@ import * as x509 from "@peculiar/x509";
|
|||||||
import crypto, { KeyObject } from "crypto";
|
import crypto, { KeyObject } from "crypto";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { ActionProjectType, ProjectType, TCertificateAuthorities, TCertificateTemplates } from "@app/db/schemas";
|
import {
|
||||||
|
ActionProjectType,
|
||||||
|
ProjectType,
|
||||||
|
TableName,
|
||||||
|
TCertificateAuthorities,
|
||||||
|
TCertificateTemplates
|
||||||
|
} from "@app/db/schemas";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import {
|
import {
|
||||||
ProjectPermissionActions,
|
ProjectPermissionActions,
|
||||||
@@ -36,7 +42,7 @@ import {
|
|||||||
import { TCertificateTemplateDALFactory } from "../certificate-template/certificate-template-dal";
|
import { TCertificateTemplateDALFactory } from "../certificate-template/certificate-template-dal";
|
||||||
import { validateCertificateDetailsAgainstTemplate } from "../certificate-template/certificate-template-fns";
|
import { validateCertificateDetailsAgainstTemplate } from "../certificate-template/certificate-template-fns";
|
||||||
import { TCertificateAuthorityCertDALFactory } from "./certificate-authority-cert-dal";
|
import { TCertificateAuthorityCertDALFactory } from "./certificate-authority-cert-dal";
|
||||||
import { TCertificateAuthorityDALFactory } from "./certificate-authority-dal";
|
import { TCertificateAuthorityDALFactory, TCertificateAuthorityWithAssociatedCa } from "./certificate-authority-dal";
|
||||||
import {
|
import {
|
||||||
createDistinguishedName,
|
createDistinguishedName,
|
||||||
createSerialNumber,
|
createSerialNumber,
|
||||||
@@ -71,7 +77,14 @@ import { TInternalCertificateAuthorityDALFactory } from "./internal-certificate-
|
|||||||
type TInternalCertificateAuthorityServiceFactoryDep = {
|
type TInternalCertificateAuthorityServiceFactoryDep = {
|
||||||
certificateAuthorityDAL: Pick<
|
certificateAuthorityDAL: Pick<
|
||||||
TCertificateAuthorityDALFactory,
|
TCertificateAuthorityDALFactory,
|
||||||
"transaction" | "create" | "findById" | "updateById" | "deleteById" | "findOne" | "findByIdWithAssociatedCa"
|
| "transaction"
|
||||||
|
| "create"
|
||||||
|
| "findById"
|
||||||
|
| "updateById"
|
||||||
|
| "deleteById"
|
||||||
|
| "findOne"
|
||||||
|
| "findByIdWithAssociatedCa"
|
||||||
|
| "findWithAssociatedCa"
|
||||||
>;
|
>;
|
||||||
internalCertificateAuthorityDAL: Pick<
|
internalCertificateAuthorityDAL: Pick<
|
||||||
TInternalCertificateAuthorityDALFactory,
|
TInternalCertificateAuthorityDALFactory,
|
||||||
@@ -371,8 +384,19 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const updatedCa = await certificateAuthorityDAL.transaction(async (tx) => {
|
const updatedCa = await certificateAuthorityDAL.transaction(async (tx) => {
|
||||||
await internalCertificateAuthorityDAL.updateById(caId, { status }, tx);
|
if (status) {
|
||||||
await certificateAuthorityDAL.updateById(ca.id, { disableDirectIssuance: requireTemplateForIssuance }, tx);
|
await internalCertificateAuthorityDAL.update(
|
||||||
|
{
|
||||||
|
certificateAuthorityId: ca.id
|
||||||
|
},
|
||||||
|
{ status },
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requireTemplateForIssuance) {
|
||||||
|
await certificateAuthorityDAL.updateById(ca.id, { disableDirectIssuance: requireTemplateForIssuance }, tx);
|
||||||
|
}
|
||||||
|
|
||||||
return certificateAuthorityDAL.findByIdWithAssociatedCa(caId, tx);
|
return certificateAuthorityDAL.findByIdWithAssociatedCa(caId, tx);
|
||||||
});
|
});
|
||||||
@@ -401,15 +425,9 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
ProjectPermissionSub.CertificateAuthorities
|
ProjectPermissionSub.CertificateAuthorities
|
||||||
);
|
);
|
||||||
|
|
||||||
return certificateAuthorityDAL.transaction(async (tx) => {
|
await certificateAuthorityDAL.deleteById(ca.id);
|
||||||
const deletedInternalCa = await internalCertificateAuthorityDAL.deleteById(caId, tx);
|
|
||||||
const deletedCa = await certificateAuthorityDAL.deleteById(ca.id, tx);
|
|
||||||
|
|
||||||
return {
|
return expandInternalCa(ca);
|
||||||
...deletedCa,
|
|
||||||
...deletedInternalCa
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -466,7 +484,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
csr: csrObj.toString("pem"),
|
csr: csrObj.toString("pem"),
|
||||||
ca
|
ca: expandInternalCa(ca)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -884,8 +902,8 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
maxPathLength
|
maxPathLength
|
||||||
}: TSignIntermediateDTO) => {
|
}: TSignIntermediateDTO) => {
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
const ca = await certificateAuthorityDAL.findById(caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId);
|
||||||
if (!ca) throw new NotFoundError({ message: "CA not found" });
|
if (!ca.internalCa) throw new NotFoundError({ message: "CA not found" });
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -901,16 +919,17 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
ProjectPermissionSub.CertificateAuthorities
|
ProjectPermissionSub.CertificateAuthorities
|
||||||
);
|
);
|
||||||
|
|
||||||
if (ca.status === CaStatus.DISABLED) throw new BadRequestError({ message: "CA is disabled" });
|
if (ca.internalCa.status === CaStatus.DISABLED) throw new BadRequestError({ message: "CA is disabled" });
|
||||||
if (!ca.activeCaCertId) throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
if (!ca.internalCa.activeCaCertId)
|
||||||
|
throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
||||||
|
|
||||||
const caCert = await certificateAuthorityCertDAL.findById(ca.activeCaCertId);
|
const caCert = await certificateAuthorityCertDAL.findById(ca.internalCa.activeCaCertId);
|
||||||
|
|
||||||
if (ca.notAfter && new Date() > new Date(ca.notAfter)) {
|
if (ca.internalCa.notAfter && new Date() > new Date(ca.internalCa.notAfter)) {
|
||||||
throw new BadRequestError({ message: "CA is expired" });
|
throw new BadRequestError({ message: "CA is expired" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
|
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||||
|
|
||||||
const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
|
const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
|
||||||
projectId: ca.projectId,
|
projectId: ca.projectId,
|
||||||
@@ -1001,7 +1020,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { caCert: issuingCaCertificate, caCertChain } = await getCaCertChain({
|
const { caCert: issuingCaCertificate, caCertChain } = await getCaCertChain({
|
||||||
caCertId: ca.activeCaCertId,
|
caCertId: ca.internalCa.activeCaCertId,
|
||||||
certificateAuthorityDAL,
|
certificateAuthorityDAL,
|
||||||
certificateAuthorityCertDAL,
|
certificateAuthorityCertDAL,
|
||||||
projectDAL,
|
projectDAL,
|
||||||
@@ -1013,7 +1032,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
issuingCaCertificate,
|
issuingCaCertificate,
|
||||||
certificateChain: `${issuingCaCertificate}\n${caCertChain}`.trim(),
|
certificateChain: `${issuingCaCertificate}\n${caCertChain}`.trim(),
|
||||||
serialNumber: intermediateCert.serialNumber,
|
serialNumber: intermediateCert.serialNumber,
|
||||||
ca
|
ca: expandInternalCa(ca)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1031,8 +1050,8 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
certificate,
|
certificate,
|
||||||
certificateChain
|
certificateChain
|
||||||
}: TImportCertToCaDTO) => {
|
}: TImportCertToCaDTO) => {
|
||||||
const ca = await certificateAuthorityDAL.findById(caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId);
|
||||||
if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
if (!ca.internalCa) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -1048,7 +1067,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
ProjectPermissionSub.CertificateAuthorities
|
ProjectPermissionSub.CertificateAuthorities
|
||||||
);
|
);
|
||||||
|
|
||||||
if (ca.parentCaId) {
|
if (ca.internalCa.parentCaId) {
|
||||||
/**
|
/**
|
||||||
* re-evaluate in the future if we should allow users to import a new CA certificate for an intermediate
|
* re-evaluate in the future if we should allow users to import a new CA certificate for an intermediate
|
||||||
* CA chained to an internal parent CA. Doing so would allow users to re-chain the CA to a different
|
* CA chained to an internal parent CA. Doing so would allow users to re-chain the CA to a different
|
||||||
@@ -1059,7 +1078,9 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const caCert = ca.activeCaCertId ? await certificateAuthorityCertDAL.findById(ca.activeCaCertId) : undefined;
|
const caCert = ca.internalCa.activeCaCertId
|
||||||
|
? await certificateAuthorityCertDAL.findById(ca.internalCa.activeCaCertId)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const certObj = new x509.X509Certificate(certificate);
|
const certObj = new x509.X509Certificate(certificate);
|
||||||
const maxPathLength = certObj.getExtension(x509.BasicConstraintsExtension)?.pathLength;
|
const maxPathLength = certObj.getExtension(x509.BasicConstraintsExtension)?.pathLength;
|
||||||
@@ -1082,9 +1103,9 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
const parentCertObj = chainItems[1];
|
const parentCertObj = chainItems[1];
|
||||||
const parentCertSubject = parentCertObj.subject;
|
const parentCertSubject = parentCertObj.subject;
|
||||||
|
|
||||||
const parentCa = await certificateAuthorityDAL.findOne({
|
const [parentCa] = await certificateAuthorityDAL.findWithAssociatedCa({
|
||||||
projectId: ca.projectId,
|
[`${TableName.CertificateAuthority}.projectId` as "projectId"]: ca.projectId,
|
||||||
dn: parentCertSubject
|
[`${TableName.InternalCertificateAuthority}.dn` as "dn"]: parentCertSubject
|
||||||
});
|
});
|
||||||
|
|
||||||
const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
|
const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
|
||||||
@@ -1134,8 +1155,10 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
tx
|
tx
|
||||||
);
|
);
|
||||||
|
|
||||||
await certificateAuthorityDAL.updateById(
|
await internalCertificateAuthorityDAL.update(
|
||||||
ca.id,
|
{
|
||||||
|
certificateAuthorityId: ca.id
|
||||||
|
},
|
||||||
{
|
{
|
||||||
status: CaStatus.ACTIVE,
|
status: CaStatus.ACTIVE,
|
||||||
maxPathLength: maxPathLength === undefined ? -1 : maxPathLength,
|
maxPathLength: maxPathLength === undefined ? -1 : maxPathLength,
|
||||||
@@ -1149,7 +1172,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return { ca };
|
return { ca: expandInternalCa(ca) };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1173,12 +1196,12 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
keyUsages,
|
keyUsages,
|
||||||
extendedKeyUsages
|
extendedKeyUsages
|
||||||
}: TIssueCertFromCaDTO) => {
|
}: TIssueCertFromCaDTO) => {
|
||||||
let ca: TCertificateAuthorities | undefined;
|
let ca: TCertificateAuthorityWithAssociatedCa | undefined;
|
||||||
let certificateTemplate: TCertificateTemplates | undefined;
|
let certificateTemplate: TCertificateTemplates | undefined;
|
||||||
let collectionId = pkiCollectionId;
|
let collectionId = pkiCollectionId;
|
||||||
|
|
||||||
if (caId) {
|
if (caId) {
|
||||||
ca = await certificateAuthorityDAL.findById(caId);
|
ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId);
|
||||||
} else if (certificateTemplateId) {
|
} else if (certificateTemplateId) {
|
||||||
certificateTemplate = await certificateTemplateDAL.getById(certificateTemplateId);
|
certificateTemplate = await certificateTemplateDAL.getById(certificateTemplateId);
|
||||||
if (!certificateTemplate) {
|
if (!certificateTemplate) {
|
||||||
@@ -1188,10 +1211,10 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
collectionId = certificateTemplate.pkiCollectionId as string;
|
collectionId = certificateTemplate.pkiCollectionId as string;
|
||||||
ca = await certificateAuthorityDAL.findById(certificateTemplate.caId);
|
ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(certificateTemplate.caId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ca) {
|
if (!ca?.internalCa) {
|
||||||
throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1209,14 +1232,16 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
ProjectPermissionSub.Certificates
|
ProjectPermissionSub.Certificates
|
||||||
);
|
);
|
||||||
|
|
||||||
if (ca.status !== CaStatus.ACTIVE) throw new BadRequestError({ message: "CA is not active" });
|
if (ca.internalCa.status !== CaStatus.ACTIVE) throw new BadRequestError({ message: "CA is not active" });
|
||||||
if (!ca.activeCaCertId) throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
if (!ca.internalCa.activeCaCertId)
|
||||||
if (ca.requireTemplateForIssuance && !certificateTemplate) {
|
throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
||||||
|
if (ca.disableDirectIssuance && !certificateTemplate) {
|
||||||
throw new BadRequestError({ message: "Certificate template is required for issuance" });
|
throw new BadRequestError({ message: "Certificate template is required for issuance" });
|
||||||
}
|
}
|
||||||
const caCert = await certificateAuthorityCertDAL.findById(ca.activeCaCertId);
|
|
||||||
|
|
||||||
if (ca.notAfter && new Date() > new Date(ca.notAfter)) {
|
const caCert = await certificateAuthorityCertDAL.findById(ca.internalCa.activeCaCertId);
|
||||||
|
|
||||||
|
if (ca.internalCa.notAfter && new Date() > new Date(ca.internalCa.notAfter)) {
|
||||||
throw new BadRequestError({ message: "CA is expired" });
|
throw new BadRequestError({ message: "CA is expired" });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1266,7 +1291,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
throw new BadRequestError({ message: "notAfter date is after CA certificate's notAfter date" });
|
throw new BadRequestError({ message: "notAfter date is after CA certificate's notAfter date" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
|
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||||
const leafKeys = await crypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
const leafKeys = await crypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||||
|
|
||||||
const csrObj = await x509.Pkcs10CertificateRequestGenerator.create({
|
const csrObj = await x509.Pkcs10CertificateRequestGenerator.create({
|
||||||
@@ -1496,7 +1521,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
issuingCaCertificate,
|
issuingCaCertificate,
|
||||||
privateKey: skLeaf,
|
privateKey: skLeaf,
|
||||||
serialNumber,
|
serialNumber,
|
||||||
ca
|
ca: expandInternalCa(ca)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1506,7 +1531,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
*/
|
*/
|
||||||
const signCertFromCa = async (dto: TSignCertFromCaDTO) => {
|
const signCertFromCa = async (dto: TSignCertFromCaDTO) => {
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
let ca: TCertificateAuthorities | undefined;
|
let ca: TCertificateAuthorityWithAssociatedCa | undefined;
|
||||||
let certificateTemplate: TCertificateTemplates | undefined;
|
let certificateTemplate: TCertificateTemplates | undefined;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -1527,7 +1552,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
let collectionId = pkiCollectionId;
|
let collectionId = pkiCollectionId;
|
||||||
|
|
||||||
if (caId) {
|
if (caId) {
|
||||||
ca = await certificateAuthorityDAL.findById(caId);
|
ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId);
|
||||||
} else if (certificateTemplateId) {
|
} else if (certificateTemplateId) {
|
||||||
certificateTemplate = await certificateTemplateDAL.getById(certificateTemplateId);
|
certificateTemplate = await certificateTemplateDAL.getById(certificateTemplateId);
|
||||||
if (!certificateTemplate) {
|
if (!certificateTemplate) {
|
||||||
@@ -1537,10 +1562,10 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
collectionId = certificateTemplate.pkiCollectionId as string;
|
collectionId = certificateTemplate.pkiCollectionId as string;
|
||||||
ca = await certificateAuthorityDAL.findById(certificateTemplate.caId);
|
ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(certificateTemplate.caId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ca) {
|
if (!ca?.internalCa) {
|
||||||
throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1560,15 +1585,16 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ca.status !== CaStatus.ACTIVE) throw new BadRequestError({ message: "CA is not active" });
|
if (ca.internalCa.status !== CaStatus.ACTIVE) throw new BadRequestError({ message: "CA is not active" });
|
||||||
if (!ca.activeCaCertId) throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
if (!ca.internalCa.activeCaCertId)
|
||||||
if (ca.requireTemplateForIssuance && !certificateTemplate) {
|
throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
||||||
|
if (ca.disableDirectIssuance && !certificateTemplate) {
|
||||||
throw new BadRequestError({ message: "Certificate template is required for issuance" });
|
throw new BadRequestError({ message: "Certificate template is required for issuance" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const caCert = await certificateAuthorityCertDAL.findById(ca.activeCaCertId);
|
const caCert = await certificateAuthorityCertDAL.findById(ca.internalCa.activeCaCertId);
|
||||||
|
|
||||||
if (ca.notAfter && new Date() > new Date(ca.notAfter)) {
|
if (ca.internalCa.notAfter && new Date() > new Date(ca.internalCa.notAfter)) {
|
||||||
throw new BadRequestError({ message: "CA is expired" });
|
throw new BadRequestError({ message: "CA is expired" });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1621,7 +1647,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
throw new BadRequestError({ message: "notAfter date is after CA certificate's notAfter date" });
|
throw new BadRequestError({ message: "notAfter date is after CA certificate's notAfter date" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
|
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||||
|
|
||||||
const csrObj = new x509.Pkcs10CertificateRequest(csr);
|
const csrObj = new x509.Pkcs10CertificateRequest(csr);
|
||||||
|
|
||||||
@@ -1874,7 +1900,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { caCert: issuingCaCertificate, caCertChain } = await getCaCertChain({
|
const { caCert: issuingCaCertificate, caCertChain } = await getCaCertChain({
|
||||||
caCertId: ca.activeCaCertId,
|
caCertId: ca.internalCa.activeCaCertId,
|
||||||
certificateAuthorityDAL,
|
certificateAuthorityDAL,
|
||||||
certificateAuthorityCertDAL,
|
certificateAuthorityCertDAL,
|
||||||
projectDAL,
|
projectDAL,
|
||||||
@@ -1886,7 +1912,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
certificateChain: `${issuingCaCertificate}\n${caCertChain}`.trim(),
|
certificateChain: `${issuingCaCertificate}\n${caCertChain}`.trim(),
|
||||||
issuingCaCertificate,
|
issuingCaCertificate,
|
||||||
serialNumber,
|
serialNumber,
|
||||||
ca,
|
ca: expandInternalCa(ca),
|
||||||
commonName: cn
|
commonName: cn
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -1901,8 +1927,8 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
actor,
|
actor,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
}: TGetCaCertificateTemplatesDTO) => {
|
}: TGetCaCertificateTemplatesDTO) => {
|
||||||
const ca = await certificateAuthorityDAL.findById(caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(caId);
|
||||||
if (!ca) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
if (!ca?.internalCa) throw new NotFoundError({ message: `CA with ID '${caId}' not found` });
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -1922,7 +1948,7 @@ export const internalCertificateAuthorityServiceFactory = ({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
certificateTemplates,
|
certificateTemplates,
|
||||||
ca
|
ca: expandInternalCa(ca)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,15 @@ export const certificateTemplateDALFactory = (db: TDbClient) => {
|
|||||||
`${TableName.CertificateAuthority}.id`,
|
`${TableName.CertificateAuthority}.id`,
|
||||||
`${TableName.CertificateTemplate}.caId`
|
`${TableName.CertificateTemplate}.caId`
|
||||||
)
|
)
|
||||||
|
.join(
|
||||||
|
TableName.InternalCertificateAuthority,
|
||||||
|
`${TableName.InternalCertificateAuthority}.certificateAuthorityId`,
|
||||||
|
`${TableName.CertificateAuthority}.id`
|
||||||
|
)
|
||||||
.where(`${TableName.CertificateAuthority}.projectId`, "=", projectId)
|
.where(`${TableName.CertificateAuthority}.projectId`, "=", projectId)
|
||||||
.select(selectAllTableCols(TableName.CertificateTemplate))
|
.select(selectAllTableCols(TableName.CertificateTemplate))
|
||||||
.select(
|
.select(
|
||||||
db.ref("friendlyName").as("caName").withSchema(TableName.CertificateAuthority),
|
db.ref("friendlyName").as("caName").withSchema(TableName.InternalCertificateAuthority),
|
||||||
db.ref("projectId").withSchema(TableName.CertificateAuthority)
|
db.ref("projectId").withSchema(TableName.CertificateAuthority)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -41,11 +46,16 @@ export const certificateTemplateDALFactory = (db: TDbClient) => {
|
|||||||
`${TableName.CertificateTemplate}.caId`
|
`${TableName.CertificateTemplate}.caId`
|
||||||
)
|
)
|
||||||
.join(TableName.Project, `${TableName.Project}.id`, `${TableName.CertificateAuthority}.projectId`)
|
.join(TableName.Project, `${TableName.Project}.id`, `${TableName.CertificateAuthority}.projectId`)
|
||||||
|
.join(
|
||||||
|
TableName.InternalCertificateAuthority,
|
||||||
|
`${TableName.InternalCertificateAuthority}.certificateAuthorityId`,
|
||||||
|
`${TableName.CertificateAuthority}.id`
|
||||||
|
)
|
||||||
.where(`${TableName.CertificateTemplate}.id`, "=", id)
|
.where(`${TableName.CertificateTemplate}.id`, "=", id)
|
||||||
.select(selectAllTableCols(TableName.CertificateTemplate))
|
.select(selectAllTableCols(TableName.CertificateTemplate))
|
||||||
.select(
|
.select(
|
||||||
db.ref("projectId").withSchema(TableName.CertificateAuthority),
|
db.ref("projectId").withSchema(TableName.CertificateAuthority),
|
||||||
db.ref("friendlyName").as("caName").withSchema(TableName.CertificateAuthority),
|
db.ref("friendlyName").as("caName").withSchema(TableName.InternalCertificateAuthority),
|
||||||
db.ref("orgId").withSchema(TableName.Project)
|
db.ref("orgId").withSchema(TableName.Project)
|
||||||
)
|
)
|
||||||
.first();
|
.first();
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
|||||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns";
|
import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns";
|
||||||
|
|
||||||
import { getCaCertChain, rebuildCaCrl } from "../certificate-authority/certificate-authority-fns";
|
import { expandInternalCa, getCaCertChain, rebuildCaCrl } from "../certificate-authority/certificate-authority-fns";
|
||||||
import { buildCertificateChain, getCertificateCredentials, revocationReasonToCrlCode } from "./certificate-fns";
|
import { buildCertificateChain, getCertificateCredentials, revocationReasonToCrlCode } from "./certificate-fns";
|
||||||
import { TCertificateSecretDALFactory } from "./certificate-secret-dal";
|
import { TCertificateSecretDALFactory } from "./certificate-secret-dal";
|
||||||
import {
|
import {
|
||||||
@@ -34,7 +34,7 @@ type TCertificateServiceFactoryDep = {
|
|||||||
certificateDAL: Pick<TCertificateDALFactory, "findOne" | "deleteById" | "update" | "find">;
|
certificateDAL: Pick<TCertificateDALFactory, "findOne" | "deleteById" | "update" | "find">;
|
||||||
certificateSecretDAL: Pick<TCertificateSecretDALFactory, "findOne">;
|
certificateSecretDAL: Pick<TCertificateSecretDALFactory, "findOne">;
|
||||||
certificateBodyDAL: Pick<TCertificateBodyDALFactory, "findOne">;
|
certificateBodyDAL: Pick<TCertificateBodyDALFactory, "findOne">;
|
||||||
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">;
|
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById" | "findByIdWithAssociatedCa">;
|
||||||
certificateAuthorityCertDAL: Pick<TCertificateAuthorityCertDALFactory, "findById">;
|
certificateAuthorityCertDAL: Pick<TCertificateAuthorityCertDALFactory, "findById">;
|
||||||
certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "update">;
|
certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "update">;
|
||||||
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
|
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
|
||||||
@@ -62,7 +62,7 @@ export const certificateServiceFactory = ({
|
|||||||
*/
|
*/
|
||||||
const getCert = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertDTO) => {
|
const getCert = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertDTO) => {
|
||||||
const cert = await certificateDAL.findOne({ serialNumber });
|
const cert = await certificateDAL.findOne({ serialNumber });
|
||||||
const ca = await certificateAuthorityDAL.findById(cert.caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(cert.caId);
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -80,7 +80,7 @@ export const certificateServiceFactory = ({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
cert,
|
cert,
|
||||||
ca
|
ca: expandInternalCa(ca)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ export const certificateServiceFactory = ({
|
|||||||
actorOrgId
|
actorOrgId
|
||||||
}: TGetCertPrivateKeyDTO) => {
|
}: TGetCertPrivateKeyDTO) => {
|
||||||
const cert = await certificateDAL.findOne({ serialNumber });
|
const cert = await certificateDAL.findOne({ serialNumber });
|
||||||
const ca = await certificateAuthorityDAL.findById(cert.caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(cert.caId);
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -120,7 +120,7 @@ export const certificateServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ca,
|
ca: expandInternalCa(ca),
|
||||||
cert,
|
cert,
|
||||||
certPrivateKey
|
certPrivateKey
|
||||||
};
|
};
|
||||||
@@ -131,7 +131,7 @@ export const certificateServiceFactory = ({
|
|||||||
*/
|
*/
|
||||||
const deleteCert = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TDeleteCertDTO) => {
|
const deleteCert = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TDeleteCertDTO) => {
|
||||||
const cert = await certificateDAL.findOne({ serialNumber });
|
const cert = await certificateDAL.findOne({ serialNumber });
|
||||||
const ca = await certificateAuthorityDAL.findById(cert.caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(cert.caId);
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -151,7 +151,7 @@ export const certificateServiceFactory = ({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
deletedCert,
|
deletedCert,
|
||||||
ca
|
ca: expandInternalCa(ca)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -169,7 +169,7 @@ export const certificateServiceFactory = ({
|
|||||||
actorOrgId
|
actorOrgId
|
||||||
}: TRevokeCertDTO) => {
|
}: TRevokeCertDTO) => {
|
||||||
const cert = await certificateDAL.findOne({ serialNumber });
|
const cert = await certificateDAL.findOne({ serialNumber });
|
||||||
const ca = await certificateAuthorityDAL.findById(cert.caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(cert.caId);
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -210,7 +210,7 @@ export const certificateServiceFactory = ({
|
|||||||
kmsService
|
kmsService
|
||||||
});
|
});
|
||||||
|
|
||||||
return { revokedAt, cert, ca };
|
return { revokedAt, cert, ca: expandInternalCa(ca) };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -219,7 +219,7 @@ export const certificateServiceFactory = ({
|
|||||||
*/
|
*/
|
||||||
const getCertBody = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertBodyDTO) => {
|
const getCertBody = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertBodyDTO) => {
|
||||||
const cert = await certificateDAL.findOne({ serialNumber });
|
const cert = await certificateDAL.findOne({ serialNumber });
|
||||||
const ca = await certificateAuthorityDAL.findById(cert.caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(cert.caId);
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -273,7 +273,7 @@ export const certificateServiceFactory = ({
|
|||||||
certificateChain,
|
certificateChain,
|
||||||
serialNumber: certObj.serialNumber,
|
serialNumber: certObj.serialNumber,
|
||||||
cert,
|
cert,
|
||||||
ca
|
ca: expandInternalCa(ca)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -283,7 +283,7 @@ export const certificateServiceFactory = ({
|
|||||||
*/
|
*/
|
||||||
const getCertBundle = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertBundleDTO) => {
|
const getCertBundle = async ({ serialNumber, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertBundleDTO) => {
|
||||||
const cert = await certificateDAL.findOne({ serialNumber });
|
const cert = await certificateDAL.findOne({ serialNumber });
|
||||||
const ca = await certificateAuthorityDAL.findById(cert.caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(cert.caId);
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -351,7 +351,7 @@ export const certificateServiceFactory = ({
|
|||||||
privateKey: certPrivateKey,
|
privateKey: certPrivateKey,
|
||||||
serialNumber,
|
serialNumber,
|
||||||
cert,
|
cert,
|
||||||
ca
|
ca: expandInternalCa(ca)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import { TCertificateAuthorityCertDALFactory } from "@app/services/certificate-a
|
|||||||
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
import { TCertificateAuthorityDALFactory } from "@app/services/certificate-authority/certificate-authority-dal";
|
||||||
import {
|
import {
|
||||||
createSerialNumber,
|
createSerialNumber,
|
||||||
|
expandInternalCa,
|
||||||
getCaCertChain,
|
getCaCertChain,
|
||||||
getCaCredentials,
|
getCaCredentials,
|
||||||
keyAlgorithmToAlgCfg,
|
keyAlgorithmToAlgCfg,
|
||||||
@@ -57,7 +58,7 @@ type TPkiSubscriberServiceFactoryDep = {
|
|||||||
TPkiSubscriberDALFactory,
|
TPkiSubscriberDALFactory,
|
||||||
"create" | "findById" | "updateById" | "deleteById" | "transaction" | "find" | "findOne"
|
"create" | "findById" | "updateById" | "deleteById" | "transaction" | "find" | "findOne"
|
||||||
>;
|
>;
|
||||||
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findById">;
|
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "findByIdWithAssociatedCa" | "findById">;
|
||||||
certificateAuthorityCertDAL: Pick<TCertificateAuthorityCertDALFactory, "findById">;
|
certificateAuthorityCertDAL: Pick<TCertificateAuthorityCertDALFactory, "findById">;
|
||||||
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
|
certificateAuthoritySecretDAL: Pick<TCertificateAuthoritySecretDALFactory, "findOne">;
|
||||||
certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "findOne">;
|
certificateAuthorityCrlDAL: Pick<TCertificateAuthorityCrlDALFactory, "findOne">;
|
||||||
@@ -266,8 +267,8 @@ export const pkiSubscriberServiceFactory = ({
|
|||||||
if (!subscriber) throw new NotFoundError({ message: `PKI subscriber named '${subscriberName}' not found` });
|
if (!subscriber) throw new NotFoundError({ message: `PKI subscriber named '${subscriberName}' not found` });
|
||||||
if (!subscriber.caId) throw new BadRequestError({ message: "Subscriber does not have an assigned issuing CA" });
|
if (!subscriber.caId) throw new BadRequestError({ message: "Subscriber does not have an assigned issuing CA" });
|
||||||
|
|
||||||
const ca = await certificateAuthorityDAL.findById(subscriber.caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(subscriber.caId);
|
||||||
if (!ca) throw new NotFoundError({ message: `CA with ID '${subscriber.caId}' not found` });
|
if (!ca?.internalCa) throw new NotFoundError({ message: `CA with ID '${subscriber.caId}' not found` });
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -287,12 +288,13 @@ export const pkiSubscriberServiceFactory = ({
|
|||||||
|
|
||||||
if (subscriber.status !== PkiSubscriberStatus.ACTIVE)
|
if (subscriber.status !== PkiSubscriberStatus.ACTIVE)
|
||||||
throw new BadRequestError({ message: "Subscriber is not active" });
|
throw new BadRequestError({ message: "Subscriber is not active" });
|
||||||
if (ca.status !== CaStatus.ACTIVE) throw new BadRequestError({ message: "CA is not active" });
|
if (ca.internalCa?.status !== CaStatus.ACTIVE) throw new BadRequestError({ message: "CA is not active" });
|
||||||
if (!ca.activeCaCertId) throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
if (!ca.internalCa?.activeCaCertId)
|
||||||
if (ca.requireTemplateForIssuance) {
|
throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
||||||
|
if (ca.disableDirectIssuance) {
|
||||||
throw new BadRequestError({ message: "Certificate template is required for issuance" });
|
throw new BadRequestError({ message: "Certificate template is required for issuance" });
|
||||||
}
|
}
|
||||||
const caCert = await certificateAuthorityCertDAL.findById(ca.activeCaCertId);
|
const caCert = await certificateAuthorityCertDAL.findById(ca.internalCa.activeCaCertId);
|
||||||
|
|
||||||
const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
|
const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
|
||||||
projectId: ca.projectId,
|
projectId: ca.projectId,
|
||||||
@@ -323,7 +325,7 @@ export const pkiSubscriberServiceFactory = ({
|
|||||||
throw new BadRequestError({ message: "notAfter date is after CA certificate's notAfter date" });
|
throw new BadRequestError({ message: "notAfter date is after CA certificate's notAfter date" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
|
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||||
const leafKeys = await crypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
const leafKeys = await crypto.subtle.generateKey(alg, true, ["sign", "verify"]);
|
||||||
|
|
||||||
const csrObj = await x509.Pkcs10CertificateRequestGenerator.create({
|
const csrObj = await x509.Pkcs10CertificateRequestGenerator.create({
|
||||||
@@ -500,8 +502,8 @@ export const pkiSubscriberServiceFactory = ({
|
|||||||
if (!subscriber) throw new NotFoundError({ message: `PKI subscriber named '${subscriberName}' not found` });
|
if (!subscriber) throw new NotFoundError({ message: `PKI subscriber named '${subscriberName}' not found` });
|
||||||
if (!subscriber.caId) throw new BadRequestError({ message: "Subscriber does not have an assigned issuing CA" });
|
if (!subscriber.caId) throw new BadRequestError({ message: "Subscriber does not have an assigned issuing CA" });
|
||||||
|
|
||||||
const ca = await certificateAuthorityDAL.findById(subscriber.caId);
|
const ca = await certificateAuthorityDAL.findByIdWithAssociatedCa(subscriber.caId);
|
||||||
if (!ca) throw new NotFoundError({ message: `CA with ID '${subscriber.caId}' not found` });
|
if (!ca?.internalCa) throw new NotFoundError({ message: `CA with ID '${subscriber.caId}' not found` });
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission({
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
actor,
|
actor,
|
||||||
@@ -521,12 +523,13 @@ export const pkiSubscriberServiceFactory = ({
|
|||||||
|
|
||||||
if (subscriber.status !== PkiSubscriberStatus.ACTIVE)
|
if (subscriber.status !== PkiSubscriberStatus.ACTIVE)
|
||||||
throw new BadRequestError({ message: "Subscriber is not active" });
|
throw new BadRequestError({ message: "Subscriber is not active" });
|
||||||
if (ca.status !== CaStatus.ACTIVE) throw new BadRequestError({ message: "CA is not active" });
|
if (ca.internalCa?.status !== CaStatus.ACTIVE) throw new BadRequestError({ message: "CA is not active" });
|
||||||
if (!ca.activeCaCertId) throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
if (!ca.internalCa?.activeCaCertId)
|
||||||
if (ca.requireTemplateForIssuance) {
|
throw new BadRequestError({ message: "CA does not have a certificate installed" });
|
||||||
|
if (ca.disableDirectIssuance) {
|
||||||
throw new BadRequestError({ message: "Certificate template is required for issuance" });
|
throw new BadRequestError({ message: "Certificate template is required for issuance" });
|
||||||
}
|
}
|
||||||
const caCert = await certificateAuthorityCertDAL.findById(ca.activeCaCertId);
|
const caCert = await certificateAuthorityCertDAL.findById(ca.internalCa.activeCaCertId);
|
||||||
|
|
||||||
const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
|
const certificateManagerKmsId = await getProjectKmsCertificateKeyId({
|
||||||
projectId: ca.projectId,
|
projectId: ca.projectId,
|
||||||
@@ -557,7 +560,7 @@ export const pkiSubscriberServiceFactory = ({
|
|||||||
throw new BadRequestError({ message: "notAfter date is after CA certificate's notAfter date" });
|
throw new BadRequestError({ message: "notAfter date is after CA certificate's notAfter date" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
|
const alg = keyAlgorithmToAlgCfg(ca.internalCa.keyAlgorithm as CertKeyAlgorithm);
|
||||||
|
|
||||||
const csrObj = new x509.Pkcs10CertificateRequest(csr);
|
const csrObj = new x509.Pkcs10CertificateRequest(csr);
|
||||||
|
|
||||||
@@ -691,7 +694,7 @@ export const pkiSubscriberServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { caCert: issuingCaCertificate, caCertChain } = await getCaCertChain({
|
const { caCert: issuingCaCertificate, caCertChain } = await getCaCertChain({
|
||||||
caCertId: ca.activeCaCertId,
|
caCertId: ca.internalCa.activeCaCertId,
|
||||||
certificateAuthorityDAL,
|
certificateAuthorityDAL,
|
||||||
certificateAuthorityCertDAL,
|
certificateAuthorityCertDAL,
|
||||||
projectDAL,
|
projectDAL,
|
||||||
@@ -740,7 +743,7 @@ export const pkiSubscriberServiceFactory = ({
|
|||||||
certificateChain: `${issuingCaCertificate}\n${caCertChain}`.trim(),
|
certificateChain: `${issuingCaCertificate}\n${caCertChain}`.trim(),
|
||||||
issuingCaCertificate,
|
issuingCaCertificate,
|
||||||
serialNumber,
|
serialNumber,
|
||||||
ca,
|
ca: expandInternalCa(ca),
|
||||||
commonName: subscriber.commonName,
|
commonName: subscriber.commonName,
|
||||||
subscriber
|
subscriber
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
ProjectMembershipRole,
|
ProjectMembershipRole,
|
||||||
ProjectType,
|
ProjectType,
|
||||||
ProjectVersion,
|
ProjectVersion,
|
||||||
|
TableName,
|
||||||
TProjectEnvironments
|
TProjectEnvironments
|
||||||
} from "@app/db/schemas";
|
} from "@app/db/schemas";
|
||||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
@@ -41,6 +42,7 @@ import { TPkiSubscriberDALFactory } from "@app/services/pki-subscriber/pki-subsc
|
|||||||
import { ActorType } from "../auth/auth-type";
|
import { ActorType } from "../auth/auth-type";
|
||||||
import { TCertificateDALFactory } from "../certificate/certificate-dal";
|
import { TCertificateDALFactory } from "../certificate/certificate-dal";
|
||||||
import { TCertificateAuthorityDALFactory } from "../certificate-authority/certificate-authority-dal";
|
import { TCertificateAuthorityDALFactory } from "../certificate-authority/certificate-authority-dal";
|
||||||
|
import { expandInternalCa } from "../certificate-authority/certificate-authority-fns";
|
||||||
import { TCertificateTemplateDALFactory } from "../certificate-template/certificate-template-dal";
|
import { TCertificateTemplateDALFactory } from "../certificate-template/certificate-template-dal";
|
||||||
import { TGroupProjectDALFactory } from "../group-project/group-project-dal";
|
import { TGroupProjectDALFactory } from "../group-project/group-project-dal";
|
||||||
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
||||||
@@ -149,7 +151,7 @@ type TProjectServiceFactoryDep = {
|
|||||||
>;
|
>;
|
||||||
projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "create">;
|
projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "create">;
|
||||||
pkiSubscriberDAL: Pick<TPkiSubscriberDALFactory, "find">;
|
pkiSubscriberDAL: Pick<TPkiSubscriberDALFactory, "find">;
|
||||||
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "find">;
|
certificateAuthorityDAL: Pick<TCertificateAuthorityDALFactory, "find" | "findWithAssociatedCa">;
|
||||||
certificateDAL: Pick<TCertificateDALFactory, "find" | "countCertificatesInProject">;
|
certificateDAL: Pick<TCertificateDALFactory, "find" | "countCertificatesInProject">;
|
||||||
certificateTemplateDAL: Pick<TCertificateTemplateDALFactory, "getCertTemplatesByProjectId">;
|
certificateTemplateDAL: Pick<TCertificateTemplateDALFactory, "getCertTemplatesByProjectId">;
|
||||||
pkiAlertDAL: Pick<TPkiAlertDALFactory, "find">;
|
pkiAlertDAL: Pick<TPkiAlertDALFactory, "find">;
|
||||||
@@ -913,17 +915,19 @@ export const projectServiceFactory = ({
|
|||||||
ProjectPermissionSub.CertificateAuthorities
|
ProjectPermissionSub.CertificateAuthorities
|
||||||
);
|
);
|
||||||
|
|
||||||
const cas = await certificateAuthorityDAL.find(
|
const cas = await certificateAuthorityDAL.findWithAssociatedCa(
|
||||||
{
|
{
|
||||||
projectId,
|
[`${TableName.CertificateAuthority}.projectId` as "projectId"]: projectId,
|
||||||
...(status && { status }),
|
...(status && { [`${TableName.InternalCertificateAuthority}.status` as "status"]: status }),
|
||||||
...(friendlyName && { friendlyName }),
|
...(friendlyName && {
|
||||||
...(commonName && { commonName })
|
[`${TableName.InternalCertificateAuthority}.friendlyName` as "friendlyName"]: friendlyName
|
||||||
|
}),
|
||||||
|
...(commonName && { [`${TableName.InternalCertificateAuthority}.commonName` as "commonName"]: commonName })
|
||||||
},
|
},
|
||||||
{ offset, limit, sort: [["updatedAt", "desc"]] }
|
{ offset, limit, sort: [["updatedAt", "desc"]] }
|
||||||
);
|
);
|
||||||
|
|
||||||
return cas;
|
return cas.map((ca) => expandInternalCa(ca));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user