Address greptile comments

This commit is contained in:
Carlos Monastyrski
2025-10-17 02:36:44 -03:00
parent 87a91ce423
commit 534ce7158b
49 changed files with 1844 additions and 617 deletions
@@ -191,6 +191,23 @@ export const mapLegacyExtendedKeyUsageToStandard = (usage: string): CertExtended
}
};
export enum CertKeyAlgorithm {
RSA_2048 = "RSA_2048",
RSA_3072 = "RSA_3072",
RSA_4096 = "RSA_4096",
ECDSA_P256 = "EC_prime256v1",
ECDSA_P384 = "EC_secp384r1"
}
export enum CertSignatureAlgorithm {
RSA_SHA256 = "RSA-SHA256",
RSA_SHA384 = "RSA-SHA384",
RSA_SHA512 = "RSA-SHA512",
ECDSA_SHA256 = "ECDSA-SHA256",
ECDSA_SHA384 = "ECDSA-SHA384",
ECDSA_SHA512 = "ECDSA-SHA512"
}
export const SAN_TYPE_OPTIONS = Object.values(CertSubjectAlternativeNameType);
export const KEY_USAGE_OPTIONS = Object.values(CertKeyUsageType);
export const EXTENDED_KEY_USAGE_OPTIONS = Object.values(CertExtendedKeyUsageType);
@@ -199,3 +216,5 @@ export const DURATION_UNIT_OPTIONS = Object.values(CertDurationUnit);
export const SUBJECT_ATTRIBUTE_TYPE_OPTIONS = Object.values(CertSubjectAttributeType);
export const ATTRIBUTE_RULE_OPTIONS = Object.values(CertAttributeRule);
export const SAN_EFFECT_OPTIONS = Object.values(CertSanEffect);
export const KEY_ALGORITHM_OPTIONS = Object.values(CertKeyAlgorithm);
export const SIGNATURE_ALGORITHM_OPTIONS = Object.values(CertSignatureAlgorithm);
@@ -1,3 +1,5 @@
import RE2 from "re2";
import { CertExtendedKeyUsage, CertKeyUsage } from "../certificate/certificate-types";
import {
CertExtendedKeyUsageType,
@@ -78,6 +80,43 @@ export const buildCertificateSubjectFromTemplate = (
return subject;
};
const isWildcardPattern = (value: string): boolean => {
return value.includes("*");
};
const createWildcardRegex = (pattern: string): RE2 => {
const escapeRegex = new RE2(/[.+?^${}()|[\]\\]/g);
const escaped = pattern.replace(escapeRegex, "\\$&");
const wildcardRegex = new RE2(/\*/g);
const regexPattern = escaped.replace(wildcardRegex, ".*");
return new RE2(`^${regexPattern}$`);
};
const validateValueAgainstPatterns = (value: string, patterns: string[]): boolean => {
if (!patterns || patterns.length === 0) {
return false;
}
for (const pattern of patterns) {
if (isWildcardPattern(pattern)) {
try {
const regex = createWildcardRegex(pattern);
if (regex.test(value)) {
return true;
}
} catch {
if (pattern === value) {
return true;
}
}
} else if (pattern === value) {
return true;
}
}
return false;
};
export const buildSubjectAlternativeNamesFromTemplate = (
request: { subjectAlternativeNames?: Array<{ type: string; value: string }> },
templateSans?: Array<{
@@ -98,7 +137,25 @@ export const buildSubjectAlternativeNamesFromTemplate = (
const allowedSans: string[] = [];
request.subjectAlternativeNames.forEach((san) => {
allowedSans.push(san.value);
const templateSan = templateSans.find((template) => template.type === san.type);
if (!templateSan) {
allowedSans.push(san.value);
return;
}
if (templateSan.denied && validateValueAgainstPatterns(san.value, templateSan.denied)) {
throw new Error(`SAN value '${san.value}' is explicitly denied for type '${san.type}'`);
}
const isRequired = templateSan.required && validateValueAgainstPatterns(san.value, templateSan.required);
const isAllowed = templateSan.allowed && validateValueAgainstPatterns(san.value, templateSan.allowed);
if (isRequired || isAllowed || (!templateSan.allowed && !templateSan.required)) {
allowedSans.push(san.value);
} else {
throw new Error(`SAN value '${san.value}' is not allowed for type '${san.type}'`);
}
});
return allowedSans.join(",");