mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-16 05:13:43 +00:00
Add preliminary dynamically generated CRLs on fetching CA CRL
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { CertKeyAlgorithm, TDNParts } from "./certificate-authority-types";
|
||||
import { CertKeyAlgorithm } from "../certificate/certificate-types";
|
||||
import { TDNParts } from "./certificate-authority-types";
|
||||
|
||||
export const createDistinguishedName = (parts: TDNParts) => {
|
||||
const dnParts = [];
|
||||
|
||||
@@ -10,7 +10,7 @@ import { TCertificateCertDALFactory } from "@app/services/certificate/certificat
|
||||
import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal";
|
||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
|
||||
import { TCertStatus } from "../certificate/certificate-types";
|
||||
import { CertKeyAlgorithm, CertStatus } from "../certificate/certificate-types";
|
||||
import { TCertificateAuthorityCertDALFactory } from "./certificate-authority-cert-dal";
|
||||
import { TCertificateAuthorityDALFactory } from "./certificate-authority-dal";
|
||||
import { createDistinguishedName, keyAlgorithmToAlgCfg } from "./certificate-authority-fns";
|
||||
@@ -18,12 +18,12 @@ import { TCertificateAuthoritySkDALFactory } from "./certificate-authority-sk-da
|
||||
import {
|
||||
CaStatus,
|
||||
CaType,
|
||||
CertKeyAlgorithm,
|
||||
TCreateCaDTO,
|
||||
TDeleteCaDTO,
|
||||
TGetCaCertDTO,
|
||||
TGetCaCsrDTO,
|
||||
TGetCaDTO,
|
||||
TGetCrl,
|
||||
TImportCertToCaDTO,
|
||||
TIssueCertFromCaDTO,
|
||||
TSignIntermediateDTO,
|
||||
@@ -37,7 +37,7 @@ type TCertificateAuthorityServiceFactoryDep = {
|
||||
>;
|
||||
certificateAuthorityCertDAL: Pick<TCertificateAuthorityCertDALFactory, "create" | "findOne" | "transaction">;
|
||||
certificateAuthoritySkDAL: Pick<TCertificateAuthoritySkDALFactory, "create" | "findOne">;
|
||||
certificateDAL: Pick<TCertificateDALFactory, "transaction" | "create">;
|
||||
certificateDAL: Pick<TCertificateDALFactory, "transaction" | "create" | "find">;
|
||||
certificateCertDAL: Pick<TCertificateCertDALFactory, "create">;
|
||||
projectDAL: Pick<TProjectDALFactory, "findProjectBySlug">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||
@@ -633,7 +633,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
const cert = await certificateDAL.create(
|
||||
{
|
||||
caId: ca.id,
|
||||
status: TCertStatus.ACTIVE,
|
||||
status: CertStatus.ACTIVE,
|
||||
commonName,
|
||||
serialNumber,
|
||||
notBefore: notBeforeDate,
|
||||
@@ -663,6 +663,64 @@ export const certificateAuthorityServiceFactory = ({
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the Certificate Revocation List (CRL) for the CA
|
||||
*/
|
||||
const getCaCrl = async ({ caId, actorId, actorAuthMethod, actor, actorOrgId }: TGetCrl) => {
|
||||
const ca = await certificateAuthorityDAL.findById(caId);
|
||||
if (!ca) throw new BadRequestError({ message: "CA not found" });
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
ca.projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
ProjectPermissionSub.CertificateAuthorities
|
||||
);
|
||||
|
||||
const caKeys = await certificateAuthoritySkDAL.findOne({ caId: ca.id });
|
||||
|
||||
const alg = keyAlgorithmToAlgCfg(ca.keyAlgorithm as CertKeyAlgorithm);
|
||||
const skObj = crypto.createPrivateKey({ key: caKeys.sk, format: "pem", type: "pkcs8" });
|
||||
const sk = await crypto.subtle.importKey("pkcs8", skObj.export({ format: "der", type: "pkcs8" }), alg, true, [
|
||||
"sign"
|
||||
]);
|
||||
|
||||
const revokedCerts = await certificateDAL.find({
|
||||
caId: ca.id,
|
||||
status: CertStatus.REVOKED
|
||||
});
|
||||
|
||||
const crl = await x509.X509CrlGenerator.create({
|
||||
issuer: ca.dn,
|
||||
thisUpdate: new Date(),
|
||||
nextUpdate: new Date("2025/12/12"),
|
||||
entries: revokedCerts.map((revokedCert) => {
|
||||
return {
|
||||
serialNumber: revokedCert.serialNumber,
|
||||
revocationDate: new Date(revokedCert.revokedAt as Date),
|
||||
reason: revokedCert.revocationReason as number,
|
||||
invalidity: new Date("2022/01/01"),
|
||||
issuer: ca.dn
|
||||
};
|
||||
}),
|
||||
signingAlgorithm: alg,
|
||||
signingKey: sk
|
||||
});
|
||||
|
||||
const base64crl = crl.toString("base64");
|
||||
const crlPem = `-----BEGIN X509 CRL-----\n${base64crl.match(/.{1,64}/g)?.join("\n")}\n-----END X509 CRL-----`;
|
||||
|
||||
return {
|
||||
crl: crlPem
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
createCa,
|
||||
getCaById,
|
||||
@@ -672,6 +730,7 @@ export const certificateAuthorityServiceFactory = ({
|
||||
getCaCert,
|
||||
signIntermediate,
|
||||
importCertToCa,
|
||||
issueCertFromCa
|
||||
issueCertFromCa,
|
||||
getCaCrl
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { TProjectPermission } from "@app/lib/types";
|
||||
|
||||
import { CertKeyAlgorithm } from "../certificate/certificate-types";
|
||||
|
||||
export enum CaType {
|
||||
ROOT = "root",
|
||||
INTERMEDIATE = "intermediate"
|
||||
@@ -11,13 +13,6 @@ export enum CaStatus {
|
||||
PENDING_CERTIFICATE = "pending-certificate"
|
||||
}
|
||||
|
||||
export enum CertKeyAlgorithm {
|
||||
RSA_2048 = "RSA_2048",
|
||||
RSA_4096 = "RSA_4096",
|
||||
ECDSA_P256 = "EC_prime256v1",
|
||||
ECDSA_P384 = "EC_secp384r1"
|
||||
}
|
||||
|
||||
export type TCreateCaDTO = {
|
||||
projectSlug: string;
|
||||
type: CaType;
|
||||
@@ -76,6 +71,10 @@ export type TIssueCertFromCaDTO = {
|
||||
notAfter?: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TGetCrl = {
|
||||
caId: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TDNParts = {
|
||||
commonName?: string;
|
||||
organization?: string;
|
||||
|
||||
Reference in New Issue
Block a user