feat: added custom key usages support for sign endpoint

This commit is contained in:
Sheen Capadngan
2024-09-11 20:26:33 +08:00
parent 4e6b289e1b
commit c1f61f2db4
4 changed files with 56 additions and 5 deletions

View File

@@ -654,7 +654,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
.refine((val) => ms(val) > 0, "TTL must be a positive number")
.describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.ttl),
notBefore: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.notBefore),
notAfter: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.notAfter)
notAfter: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.notAfter),
keyUsages: z.nativeEnum(CertKeyUsage).array().optional()
})
.refine(
(data) => {

View File

@@ -178,7 +178,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
.refine((val) => ms(val) > 0, "TTL must be a positive number")
.describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.ttl),
notBefore: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.notBefore),
notAfter: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.notAfter)
notAfter: validateCaDateField.optional().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.notAfter),
keyUsages: z.nativeEnum(CertKeyUsage).array().optional()
})
.refine(
(data) => {

View File

@@ -1346,7 +1346,8 @@ export const certificateAuthorityServiceFactory = ({
altNames,
ttl,
notBefore,
notAfter
notAfter,
keyUsages
} = dto;
let collectionId = pkiCollectionId;
@@ -1466,12 +1467,57 @@ export const certificateAuthorityServiceFactory = ({
});
const extensions: x509.Extension[] = [
new x509.KeyUsagesExtension(x509.KeyUsageFlags.digitalSignature | x509.KeyUsageFlags.keyEncipherment, true),
new x509.BasicConstraintsExtension(false),
await x509.AuthorityKeyIdentifierExtension.create(caCertObj, false),
await x509.SubjectKeyIdentifierExtension.create(csrObj.publicKey)
];
const csrKeyUsageExtension = csrObj.getExtension("2.5.29.15") as x509.KeyUsagesExtension;
let csrKeyUsages: CertKeyUsage[] = [];
if (csrKeyUsageExtension) {
csrKeyUsages = Object.values(CertKeyUsage).filter(
(keyUsage) => (x509.KeyUsageFlags[keyUsage] & csrKeyUsageExtension.usages) !== 0
);
}
let selectedKeyUsages: CertKeyUsage[] = keyUsages ?? [];
if (keyUsages === undefined && !certificateTemplate) {
if (csrKeyUsageExtension) {
selectedKeyUsages = csrKeyUsages;
} else {
selectedKeyUsages = [CertKeyUsage.DIGITAL_SIGNATURE, CertKeyUsage.KEY_ENCIPHERMENT];
}
}
if (keyUsages === undefined && certificateTemplate) {
if (csrKeyUsageExtension) {
const validKeyUsages = certificateTemplate.keyUsages || [];
if (csrKeyUsages.some((keyUsage) => !validKeyUsages.includes(keyUsage))) {
throw new BadRequestError({
message: "Invalid key usage value for certificate"
});
}
selectedKeyUsages = csrKeyUsages;
} else {
selectedKeyUsages = (certificateTemplate.keyUsages ?? []) as CertKeyUsage[];
}
}
if (keyUsages?.length && certificateTemplate) {
const validKeyUsages = certificateTemplate.keyUsages || [];
if (keyUsages.some((keyUsage) => !validKeyUsages.includes(keyUsage))) {
throw new BadRequestError({
message: "Invalid key usage value for certificate"
});
}
selectedKeyUsages = keyUsages;
}
const keyUsagesBitValue = selectedKeyUsages.reduce((accum, keyUsage) => accum | x509.KeyUsageFlags[keyUsage], 0);
if (keyUsagesBitValue) {
extensions.push(new x509.KeyUsagesExtension(keyUsagesBitValue, true));
}
let altNamesFromCsr: string = "";
let altNamesArray: {
type: "email" | "dns";
@@ -1567,7 +1613,8 @@ export const certificateAuthorityServiceFactory = ({
altNames: altNamesFromCsr || altNames,
serialNumber,
notBefore: notBeforeDate,
notAfter: notAfterDate
notAfter: notAfterDate,
keyUsages: selectedKeyUsages
},
tx
);

View File

@@ -113,6 +113,7 @@ export type TSignCertFromCaDTO =
ttl?: string;
notBefore?: string;
notAfter?: string;
keyUsages?: CertKeyUsage[];
}
| ({
isInternal: false;
@@ -126,6 +127,7 @@ export type TSignCertFromCaDTO =
ttl: string;
notBefore?: string;
notAfter?: string;
keyUsages?: CertKeyUsage[];
} & Omit<TProjectPermission, "projectId">);
export type TGetCaCertificateTemplatesDTO = {