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