mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 02:27:37 +00:00
Merge pull request #4867 from Infisical/feat/ENG-3969
Add PKI template presets
This commit is contained in:
+7
-2
@@ -10,7 +10,7 @@ import {
|
|||||||
ProjectPermissionSub
|
ProjectPermissionSub
|
||||||
} from "@app/context/ProjectPermissionContext/types";
|
} from "@app/context/ProjectPermissionContext/types";
|
||||||
import { useDeleteCertificateTemplateV2WithPolicies } from "@app/hooks/api/certificateTemplates/mutations";
|
import { useDeleteCertificateTemplateV2WithPolicies } from "@app/hooks/api/certificateTemplates/mutations";
|
||||||
import { TCertificateTemplateV2WithPolicies } from "@app/hooks/api/certificateTemplates/types";
|
import { type TCertificateTemplateV2WithPolicies } from "@app/hooks/api/certificateTemplates/types";
|
||||||
|
|
||||||
import { CreateTemplateModal } from "./CreateTemplateModal";
|
import { CreateTemplateModal } from "./CreateTemplateModal";
|
||||||
import { TemplateList } from "./TemplateList";
|
import { TemplateList } from "./TemplateList";
|
||||||
@@ -84,7 +84,12 @@ export const CertificateTemplatesV2Tab = () => {
|
|||||||
|
|
||||||
<TemplateList onEditTemplate={handleEditTemplate} onDeleteTemplate={handleDeleteTemplate} />
|
<TemplateList onEditTemplate={handleEditTemplate} onDeleteTemplate={handleDeleteTemplate} />
|
||||||
|
|
||||||
<CreateTemplateModal isOpen={isCreateModalOpen} onClose={() => setIsCreateModalOpen(false)} />
|
<CreateTemplateModal
|
||||||
|
isOpen={isCreateModalOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setIsCreateModalOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
{selectedTemplate && (
|
{selectedTemplate && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
+157
-32
@@ -36,13 +36,18 @@ import {
|
|||||||
CertDurationUnit,
|
CertDurationUnit,
|
||||||
CertExtendedKeyUsageType,
|
CertExtendedKeyUsageType,
|
||||||
CertKeyUsageType,
|
CertKeyUsageType,
|
||||||
|
CertSanInclude,
|
||||||
CertSubjectAlternativeNameType,
|
CertSubjectAlternativeNameType,
|
||||||
|
CertSubjectAttributeInclude,
|
||||||
CertSubjectAttributeType,
|
CertSubjectAttributeType,
|
||||||
SAN_INCLUDE_OPTIONS,
|
SAN_INCLUDE_OPTIONS,
|
||||||
SAN_TYPE_OPTIONS,
|
SAN_TYPE_OPTIONS,
|
||||||
SUBJECT_ATTRIBUTE_INCLUDE_OPTIONS,
|
SUBJECT_ATTRIBUTE_INCLUDE_OPTIONS,
|
||||||
SUBJECT_ATTRIBUTE_TYPE_OPTIONS
|
SUBJECT_ATTRIBUTE_TYPE_OPTIONS,
|
||||||
|
TEMPLATE_PRESET_IDS,
|
||||||
|
type TemplatePresetId
|
||||||
} from "./shared/certificate-constants";
|
} from "./shared/certificate-constants";
|
||||||
|
import { CERTIFICATE_TEMPLATE_PRESETS } from "./shared/template-presets";
|
||||||
import { KeyUsagesSection, TemplateFormData, templateSchema } from "./shared";
|
import { KeyUsagesSection, TemplateFormData, templateSchema } from "./shared";
|
||||||
|
|
||||||
export type FormData = TemplateFormData;
|
export type FormData = TemplateFormData;
|
||||||
@@ -91,7 +96,7 @@ const SIGNATURE_ALGORITHMS = [
|
|||||||
"SHA256-ECDSA",
|
"SHA256-ECDSA",
|
||||||
"SHA384-ECDSA",
|
"SHA384-ECDSA",
|
||||||
"SHA512-ECDSA"
|
"SHA512-ECDSA"
|
||||||
];
|
] as const;
|
||||||
|
|
||||||
const KEY_ALGORITHMS = [
|
const KEY_ALGORITHMS = [
|
||||||
"RSA-2048",
|
"RSA-2048",
|
||||||
@@ -100,7 +105,7 @@ const KEY_ALGORITHMS = [
|
|||||||
"ECDSA-P256",
|
"ECDSA-P256",
|
||||||
"ECDSA-P384",
|
"ECDSA-P384",
|
||||||
"ECDSA-P521"
|
"ECDSA-P521"
|
||||||
];
|
] as const;
|
||||||
|
|
||||||
export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create" }: Props) => {
|
export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create" }: Props) => {
|
||||||
const { currentProject } = useProject();
|
const { currentProject } = useProject();
|
||||||
@@ -117,7 +122,7 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
subj.allowed.forEach((allowedValue) => {
|
subj.allowed.forEach((allowedValue) => {
|
||||||
attributes.push({
|
attributes.push({
|
||||||
type: subj.type as CertSubjectAttributeType,
|
type: subj.type as CertSubjectAttributeType,
|
||||||
include: "optional",
|
include: CertSubjectAttributeInclude.OPTIONAL,
|
||||||
value: [allowedValue]
|
value: [allowedValue]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -126,7 +131,7 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
subj.denied.forEach((deniedValue) => {
|
subj.denied.forEach((deniedValue) => {
|
||||||
attributes.push({
|
attributes.push({
|
||||||
type: subj.type as CertSubjectAttributeType,
|
type: subj.type as CertSubjectAttributeType,
|
||||||
include: "prohibit",
|
include: CertSubjectAttributeInclude.PROHIBIT,
|
||||||
value: [deniedValue]
|
value: [deniedValue]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -141,7 +146,7 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
san.required.forEach((requiredValue) => {
|
san.required.forEach((requiredValue) => {
|
||||||
subjectAlternativeNames.push({
|
subjectAlternativeNames.push({
|
||||||
type: san.type as CertSubjectAlternativeNameType,
|
type: san.type as CertSubjectAlternativeNameType,
|
||||||
include: "mandatory",
|
include: CertSanInclude.MANDATORY,
|
||||||
value: [requiredValue]
|
value: [requiredValue]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -150,7 +155,7 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
san.allowed.forEach((allowedValue) => {
|
san.allowed.forEach((allowedValue) => {
|
||||||
subjectAlternativeNames.push({
|
subjectAlternativeNames.push({
|
||||||
type: san.type as CertSubjectAlternativeNameType,
|
type: san.type as CertSubjectAlternativeNameType,
|
||||||
include: "optional",
|
include: CertSanInclude.OPTIONAL,
|
||||||
value: [allowedValue]
|
value: [allowedValue]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -159,7 +164,7 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
san.denied.forEach((deniedValue) => {
|
san.denied.forEach((deniedValue) => {
|
||||||
subjectAlternativeNames.push({
|
subjectAlternativeNames.push({
|
||||||
type: san.type as CertSubjectAlternativeNameType,
|
type: san.type as CertSubjectAlternativeNameType,
|
||||||
include: "prohibit",
|
include: CertSanInclude.PROHIBIT,
|
||||||
value: [deniedValue]
|
value: [deniedValue]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -219,6 +224,7 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
preset: TEMPLATE_PRESET_IDS.CUSTOM,
|
||||||
name: templateData.name || "",
|
name: templateData.name || "",
|
||||||
description: templateData.description || "",
|
description: templateData.description || "",
|
||||||
attributes,
|
attributes,
|
||||||
@@ -231,25 +237,30 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDefaultValues = (): FormData => ({
|
const getDefaultValues = (): FormData & { preset: TemplatePresetId } => {
|
||||||
name: "",
|
return {
|
||||||
description: "",
|
preset: TEMPLATE_PRESET_IDS.CUSTOM,
|
||||||
attributes: [],
|
name: "",
|
||||||
keyUsages: { requiredUsages: [], optionalUsages: [] },
|
description: "",
|
||||||
extendedKeyUsages: { requiredUsages: [], optionalUsages: [] },
|
attributes: [],
|
||||||
subjectAlternativeNames: [],
|
keyUsages: { requiredUsages: [], optionalUsages: [] },
|
||||||
validity: {
|
extendedKeyUsages: { requiredUsages: [], optionalUsages: [] },
|
||||||
maxDuration: { value: 365, unit: CertDurationUnit.DAYS }
|
subjectAlternativeNames: [],
|
||||||
},
|
validity: {
|
||||||
signatureAlgorithm: {
|
maxDuration: { value: 365, unit: CertDurationUnit.DAYS }
|
||||||
allowedAlgorithms: []
|
},
|
||||||
},
|
signatureAlgorithm: {
|
||||||
keyAlgorithm: {
|
allowedAlgorithms: []
|
||||||
allowedKeyTypes: []
|
},
|
||||||
}
|
keyAlgorithm: {
|
||||||
});
|
allowedKeyTypes: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const { control, handleSubmit, reset, watch, setValue, formState } = useForm<FormData>({
|
const { control, handleSubmit, reset, watch, setValue, formState } = useForm<
|
||||||
|
FormData & { preset: TemplatePresetId }
|
||||||
|
>({
|
||||||
resolver: zodResolver(templateSchema),
|
resolver: zodResolver(templateSchema),
|
||||||
defaultValues: getDefaultValues(),
|
defaultValues: getDefaultValues(),
|
||||||
mode: "onChange",
|
mode: "onChange",
|
||||||
@@ -260,7 +271,7 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isEdit && template) {
|
if (isEdit && template) {
|
||||||
const convertedData = convertApiToUiFormat(template);
|
const convertedData = convertApiToUiFormat(template);
|
||||||
reset(convertedData);
|
reset({ ...convertedData, preset: TEMPLATE_PRESET_IDS.CUSTOM });
|
||||||
} else if (!isEdit) {
|
} else if (!isEdit) {
|
||||||
reset(getDefaultValues());
|
reset(getDefaultValues());
|
||||||
}
|
}
|
||||||
@@ -273,6 +284,37 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
requiredUsages: [],
|
requiredUsages: [],
|
||||||
optionalUsages: []
|
optionalUsages: []
|
||||||
};
|
};
|
||||||
|
const watchedPreset = watch("preset") || TEMPLATE_PRESET_IDS.CUSTOM;
|
||||||
|
|
||||||
|
const handlePresetChange = (presetId: TemplatePresetId) => {
|
||||||
|
setValue("preset", presetId);
|
||||||
|
|
||||||
|
if (presetId === TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedPreset = CERTIFICATE_TEMPLATE_PRESETS.find((p) => p.id === presetId);
|
||||||
|
if (selectedPreset) {
|
||||||
|
if (selectedPreset.formData.keyUsages) {
|
||||||
|
setValue("keyUsages", selectedPreset.formData.keyUsages);
|
||||||
|
}
|
||||||
|
if (selectedPreset.formData.extendedKeyUsages) {
|
||||||
|
setValue("extendedKeyUsages", selectedPreset.formData.extendedKeyUsages);
|
||||||
|
}
|
||||||
|
if (selectedPreset.formData.attributes) {
|
||||||
|
setValue("attributes", selectedPreset.formData.attributes);
|
||||||
|
}
|
||||||
|
if (selectedPreset.formData.subjectAlternativeNames) {
|
||||||
|
setValue("subjectAlternativeNames", selectedPreset.formData.subjectAlternativeNames);
|
||||||
|
}
|
||||||
|
if (selectedPreset.formData.signatureAlgorithm) {
|
||||||
|
setValue("signatureAlgorithm", selectedPreset.formData.signatureAlgorithm);
|
||||||
|
}
|
||||||
|
if (selectedPreset.formData.keyAlgorithm) {
|
||||||
|
setValue("keyAlgorithm", selectedPreset.formData.keyAlgorithm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const consolidateByType = <
|
const consolidateByType = <
|
||||||
T extends { type: string; allowed?: string[]; required?: string[]; denied?: string[] }
|
T extends { type: string; allowed?: string[]; required?: string[]; denied?: string[] }
|
||||||
@@ -309,9 +351,17 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
data.attributes?.map((attr) => {
|
data.attributes?.map((attr) => {
|
||||||
const result: AttributeTransform = { type: attr.type };
|
const result: AttributeTransform = { type: attr.type };
|
||||||
|
|
||||||
if (attr.include === "optional" && attr.value && attr.value.length > 0) {
|
if (
|
||||||
|
attr.include === CertSubjectAttributeInclude.OPTIONAL &&
|
||||||
|
attr.value &&
|
||||||
|
attr.value.length > 0
|
||||||
|
) {
|
||||||
result.allowed = attr.value;
|
result.allowed = attr.value;
|
||||||
} else if (attr.include === "prohibit" && attr.value && attr.value.length > 0) {
|
} else if (
|
||||||
|
attr.include === CertSubjectAttributeInclude.PROHIBIT &&
|
||||||
|
attr.value &&
|
||||||
|
attr.value.length > 0
|
||||||
|
) {
|
||||||
result.denied = attr.value;
|
result.denied = attr.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,11 +372,11 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
data.subjectAlternativeNames?.map((san) => {
|
data.subjectAlternativeNames?.map((san) => {
|
||||||
const result: SanTransform = { type: san.type };
|
const result: SanTransform = { type: san.type };
|
||||||
|
|
||||||
if (san.include === "mandatory" && san.value && san.value.length > 0) {
|
if (san.include === CertSanInclude.MANDATORY && san.value && san.value.length > 0) {
|
||||||
result.required = san.value;
|
result.required = san.value;
|
||||||
} else if (san.include === "optional" && san.value && san.value.length > 0) {
|
} else if (san.include === CertSanInclude.OPTIONAL && san.value && san.value.length > 0) {
|
||||||
result.allowed = san.value;
|
result.allowed = san.value;
|
||||||
} else if (san.include === "prohibit" && san.value && san.value.length > 0) {
|
} else if (san.include === CertSanInclude.PROHIBIT && san.value && san.value.length > 0) {
|
||||||
result.denied = san.value;
|
result.denied = san.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,11 +514,19 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
value: ["*"]
|
value: ["*"]
|
||||||
};
|
};
|
||||||
setValue("attributes", [...watchedAttributes, newAttribute]);
|
setValue("attributes", [...watchedAttributes, newAttribute]);
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeAttribute = (index: number) => {
|
const removeAttribute = (index: number) => {
|
||||||
const newAttributes = watchedAttributes.filter((_, i) => i !== index);
|
const newAttributes = watchedAttributes.filter((_, i) => i !== index);
|
||||||
setValue("attributes", newAttributes);
|
setValue("attributes", newAttributes);
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const addSan = () => {
|
const addSan = () => {
|
||||||
@@ -478,11 +536,19 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
value: ["*"]
|
value: ["*"]
|
||||||
};
|
};
|
||||||
setValue("subjectAlternativeNames", [...watchedSans, newSan]);
|
setValue("subjectAlternativeNames", [...watchedSans, newSan]);
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeSan = (index: number) => {
|
const removeSan = (index: number) => {
|
||||||
const newSans = watchedSans.filter((_, i) => i !== index);
|
const newSans = watchedSans.filter((_, i) => i !== index);
|
||||||
setValue("subjectAlternativeNames", newSans);
|
setValue("subjectAlternativeNames", newSans);
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleKeyUsagesChange = (usages: {
|
const handleKeyUsagesChange = (usages: {
|
||||||
@@ -493,6 +559,10 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
requiredUsages: usages.requiredUsages,
|
requiredUsages: usages.requiredUsages,
|
||||||
optionalUsages: usages.optionalUsages
|
optionalUsages: usages.optionalUsages
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleExtendedKeyUsagesChange = (usages: {
|
const handleExtendedKeyUsagesChange = (usages: {
|
||||||
@@ -503,6 +573,10 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
requiredUsages: usages.requiredUsages,
|
requiredUsages: usages.requiredUsages,
|
||||||
optionalUsages: usages.optionalUsages
|
optionalUsages: usages.optionalUsages
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -555,6 +629,33 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="preset"
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
label="Template Preset"
|
||||||
|
isError={Boolean(error)}
|
||||||
|
errorText={error?.message}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
value={field.value}
|
||||||
|
onValueChange={handlePresetChange}
|
||||||
|
className="w-full"
|
||||||
|
position="popper"
|
||||||
|
dropdownContainerClassName="max-w-none"
|
||||||
|
>
|
||||||
|
<SelectItem value={TEMPLATE_PRESET_IDS.CUSTOM}>Custom</SelectItem>
|
||||||
|
{CERTIFICATE_TEMPLATE_PRESETS.map((preset) => (
|
||||||
|
<SelectItem key={preset.id} value={preset.id}>
|
||||||
|
{preset.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<AccordionItem value="attributes">
|
<AccordionItem value="attributes">
|
||||||
<AccordionTrigger>Subject Attributes</AccordionTrigger>
|
<AccordionTrigger>Subject Attributes</AccordionTrigger>
|
||||||
@@ -595,6 +696,10 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
type: value as CertSubjectAttributeType
|
type: value as CertSubjectAttributeType
|
||||||
};
|
};
|
||||||
setValue("attributes", newAttributes);
|
setValue("attributes", newAttributes);
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
className="w-48"
|
className="w-48"
|
||||||
>
|
>
|
||||||
@@ -615,6 +720,10 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
value as (typeof SUBJECT_ATTRIBUTE_INCLUDE_OPTIONS)[number]
|
value as (typeof SUBJECT_ATTRIBUTE_INCLUDE_OPTIONS)[number]
|
||||||
};
|
};
|
||||||
setValue("attributes", newAttributes);
|
setValue("attributes", newAttributes);
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
className="w-32"
|
className="w-32"
|
||||||
>
|
>
|
||||||
@@ -635,6 +744,10 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
value: e.target.value.trim() ? [e.target.value.trim()] : []
|
value: e.target.value.trim() ? [e.target.value.trim()] : []
|
||||||
};
|
};
|
||||||
setValue("attributes", newAttributes);
|
setValue("attributes", newAttributes);
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
className={`flex-1 ${
|
className={`flex-1 ${
|
||||||
attr.value && attr.value.length > 0 && attr.value[0] === ""
|
attr.value && attr.value.length > 0 && attr.value[0] === ""
|
||||||
@@ -701,6 +814,10 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
type: value as CertSubjectAlternativeNameType
|
type: value as CertSubjectAlternativeNameType
|
||||||
};
|
};
|
||||||
setValue("subjectAlternativeNames", newSans);
|
setValue("subjectAlternativeNames", newSans);
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
className="w-36"
|
className="w-36"
|
||||||
>
|
>
|
||||||
@@ -720,6 +837,10 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
include: value as (typeof SAN_INCLUDE_OPTIONS)[number]
|
include: value as (typeof SAN_INCLUDE_OPTIONS)[number]
|
||||||
};
|
};
|
||||||
setValue("subjectAlternativeNames", newSans);
|
setValue("subjectAlternativeNames", newSans);
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
className="w-32"
|
className="w-32"
|
||||||
>
|
>
|
||||||
@@ -740,6 +861,10 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
|||||||
value: e.target.value.trim() ? [e.target.value.trim()] : []
|
value: e.target.value.trim() ? [e.target.value.trim()] : []
|
||||||
};
|
};
|
||||||
setValue("subjectAlternativeNames", newSans);
|
setValue("subjectAlternativeNames", newSans);
|
||||||
|
|
||||||
|
if (watchedPreset !== TEMPLATE_PRESET_IDS.CUSTOM) {
|
||||||
|
setValue("preset", TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
className={`flex-1 ${
|
className={`flex-1 ${
|
||||||
san.value && san.value.length > 0 && san.value[0] === ""
|
san.value && san.value.length > 0 && san.value[0] === ""
|
||||||
|
|||||||
+37
-2
@@ -150,8 +150,19 @@ export const SUBJECT_ATTRIBUTE_TYPE_OPTIONS = Object.values(CertSubjectAttribute
|
|||||||
export const ATTRIBUTE_RULE_OPTIONS = Object.values(CertAttributeRule);
|
export const ATTRIBUTE_RULE_OPTIONS = Object.values(CertAttributeRule);
|
||||||
export const SAN_EFFECT_OPTIONS = Object.values(CertSanEffect);
|
export const SAN_EFFECT_OPTIONS = Object.values(CertSanEffect);
|
||||||
|
|
||||||
export const SUBJECT_ATTRIBUTE_INCLUDE_OPTIONS = ["optional", "prohibit"] as const;
|
export enum CertSubjectAttributeInclude {
|
||||||
export const SAN_INCLUDE_OPTIONS = ["mandatory", "optional", "prohibit"] as const;
|
OPTIONAL = "optional",
|
||||||
|
PROHIBIT = "prohibit"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum CertSanInclude {
|
||||||
|
MANDATORY = "mandatory",
|
||||||
|
OPTIONAL = "optional",
|
||||||
|
PROHIBIT = "prohibit"
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SUBJECT_ATTRIBUTE_INCLUDE_OPTIONS = Object.values(CertSubjectAttributeInclude);
|
||||||
|
export const SAN_INCLUDE_OPTIONS = Object.values(CertSanInclude);
|
||||||
|
|
||||||
export const USAGE_STATES = {
|
export const USAGE_STATES = {
|
||||||
REQUIRED: "required",
|
REQUIRED: "required",
|
||||||
@@ -239,3 +250,27 @@ export const mapTemplateKeyAlgorithmToApi = (templateFormat: string): string =>
|
|||||||
};
|
};
|
||||||
return mapping[templateFormat] || templateFormat;
|
return mapping[templateFormat] || templateFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const TEMPLATE_PRESET_IDS = {
|
||||||
|
CUSTOM: "custom",
|
||||||
|
TLS_SERVER: "tls-server",
|
||||||
|
TLS_CLIENT: "tls-client",
|
||||||
|
CODE_SIGNING: "code-signing",
|
||||||
|
DEVICE: "device",
|
||||||
|
USER: "user",
|
||||||
|
EMAIL_PROTECTION: "email-protection",
|
||||||
|
DUAL_PURPOSE_SERVER: "dual-purpose-server"
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type TemplatePresetId = (typeof TEMPLATE_PRESET_IDS)[keyof typeof TEMPLATE_PRESET_IDS];
|
||||||
|
|
||||||
|
export const ALGORITHM_FAMILIES = {
|
||||||
|
ECDSA: {
|
||||||
|
signature: ["SHA256-ECDSA", "SHA384-ECDSA", "SHA512-ECDSA"] as const,
|
||||||
|
key: ["ECDSA-P256", "ECDSA-P384", "ECDSA-P521"] as const
|
||||||
|
},
|
||||||
|
RSA: {
|
||||||
|
signature: ["SHA256-RSA", "SHA384-RSA", "SHA512-RSA"] as const,
|
||||||
|
key: ["RSA-2048", "RSA-3072", "RSA-4096"] as const
|
||||||
|
}
|
||||||
|
} as const;
|
||||||
|
|||||||
+19
-4
@@ -4,21 +4,22 @@ import {
|
|||||||
CertDurationUnit,
|
CertDurationUnit,
|
||||||
CertExtendedKeyUsageType,
|
CertExtendedKeyUsageType,
|
||||||
CertKeyUsageType,
|
CertKeyUsageType,
|
||||||
|
CertSanInclude,
|
||||||
CertSubjectAlternativeNameType,
|
CertSubjectAlternativeNameType,
|
||||||
|
CertSubjectAttributeInclude,
|
||||||
CertSubjectAttributeType,
|
CertSubjectAttributeType,
|
||||||
SAN_INCLUDE_OPTIONS,
|
TEMPLATE_PRESET_IDS
|
||||||
SUBJECT_ATTRIBUTE_INCLUDE_OPTIONS
|
|
||||||
} from "./certificate-constants";
|
} from "./certificate-constants";
|
||||||
|
|
||||||
export const uiAttributeSchema = z.object({
|
export const uiAttributeSchema = z.object({
|
||||||
type: z.nativeEnum(CertSubjectAttributeType),
|
type: z.nativeEnum(CertSubjectAttributeType),
|
||||||
include: z.enum(SUBJECT_ATTRIBUTE_INCLUDE_OPTIONS),
|
include: z.nativeEnum(CertSubjectAttributeInclude),
|
||||||
value: z.array(z.string().min(1, "Value cannot be empty"))
|
value: z.array(z.string().min(1, "Value cannot be empty"))
|
||||||
});
|
});
|
||||||
|
|
||||||
export const uiSanSchema = z.object({
|
export const uiSanSchema = z.object({
|
||||||
type: z.nativeEnum(CertSubjectAlternativeNameType),
|
type: z.nativeEnum(CertSubjectAlternativeNameType),
|
||||||
include: z.enum(SAN_INCLUDE_OPTIONS),
|
include: z.nativeEnum(CertSanInclude),
|
||||||
value: z.array(z.string().min(1, "Value cannot be empty"))
|
value: z.array(z.string().min(1, "Value cannot be empty"))
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -51,7 +52,21 @@ export const uiKeyAlgorithmSchema = z.object({
|
|||||||
.min(1, "At least one key type must be selected")
|
.min(1, "At least one key type must be selected")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const uiPresetSchema = z
|
||||||
|
.enum([
|
||||||
|
TEMPLATE_PRESET_IDS.CUSTOM,
|
||||||
|
TEMPLATE_PRESET_IDS.TLS_SERVER,
|
||||||
|
TEMPLATE_PRESET_IDS.TLS_CLIENT,
|
||||||
|
TEMPLATE_PRESET_IDS.CODE_SIGNING,
|
||||||
|
TEMPLATE_PRESET_IDS.DEVICE,
|
||||||
|
TEMPLATE_PRESET_IDS.USER,
|
||||||
|
TEMPLATE_PRESET_IDS.EMAIL_PROTECTION,
|
||||||
|
TEMPLATE_PRESET_IDS.DUAL_PURPOSE_SERVER
|
||||||
|
])
|
||||||
|
.default(TEMPLATE_PRESET_IDS.CUSTOM);
|
||||||
|
|
||||||
export const templateSchema = z.object({
|
export const templateSchema = z.object({
|
||||||
|
preset: uiPresetSchema,
|
||||||
name: z
|
name: z
|
||||||
.string()
|
.string()
|
||||||
.trim()
|
.trim()
|
||||||
|
|||||||
+385
@@ -0,0 +1,385 @@
|
|||||||
|
import {
|
||||||
|
ALGORITHM_FAMILIES,
|
||||||
|
CertDurationUnit,
|
||||||
|
CertExtendedKeyUsageType,
|
||||||
|
CertKeyUsageType,
|
||||||
|
CertSanInclude,
|
||||||
|
CertSubjectAlternativeNameType,
|
||||||
|
CertSubjectAttributeInclude,
|
||||||
|
CertSubjectAttributeType,
|
||||||
|
TEMPLATE_PRESET_IDS,
|
||||||
|
type TemplatePresetId
|
||||||
|
} from "./certificate-constants";
|
||||||
|
import { TemplateFormData } from ".";
|
||||||
|
|
||||||
|
export interface CertificateTemplatePreset {
|
||||||
|
readonly id: TemplatePresetId;
|
||||||
|
readonly name: string;
|
||||||
|
readonly description: string;
|
||||||
|
readonly useCase: string;
|
||||||
|
readonly formData: Omit<TemplateFormData, "preset">;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CERTIFICATE_TEMPLATE_PRESETS: CertificateTemplatePreset[] = [
|
||||||
|
{
|
||||||
|
id: TEMPLATE_PRESET_IDS.TLS_SERVER,
|
||||||
|
name: "TLS Server Certificate",
|
||||||
|
description: "Standard TLS/SSL server certificate for HTTPS services and API endpoints.",
|
||||||
|
useCase: "Web servers, API endpoints, HTTPS services",
|
||||||
|
formData: {
|
||||||
|
name: "TLS Server Certificate",
|
||||||
|
description: "Standard TLS/SSL server certificate for HTTPS services and API endpoints.",
|
||||||
|
keyUsages: {
|
||||||
|
requiredUsages: [CertKeyUsageType.DIGITAL_SIGNATURE],
|
||||||
|
optionalUsages: [CertKeyUsageType.DIGITAL_SIGNATURE, CertKeyUsageType.KEY_ENCIPHERMENT]
|
||||||
|
},
|
||||||
|
extendedKeyUsages: {
|
||||||
|
requiredUsages: [CertExtendedKeyUsageType.SERVER_AUTH],
|
||||||
|
optionalUsages: [CertExtendedKeyUsageType.SERVER_AUTH]
|
||||||
|
},
|
||||||
|
validity: {
|
||||||
|
maxDuration: {
|
||||||
|
value: 365,
|
||||||
|
unit: CertDurationUnit.DAYS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAttributeType.COMMON_NAME,
|
||||||
|
include: CertSubjectAttributeInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
subjectAlternativeNames: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAlternativeNameType.DNS_NAME,
|
||||||
|
include: CertSanInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: CertSubjectAlternativeNameType.IP_ADDRESS,
|
||||||
|
include: CertSanInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
signatureAlgorithm: {
|
||||||
|
allowedAlgorithms: [...ALGORITHM_FAMILIES.ECDSA.signature]
|
||||||
|
},
|
||||||
|
keyAlgorithm: {
|
||||||
|
allowedKeyTypes: [...ALGORITHM_FAMILIES.ECDSA.key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TEMPLATE_PRESET_IDS.TLS_CLIENT,
|
||||||
|
name: "TLS Client Certificate",
|
||||||
|
description: "Client certificate for mutual TLS authentication and API access.",
|
||||||
|
useCase: "Client authentication, mTLS, API authentication",
|
||||||
|
formData: {
|
||||||
|
name: "TLS Client Certificate",
|
||||||
|
description: "Client certificate for mutual TLS authentication and API access.",
|
||||||
|
keyUsages: {
|
||||||
|
requiredUsages: [CertKeyUsageType.DIGITAL_SIGNATURE],
|
||||||
|
optionalUsages: [CertKeyUsageType.DIGITAL_SIGNATURE, CertKeyUsageType.KEY_AGREEMENT]
|
||||||
|
},
|
||||||
|
extendedKeyUsages: {
|
||||||
|
requiredUsages: [CertExtendedKeyUsageType.CLIENT_AUTH],
|
||||||
|
optionalUsages: [CertExtendedKeyUsageType.CLIENT_AUTH]
|
||||||
|
},
|
||||||
|
validity: {
|
||||||
|
maxDuration: {
|
||||||
|
value: 365,
|
||||||
|
unit: CertDurationUnit.DAYS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAttributeType.COMMON_NAME,
|
||||||
|
include: CertSubjectAttributeInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
subjectAlternativeNames: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAlternativeNameType.EMAIL,
|
||||||
|
include: CertSanInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: CertSubjectAlternativeNameType.DNS_NAME,
|
||||||
|
include: CertSanInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
signatureAlgorithm: {
|
||||||
|
allowedAlgorithms: [...ALGORITHM_FAMILIES.ECDSA.signature]
|
||||||
|
},
|
||||||
|
keyAlgorithm: {
|
||||||
|
allowedKeyTypes: [...ALGORITHM_FAMILIES.ECDSA.key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TEMPLATE_PRESET_IDS.CODE_SIGNING,
|
||||||
|
name: "Code Signing Certificate",
|
||||||
|
description:
|
||||||
|
"Certificate for signing software, executables, and packages. Requires hardware security modules.",
|
||||||
|
useCase: "Software signing, executable authentication, package validation",
|
||||||
|
formData: {
|
||||||
|
name: "Code Signing Certificate",
|
||||||
|
description:
|
||||||
|
"Certificate for signing software, executables, and packages. Requires hardware security modules.",
|
||||||
|
keyUsages: {
|
||||||
|
requiredUsages: [CertKeyUsageType.DIGITAL_SIGNATURE, CertKeyUsageType.NON_REPUDIATION],
|
||||||
|
optionalUsages: [CertKeyUsageType.DIGITAL_SIGNATURE, CertKeyUsageType.NON_REPUDIATION]
|
||||||
|
},
|
||||||
|
extendedKeyUsages: {
|
||||||
|
requiredUsages: [CertExtendedKeyUsageType.CODE_SIGNING],
|
||||||
|
optionalUsages: [
|
||||||
|
CertExtendedKeyUsageType.CODE_SIGNING,
|
||||||
|
CertExtendedKeyUsageType.TIME_STAMPING
|
||||||
|
]
|
||||||
|
},
|
||||||
|
validity: {
|
||||||
|
maxDuration: {
|
||||||
|
value: 365,
|
||||||
|
unit: CertDurationUnit.DAYS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAttributeType.COMMON_NAME,
|
||||||
|
include: CertSubjectAttributeInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
subjectAlternativeNames: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAlternativeNameType.EMAIL,
|
||||||
|
include: CertSanInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
signatureAlgorithm: {
|
||||||
|
allowedAlgorithms: [...ALGORITHM_FAMILIES.RSA.signature]
|
||||||
|
},
|
||||||
|
keyAlgorithm: {
|
||||||
|
allowedKeyTypes: [...ALGORITHM_FAMILIES.RSA.key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TEMPLATE_PRESET_IDS.DEVICE,
|
||||||
|
name: "Device Certificate",
|
||||||
|
description:
|
||||||
|
"Certificate for IoT devices and embedded systems authentication. IEEE 802.1AR compliant.",
|
||||||
|
useCase: "Device authentication, IoT security, embedded systems",
|
||||||
|
formData: {
|
||||||
|
name: "Device Certificate",
|
||||||
|
description:
|
||||||
|
"Certificate for IoT devices and embedded systems authentication. IEEE 802.1AR compliant.",
|
||||||
|
keyUsages: {
|
||||||
|
requiredUsages: [CertKeyUsageType.DIGITAL_SIGNATURE],
|
||||||
|
optionalUsages: [CertKeyUsageType.DIGITAL_SIGNATURE, CertKeyUsageType.KEY_AGREEMENT]
|
||||||
|
},
|
||||||
|
extendedKeyUsages: {
|
||||||
|
requiredUsages: [CertExtendedKeyUsageType.CLIENT_AUTH],
|
||||||
|
optionalUsages: [CertExtendedKeyUsageType.CLIENT_AUTH, CertExtendedKeyUsageType.SERVER_AUTH]
|
||||||
|
},
|
||||||
|
validity: {
|
||||||
|
maxDuration: {
|
||||||
|
value: 365,
|
||||||
|
unit: CertDurationUnit.DAYS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAttributeType.COMMON_NAME,
|
||||||
|
include: CertSubjectAttributeInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
subjectAlternativeNames: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAlternativeNameType.DNS_NAME,
|
||||||
|
include: CertSanInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: CertSubjectAlternativeNameType.IP_ADDRESS,
|
||||||
|
include: CertSanInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
signatureAlgorithm: {
|
||||||
|
allowedAlgorithms: [...ALGORITHM_FAMILIES.ECDSA.signature]
|
||||||
|
},
|
||||||
|
keyAlgorithm: {
|
||||||
|
allowedKeyTypes: [...ALGORITHM_FAMILIES.ECDSA.key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TEMPLATE_PRESET_IDS.USER,
|
||||||
|
name: "User Certificate",
|
||||||
|
description:
|
||||||
|
"Personal certificate for user authentication and email signing. FIPS 201 PIV compliant.",
|
||||||
|
useCase: "Personal authentication, smart cards, email protection",
|
||||||
|
formData: {
|
||||||
|
name: "User Certificate",
|
||||||
|
description:
|
||||||
|
"Personal certificate for user authentication and email signing. FIPS 201 PIV compliant.",
|
||||||
|
keyUsages: {
|
||||||
|
requiredUsages: [CertKeyUsageType.DIGITAL_SIGNATURE],
|
||||||
|
optionalUsages: [
|
||||||
|
CertKeyUsageType.DIGITAL_SIGNATURE,
|
||||||
|
CertKeyUsageType.KEY_ENCIPHERMENT,
|
||||||
|
CertKeyUsageType.KEY_AGREEMENT
|
||||||
|
]
|
||||||
|
},
|
||||||
|
extendedKeyUsages: {
|
||||||
|
requiredUsages: [
|
||||||
|
CertExtendedKeyUsageType.CLIENT_AUTH,
|
||||||
|
CertExtendedKeyUsageType.EMAIL_PROTECTION
|
||||||
|
],
|
||||||
|
optionalUsages: [
|
||||||
|
CertExtendedKeyUsageType.CLIENT_AUTH,
|
||||||
|
CertExtendedKeyUsageType.EMAIL_PROTECTION
|
||||||
|
]
|
||||||
|
},
|
||||||
|
validity: {
|
||||||
|
maxDuration: {
|
||||||
|
value: 365,
|
||||||
|
unit: CertDurationUnit.DAYS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAttributeType.COMMON_NAME,
|
||||||
|
include: CertSubjectAttributeInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
subjectAlternativeNames: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAlternativeNameType.EMAIL,
|
||||||
|
include: CertSanInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
signatureAlgorithm: {
|
||||||
|
allowedAlgorithms: [...ALGORITHM_FAMILIES.ECDSA.signature]
|
||||||
|
},
|
||||||
|
keyAlgorithm: {
|
||||||
|
allowedKeyTypes: [...ALGORITHM_FAMILIES.ECDSA.key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TEMPLATE_PRESET_IDS.EMAIL_PROTECTION,
|
||||||
|
name: "Email Protection Certificate",
|
||||||
|
description: "S/MIME certificate for email encryption and digital signing. RFC 8550 compliant.",
|
||||||
|
useCase: "Email encryption, digital signing, secure messaging",
|
||||||
|
formData: {
|
||||||
|
name: "Email Protection Certificate",
|
||||||
|
description:
|
||||||
|
"S/MIME certificate for email encryption and digital signing. RFC 8550 compliant.",
|
||||||
|
keyUsages: {
|
||||||
|
requiredUsages: [CertKeyUsageType.DIGITAL_SIGNATURE],
|
||||||
|
optionalUsages: [
|
||||||
|
CertKeyUsageType.DIGITAL_SIGNATURE,
|
||||||
|
CertKeyUsageType.KEY_ENCIPHERMENT,
|
||||||
|
CertKeyUsageType.KEY_AGREEMENT
|
||||||
|
]
|
||||||
|
},
|
||||||
|
extendedKeyUsages: {
|
||||||
|
requiredUsages: [CertExtendedKeyUsageType.EMAIL_PROTECTION],
|
||||||
|
optionalUsages: [CertExtendedKeyUsageType.EMAIL_PROTECTION]
|
||||||
|
},
|
||||||
|
validity: {
|
||||||
|
maxDuration: {
|
||||||
|
value: 365,
|
||||||
|
unit: CertDurationUnit.DAYS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAttributeType.COMMON_NAME,
|
||||||
|
include: CertSubjectAttributeInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
subjectAlternativeNames: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAlternativeNameType.EMAIL,
|
||||||
|
include: CertSanInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
signatureAlgorithm: {
|
||||||
|
allowedAlgorithms: [...ALGORITHM_FAMILIES.RSA.signature]
|
||||||
|
},
|
||||||
|
keyAlgorithm: {
|
||||||
|
allowedKeyTypes: [...ALGORITHM_FAMILIES.RSA.key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TEMPLATE_PRESET_IDS.DUAL_PURPOSE_SERVER,
|
||||||
|
name: "Dual-Purpose Server Certificate",
|
||||||
|
description:
|
||||||
|
"Certificate for services requiring both server and client authentication capabilities",
|
||||||
|
useCase: "Microservices, service mesh, dual authentication",
|
||||||
|
formData: {
|
||||||
|
name: "Dual-Purpose Server Certificate",
|
||||||
|
description:
|
||||||
|
"Certificate for services requiring both server and client authentication capabilities",
|
||||||
|
keyUsages: {
|
||||||
|
requiredUsages: [CertKeyUsageType.DIGITAL_SIGNATURE],
|
||||||
|
optionalUsages: [
|
||||||
|
CertKeyUsageType.DIGITAL_SIGNATURE,
|
||||||
|
CertKeyUsageType.KEY_ENCIPHERMENT,
|
||||||
|
CertKeyUsageType.KEY_AGREEMENT
|
||||||
|
]
|
||||||
|
},
|
||||||
|
extendedKeyUsages: {
|
||||||
|
requiredUsages: [
|
||||||
|
CertExtendedKeyUsageType.SERVER_AUTH,
|
||||||
|
CertExtendedKeyUsageType.CLIENT_AUTH
|
||||||
|
],
|
||||||
|
optionalUsages: [CertExtendedKeyUsageType.SERVER_AUTH, CertExtendedKeyUsageType.CLIENT_AUTH]
|
||||||
|
},
|
||||||
|
validity: {
|
||||||
|
maxDuration: {
|
||||||
|
value: 365,
|
||||||
|
unit: CertDurationUnit.DAYS
|
||||||
|
}
|
||||||
|
},
|
||||||
|
attributes: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAttributeType.COMMON_NAME,
|
||||||
|
include: CertSubjectAttributeInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
subjectAlternativeNames: [
|
||||||
|
{
|
||||||
|
type: CertSubjectAlternativeNameType.DNS_NAME,
|
||||||
|
include: CertSanInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: CertSubjectAlternativeNameType.IP_ADDRESS,
|
||||||
|
include: CertSanInclude.OPTIONAL,
|
||||||
|
value: ["*"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
signatureAlgorithm: {
|
||||||
|
allowedAlgorithms: [...ALGORITHM_FAMILIES.ECDSA.signature]
|
||||||
|
},
|
||||||
|
keyAlgorithm: {
|
||||||
|
allowedKeyTypes: [...ALGORITHM_FAMILIES.ECDSA.key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
Reference in New Issue
Block a user