mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-21 07:27:58 +00:00
PKI revamp: general improvements
This commit is contained in:
@@ -52,7 +52,7 @@ export const PoliciesPage = () => {
|
||||
/>
|
||||
|
||||
<Tabs value={activeTab} onValueChange={(value) => setActiveTab(value as TabSections)}>
|
||||
<TabList className="mb-6 w-full">
|
||||
<TabList className="w-full">
|
||||
<div className="flex w-full border-b border-mineshaft-600">
|
||||
<Tab value={TabSections.CertificateProfiles}>Certificate Profiles</Tab>
|
||||
<Tab value={TabSections.CertificateTemplatesV2}>Certificate Templates</Tab>
|
||||
|
||||
+47
-8
@@ -27,8 +27,20 @@ import { useListCertificateTemplatesV2 } from "@app/hooks/api/certificateTemplat
|
||||
|
||||
const createSchema = z
|
||||
.object({
|
||||
slug: z.string().trim().min(1, "Profile slug is required"),
|
||||
description: z.string().optional(),
|
||||
slug: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1, "Profile slug is required")
|
||||
.max(255, "Profile slug must be less than 255 characters")
|
||||
.regex(
|
||||
/^[a-zA-Z0-9-_]+$/,
|
||||
"Profile slug must contain only letters, numbers, hyphens, and underscores"
|
||||
),
|
||||
description: z
|
||||
.string()
|
||||
.trim()
|
||||
.max(1000, "Description must be less than 1000 characters")
|
||||
.optional(),
|
||||
enrollmentType: z.enum(["api", "est"]),
|
||||
certificateAuthorityId: z.string().min(1, "Certificate Authority is required"),
|
||||
certificateTemplateId: z.string().min(1, "Certificate Template is required"),
|
||||
@@ -36,8 +48,19 @@ const createSchema = z
|
||||
.object({
|
||||
disableBootstrapCaValidation: z.boolean().optional(),
|
||||
passphrase: z.string().min(1, "EST passphrase is required"),
|
||||
caChain: z.string().min(1, "EST CA chain is required")
|
||||
caChain: z.string().min(1, "EST CA chain is required").optional()
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
if (!data.disableBootstrapCaValidation && !data.caChain) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message: "EST CA chain is required"
|
||||
}
|
||||
)
|
||||
.optional(),
|
||||
apiConfig: z
|
||||
.object({
|
||||
@@ -63,8 +86,20 @@ const createSchema = z
|
||||
|
||||
const editSchema = z
|
||||
.object({
|
||||
slug: z.string().trim().min(1, "Profile slug is required"),
|
||||
description: z.string().optional(),
|
||||
slug: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1, "Profile slug is required")
|
||||
.max(255, "Profile slug must be less than 255 characters")
|
||||
.regex(
|
||||
/^[a-zA-Z0-9-_]+$/,
|
||||
"Profile slug must contain only letters, numbers, hyphens, and underscores"
|
||||
),
|
||||
description: z
|
||||
.string()
|
||||
.trim()
|
||||
.max(1000, "Description must be less than 1000 characters")
|
||||
.optional(),
|
||||
enrollmentType: z.enum(["api", "est"]),
|
||||
certificateAuthorityId: z.string().optional(),
|
||||
certificateTemplateId: z.string().optional(),
|
||||
@@ -136,7 +171,7 @@ export const CreateProfileModal = ({ isOpen, onClose, profile, mode = "create" }
|
||||
estConfig: {
|
||||
disableBootstrapCaValidation: profile.estConfig?.disableBootstrapCaValidation || false,
|
||||
passphrase: "",
|
||||
caChain: ""
|
||||
caChain: undefined
|
||||
},
|
||||
apiConfig: {
|
||||
autoRenew: profile.apiConfig?.autoRenew || false,
|
||||
@@ -193,7 +228,11 @@ export const CreateProfileModal = ({ isOpen, onClose, profile, mode = "create" }
|
||||
};
|
||||
|
||||
if (data.enrollmentType === "est" && data.estConfig) {
|
||||
createData.estConfig = data.estConfig;
|
||||
createData.estConfig = {
|
||||
passphrase: data.estConfig.passphrase,
|
||||
caChain: data.estConfig.caChain || "",
|
||||
disableBootstrapCaValidation: data.estConfig.disableBootstrapCaValidation
|
||||
};
|
||||
} else if (data.enrollmentType === "api" && data.apiConfig) {
|
||||
createData.apiConfig = data.apiConfig;
|
||||
}
|
||||
@@ -241,7 +280,7 @@ export const CreateProfileModal = ({ isOpen, onClose, profile, mode = "create" }
|
||||
name="slug"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Profile Slug"
|
||||
label="Name"
|
||||
isRequired
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
|
||||
+1
-1
@@ -150,7 +150,7 @@ export const ProfileRow = ({ profile, onEditProfile, onDeleteProfile }: Props) =
|
||||
<Tr key={profile.id} className="h-10 transition-colors duration-100 hover:bg-mineshaft-700">
|
||||
<Td>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="font-medium text-mineshaft-100">{profile.slug}</div>
|
||||
<div className="text-mineshaft-300">{profile.slug}</div>
|
||||
{profile.description && (
|
||||
<Tooltip content={profile.description}>
|
||||
<FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-400" />
|
||||
|
||||
+9
-7
@@ -362,8 +362,8 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
||||
return {
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
subject: subject.length > 0 ? subject : undefined,
|
||||
sans: sans.length > 0 ? sans : undefined,
|
||||
subject,
|
||||
sans,
|
||||
keyUsages: Object.keys(keyUsages).length > 0 ? keyUsages : undefined,
|
||||
extendedKeyUsages: Object.keys(extendedKeyUsages).length > 0 ? extendedKeyUsages : undefined,
|
||||
algorithms: Object.keys(algorithms).length > 0 ? algorithms : undefined,
|
||||
@@ -614,7 +614,7 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
||||
required
|
||||
/>
|
||||
|
||||
{watchedAttributes.length > 1 && (
|
||||
{watchedAttributes.length > 0 && (
|
||||
<IconButton
|
||||
ariaLabel="Remove Attribute"
|
||||
variant="plain"
|
||||
@@ -672,7 +672,7 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
||||
};
|
||||
setValue("subjectAlternativeNames", newSans);
|
||||
}}
|
||||
className="w-24"
|
||||
className="w-36"
|
||||
>
|
||||
{SAN_TYPE_OPTIONS.map((type) => (
|
||||
<SelectItem key={type} value={type}>
|
||||
@@ -719,7 +719,7 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
||||
required
|
||||
/>
|
||||
|
||||
{watchedSans.length > 1 && (
|
||||
{watchedSans.length > 0 && (
|
||||
<IconButton
|
||||
ariaLabel="Remove SAN"
|
||||
variant="plain"
|
||||
@@ -755,7 +755,7 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h4 className="mb-3 text-sm font-medium text-mineshaft-200">
|
||||
Signature Algorithms
|
||||
Allowed Signature Algorithms
|
||||
</h4>
|
||||
<Controller
|
||||
control={control}
|
||||
@@ -799,7 +799,9 @@ export const CreateTemplateModal = ({ isOpen, onClose, template, mode = "create"
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 className="mb-3 text-sm font-medium text-mineshaft-200">Key Algorithms</h4>
|
||||
<h4 className="mb-3 text-sm font-medium text-mineshaft-200">
|
||||
Allowed Key Algorithms
|
||||
</h4>
|
||||
<Controller
|
||||
control={control}
|
||||
name="keyAlgorithm.allowedKeyTypes"
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ export const TemplateList = ({ onEditTemplate, onDeleteTemplate }: Props) => {
|
||||
>
|
||||
<Td>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="font-medium">{template.name}</div>
|
||||
<div className="text-mineshaft-300">{template.name}</div>
|
||||
{template.description && (
|
||||
<Tooltip content={template.description}>
|
||||
<FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-400" />
|
||||
|
||||
+31
-6
@@ -50,8 +50,20 @@ export const uiKeyAlgorithmSchema = z.object({
|
||||
});
|
||||
|
||||
export const templateSchema = z.object({
|
||||
name: z.string().trim().min(1, "Template name is required"),
|
||||
description: z.string().optional(),
|
||||
name: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1, "Template name is required")
|
||||
.max(255, "Template name must be less than 255 characters")
|
||||
.regex(
|
||||
/^[a-zA-Z0-9-_]+$/,
|
||||
"Template name must contain only letters, numbers, hyphens, and underscores"
|
||||
),
|
||||
description: z
|
||||
.string()
|
||||
.trim()
|
||||
.max(1000, "Description must be less than 1000 characters")
|
||||
.optional(),
|
||||
attributes: z.array(uiAttributeSchema).optional(),
|
||||
subjectAlternativeNames: z.array(uiSanSchema).optional(),
|
||||
keyUsages: uiKeyUsagesSchema.optional(),
|
||||
@@ -86,8 +98,20 @@ export const apiSanSchema = z
|
||||
});
|
||||
|
||||
export const apiTemplateSchema = z.object({
|
||||
name: z.string().trim().min(1, "Template name is required"),
|
||||
description: z.string().optional(),
|
||||
name: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1, "Template name is required")
|
||||
.max(255, "Template name must be less than 255 characters")
|
||||
.regex(
|
||||
/^[a-zA-Z0-9-_]+$/,
|
||||
"Template name must contain only letters, numbers, hyphens, and underscores"
|
||||
),
|
||||
description: z
|
||||
.string()
|
||||
.trim()
|
||||
.max(1000, "Description must be less than 1000 characters")
|
||||
.optional(),
|
||||
subject: z.array(apiSubjectSchema).optional(),
|
||||
sans: z.array(apiSanSchema).optional(),
|
||||
keyUsages: z
|
||||
@@ -106,14 +130,15 @@ export const apiTemplateSchema = z.object({
|
||||
.optional(),
|
||||
algorithms: z
|
||||
.object({
|
||||
signature: z.array(z.string()).optional(),
|
||||
keyAlgorithm: z.array(z.string()).optional()
|
||||
signature: z.array(z.string().trim().min(1, "Algorithm cannot be empty")).optional(),
|
||||
keyAlgorithm: z.array(z.string().trim().min(1, "Algorithm cannot be empty")).optional()
|
||||
})
|
||||
.optional(),
|
||||
validity: z
|
||||
.object({
|
||||
max: z
|
||||
.string()
|
||||
.trim()
|
||||
.regex(/^[1-9]\d*[dhmy]$/, "Must be in format like '365d', '12m', '1y', or '24h'")
|
||||
.optional()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user