Merge pull request #2414 from Infisical/misc/address-minor-cert-lint-issues

misc: addressed minor cert lint issues
This commit is contained in:
Sheen
2024-09-13 20:57:40 +08:00
committed by GitHub
5 changed files with 123 additions and 7 deletions

View File

@@ -11,6 +11,30 @@ export const registerCaCrlRouter = async (server: FastifyZodProvider) => {
config: { config: {
rateLimit: readLimit rateLimit: readLimit
}, },
schema: {
description: "Get CRL in DER format (deprecated)",
params: z.object({
crlId: z.string().trim().describe(CA_CRLS.GET.crlId)
}),
response: {
200: z.instanceof(Buffer)
}
},
handler: async (req, res) => {
const { crl } = await server.services.certificateAuthorityCrl.getCrlById(req.params.crlId);
res.header("Content-Type", "application/pkix-crl");
return Buffer.from(crl);
}
});
server.route({
method: "GET",
url: "/:crlId/der",
config: {
rateLimit: readLimit
},
schema: { schema: {
description: "Get CRL in DER format", description: "Get CRL in DER format",
params: z.object({ params: z.object({

View File

@@ -1083,6 +1083,10 @@ export const CERTIFICATE_AUTHORITIES = {
certificateChain: "The certificate chain of the CA", certificateChain: "The certificate chain of the CA",
serialNumber: "The serial number of the CA certificate" serialNumber: "The serial number of the CA certificate"
}, },
GET_CERT_BY_ID: {
caId: "The ID of the CA to get the CA certificate from",
caCertId: "The ID of the CA certificate to get"
},
GET_CA_CERTS: { GET_CA_CERTS: {
caId: "The ID of the CA to get the CA certificates for", caId: "The ID of the CA to get the CA certificates for",
certificate: "The certificate body of the CA certificate", certificate: "The certificate body of the CA certificate",

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-floating-promises */
import ms from "ms"; import ms from "ms";
import { z } from "zod"; import { z } from "zod";
@@ -139,6 +140,33 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
} }
}); });
// this endpoint will be used to serve the CA certificate when a client makes a request
// against the Authority Information Access CA Issuer URL
server.route({
method: "GET",
url: "/:caId/certificates/:caCertId/der",
config: {
rateLimit: readLimit
},
schema: {
description: "Get DER-encoded certificate of CA",
params: z.object({
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT_BY_ID.caId),
caCertId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT_BY_ID.caCertId)
}),
response: {
200: z.instanceof(Buffer)
}
},
handler: async (req, res) => {
const caCert = await server.services.certificateAuthority.getCaCertById(req.params);
res.header("Content-Type", "application/pkix-cert");
return Buffer.from(caCert.rawData);
}
});
server.route({ server.route({
method: "PATCH", method: "PATCH",
url: "/:caId", url: "/:caId",

View File

@@ -15,7 +15,7 @@ import {
/* eslint-disable no-bitwise */ /* eslint-disable no-bitwise */
export const createSerialNumber = () => { export const createSerialNumber = () => {
const randomBytes = crypto.randomBytes(32); const randomBytes = crypto.randomBytes(20);
randomBytes[0] &= 0x7f; // ensure the first bit is 0 randomBytes[0] &= 0x7f; // ensure the first bit is 0
return randomBytes.toString("hex"); return randomBytes.toString("hex");
}; };

View File

@@ -768,6 +768,39 @@ export const certificateAuthorityServiceFactory = ({
}; };
}; };
/**
* Return CA certificate object by ID
*/
const getCaCertById = async ({ caId, caCertId }: { caId: string; caCertId: string }) => {
const caCert = await certificateAuthorityCertDAL.findOne({
caId,
id: caCertId
});
if (!caCert) {
throw new NotFoundError({ message: "CA certificate not found" });
}
const ca = await certificateAuthorityDAL.findById(caId);
const keyId = await getProjectKmsCertificateKeyId({
projectId: ca.projectId,
projectDAL,
kmsService
});
const kmsDecryptor = await kmsService.decryptWithKmsKey({
kmsId: keyId
});
const decryptedCaCert = await kmsDecryptor({
cipherTextBlob: caCert.encryptedCertificate
});
const caCertObj = new x509.X509Certificate(decryptedCaCert);
return caCertObj;
};
/** /**
* Issue certificate to be imported back in for intermediate CA * Issue certificate to be imported back in for intermediate CA
*/ */
@@ -782,6 +815,7 @@ export const certificateAuthorityServiceFactory = ({
notAfter, notAfter,
maxPathLength maxPathLength
}: TSignIntermediateDTO) => { }: TSignIntermediateDTO) => {
const appCfg = getConfig();
const ca = await certificateAuthorityDAL.findById(caId); const ca = await certificateAuthorityDAL.findById(caId);
if (!ca) throw new BadRequestError({ message: "CA not found" }); if (!ca) throw new BadRequestError({ message: "CA not found" });
@@ -856,7 +890,7 @@ export const certificateAuthorityServiceFactory = ({
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 { caPrivateKey } = await getCaCredentials({ const { caPrivateKey, caSecret } = await getCaCredentials({
caId: ca.id, caId: ca.id,
certificateAuthorityDAL, certificateAuthorityDAL,
certificateAuthoritySecretDAL, certificateAuthoritySecretDAL,
@@ -865,6 +899,11 @@ export const certificateAuthorityServiceFactory = ({
}); });
const serialNumber = createSerialNumber(); const serialNumber = createSerialNumber();
const caCrl = await certificateAuthorityCrlDAL.findOne({ caSecretId: caSecret.id });
const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/pki/crl/${caCrl.id}/der`;
const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/pki/ca/${ca.id}/certificates/${caCert.id}/der`;
const intermediateCert = await x509.X509CertificateGenerator.create({ const intermediateCert = await x509.X509CertificateGenerator.create({
serialNumber, serialNumber,
subject: csrObj.subject, subject: csrObj.subject,
@@ -884,7 +923,11 @@ export const certificateAuthorityServiceFactory = ({
), ),
new x509.BasicConstraintsExtension(true, maxPathLength === -1 ? undefined : maxPathLength, true), new x509.BasicConstraintsExtension(true, maxPathLength === -1 ? undefined : maxPathLength, true),
await x509.AuthorityKeyIdentifierExtension.create(caCertObj, false), await x509.AuthorityKeyIdentifierExtension.create(caCertObj, false),
await x509.SubjectKeyIdentifierExtension.create(csrObj.publicKey) await x509.SubjectKeyIdentifierExtension.create(csrObj.publicKey),
new x509.CRLDistributionPointsExtension([distributionPointUrl]),
new x509.AuthorityInfoAccessExtension({
caIssuers: new x509.GeneralName("url", caIssuerUrl)
})
] ]
}); });
@@ -1176,12 +1219,18 @@ export const certificateAuthorityServiceFactory = ({
const caCrl = await certificateAuthorityCrlDAL.findOne({ caSecretId: caSecret.id }); const caCrl = await certificateAuthorityCrlDAL.findOne({ caSecretId: caSecret.id });
const appCfg = getConfig(); const appCfg = getConfig();
const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/pki/crl/${caCrl.id}`; const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/pki/crl/${caCrl.id}/der`;
const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/pki/ca/${ca.id}/certificates/${caCert.id}/der`;
const extensions: x509.Extension[] = [ const extensions: x509.Extension[] = [
new x509.BasicConstraintsExtension(false), new x509.BasicConstraintsExtension(false),
new x509.CRLDistributionPointsExtension([distributionPointUrl]), new x509.CRLDistributionPointsExtension([distributionPointUrl]),
await x509.AuthorityKeyIdentifierExtension.create(caCertObj, false), await x509.AuthorityKeyIdentifierExtension.create(caCertObj, false),
await x509.SubjectKeyIdentifierExtension.create(csrObj.publicKey) await x509.SubjectKeyIdentifierExtension.create(csrObj.publicKey),
new x509.AuthorityInfoAccessExtension({
caIssuers: new x509.GeneralName("url", caIssuerUrl)
}),
new x509.CertificatePolicyExtension(["2.5.29.32.0"]) // anyPolicy
]; ];
// handle key usages // handle key usages
@@ -1366,6 +1415,7 @@ export const certificateAuthorityServiceFactory = ({
* Note: CSR is generated externally and submitted to Infisical. * Note: CSR is generated externally and submitted to Infisical.
*/ */
const signCertFromCa = async (dto: TSignCertFromCaDTO) => { const signCertFromCa = async (dto: TSignCertFromCaDTO) => {
const appCfg = getConfig();
let ca: TCertificateAuthorities | undefined; let ca: TCertificateAuthorities | undefined;
let certificateTemplate: TCertificateTemplates | undefined; let certificateTemplate: TCertificateTemplates | undefined;
@@ -1492,7 +1542,7 @@ export const certificateAuthorityServiceFactory = ({
message: "A common name (CN) is required in the CSR or as a parameter to this endpoint" message: "A common name (CN) is required in the CSR or as a parameter to this endpoint"
}); });
const { caPrivateKey } = await getCaCredentials({ const { caPrivateKey, caSecret } = await getCaCredentials({
caId: ca.id, caId: ca.id,
certificateAuthorityDAL, certificateAuthorityDAL,
certificateAuthoritySecretDAL, certificateAuthoritySecretDAL,
@@ -1500,10 +1550,19 @@ export const certificateAuthorityServiceFactory = ({
kmsService kmsService
}); });
const caCrl = await certificateAuthorityCrlDAL.findOne({ caSecretId: caSecret.id });
const distributionPointUrl = `${appCfg.SITE_URL}/api/v1/pki/crl/${caCrl.id}/der`;
const caIssuerUrl = `${appCfg.SITE_URL}/api/v1/pki/ca/${ca.id}/certificates/${caCert.id}/der`;
const extensions: x509.Extension[] = [ const extensions: x509.Extension[] = [
new x509.BasicConstraintsExtension(false), new x509.BasicConstraintsExtension(false),
await x509.AuthorityKeyIdentifierExtension.create(caCertObj, false), await x509.AuthorityKeyIdentifierExtension.create(caCertObj, false),
await x509.SubjectKeyIdentifierExtension.create(csrObj.publicKey) await x509.SubjectKeyIdentifierExtension.create(csrObj.publicKey),
new x509.CRLDistributionPointsExtension([distributionPointUrl]),
new x509.AuthorityInfoAccessExtension({
caIssuers: new x509.GeneralName("url", caIssuerUrl)
}),
new x509.CertificatePolicyExtension(["2.5.29.32.0"]) // anyPolicy
]; ];
// handle key usages // handle key usages
@@ -1783,6 +1842,7 @@ export const certificateAuthorityServiceFactory = ({
renewCaCert, renewCaCert,
getCaCerts, getCaCerts,
getCaCert, getCaCert,
getCaCertById,
signIntermediate, signIntermediate,
importCertToCa, importCertToCa,
issueCertFromCa, issueCertFromCa,