mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 08:27:22 +00:00
Add CA certs to Chef sync and make field names more dynamic
This commit is contained in:
@@ -64,7 +64,7 @@ export const CreatePkiSyncModal = ({
|
||||
"Add Sync"
|
||||
)
|
||||
}
|
||||
className="max-w-2xl"
|
||||
className="max-w-3xl"
|
||||
bodyClassName="overflow-visible"
|
||||
subTitle={
|
||||
selectedSync ? undefined : "Select a third-party service to sync certificates to."
|
||||
|
||||
@@ -15,11 +15,13 @@ type Props = {
|
||||
export const EditPkiSyncModal = ({ pkiSync, onOpenChange, fields, ...props }: Props) => {
|
||||
if (!pkiSync) return null;
|
||||
|
||||
const modalClassName = fields === PkiSyncEditFields.Mappings ? "max-w-4xl" : "max-w-2xl";
|
||||
|
||||
return (
|
||||
<Modal {...props} onOpenChange={onOpenChange}>
|
||||
<ModalContent
|
||||
title={<PkiSyncModalHeader isConfigured destination={pkiSync.destination} />}
|
||||
className="max-w-2xl"
|
||||
className={modalClassName}
|
||||
bodyClassName="overflow-visible"
|
||||
>
|
||||
<EditPkiSyncForm onComplete={() => onOpenChange(false)} fields={fields} pkiSync={pkiSync} />
|
||||
|
||||
@@ -4,7 +4,6 @@ import { faInfoCircle } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Tab } from "@headlessui/react";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Button, FormControl, Switch } from "@app/components/v2";
|
||||
@@ -16,6 +15,7 @@ import { PkiSyncFormSchema, TPkiSyncForm } from "./schemas/pki-sync-schema";
|
||||
import { PkiSyncCertificatesFields } from "./PkiSyncCertificatesFields";
|
||||
import { PkiSyncDestinationFields } from "./PkiSyncDestinationFields";
|
||||
import { PkiSyncDetailsFields } from "./PkiSyncDetailsFields";
|
||||
import { PkiSyncFieldMappingsFields } from "./PkiSyncFieldMappingsFields";
|
||||
import { PkiSyncOptionsFields } from "./PkiSyncOptionsFields";
|
||||
import { PkiSyncReviewFields } from "./PkiSyncReviewFields";
|
||||
|
||||
@@ -26,13 +26,38 @@ type Props = {
|
||||
initialData?: any;
|
||||
};
|
||||
|
||||
const FORM_TABS: { name: string; key: string; fields: (keyof TPkiSyncForm)[] }[] = [
|
||||
{ name: "Destination", key: "destination", fields: ["connection", "destinationConfig"] },
|
||||
{ name: "Sync Options", key: "options", fields: ["syncOptions"] },
|
||||
{ name: "Details", key: "details", fields: ["name", "description"] },
|
||||
{ name: "Certificates", key: "certificates", fields: ["certificateIds"] },
|
||||
{ name: "Review", key: "review", fields: [] }
|
||||
];
|
||||
const getFormTabs = (
|
||||
destination: PkiSync
|
||||
): { name: string; key: string; fields: (keyof TPkiSyncForm)[] }[] => {
|
||||
const baseTabs = [
|
||||
{
|
||||
name: "Destination",
|
||||
key: "destination",
|
||||
fields: ["connection", "destinationConfig"] as (keyof TPkiSyncForm)[]
|
||||
},
|
||||
{ name: "Sync Options", key: "options", fields: ["syncOptions"] as (keyof TPkiSyncForm)[] }
|
||||
];
|
||||
|
||||
if (destination === PkiSync.Chef) {
|
||||
baseTabs.push({
|
||||
name: "Mappings",
|
||||
key: "mappings",
|
||||
fields: ["syncOptions"] as (keyof TPkiSyncForm)[]
|
||||
});
|
||||
}
|
||||
|
||||
baseTabs.push(
|
||||
{ name: "Details", key: "details", fields: ["name", "description"] as (keyof TPkiSyncForm)[] },
|
||||
{
|
||||
name: "Certificates",
|
||||
key: "certificates",
|
||||
fields: ["certificateIds"] as (keyof TPkiSyncForm)[]
|
||||
},
|
||||
{ name: "Review", key: "review", fields: [] as (keyof TPkiSyncForm)[] }
|
||||
);
|
||||
|
||||
return baseTabs;
|
||||
};
|
||||
|
||||
export const CreatePkiSyncForm = ({ destination, onComplete, onCancel, initialData }: Props) => {
|
||||
const createPkiSync = useCreatePkiSync();
|
||||
@@ -42,6 +67,7 @@ export const CreatePkiSyncForm = ({ destination, onComplete, onCancel, initialDa
|
||||
const [showConfirmation, setShowConfirmation] = useState(false);
|
||||
|
||||
const [selectedTabIndex, setSelectedTabIndex] = useState(0);
|
||||
const FORM_TABS = getFormTabs(destination);
|
||||
|
||||
const { syncOption } = usePkiSyncOption(destination);
|
||||
|
||||
@@ -55,7 +81,15 @@ export const CreatePkiSyncForm = ({ destination, onComplete, onCancel, initialDa
|
||||
canImportCertificates: false,
|
||||
canRemoveCertificates: false,
|
||||
preserveArn: true,
|
||||
certificateNameSchema: syncOption?.defaultCertificateNameSchema
|
||||
certificateNameSchema: syncOption?.defaultCertificateNameSchema,
|
||||
...(destination === PkiSync.Chef && {
|
||||
fieldMappings: {
|
||||
certificate: "certificate",
|
||||
privateKey: "private_key",
|
||||
certificateChain: "certificate_chain",
|
||||
caCertificate: "ca_certificate"
|
||||
}
|
||||
})
|
||||
},
|
||||
...initialData
|
||||
} as Partial<TPkiSyncForm>,
|
||||
@@ -78,11 +112,10 @@ export const CreatePkiSyncForm = ({ destination, onComplete, onCancel, initialDa
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: `Successfully created ${destinationName} Certificate Sync${
|
||||
certificateIds && certificateIds.length > 0
|
||||
text: `Successfully created ${destinationName} Certificate Sync${certificateIds && certificateIds.length > 0
|
||||
? ` with ${certificateIds.length} certificate(s)`
|
||||
: ""
|
||||
}`,
|
||||
}`,
|
||||
type: "success"
|
||||
});
|
||||
onComplete(pkiSync);
|
||||
@@ -167,10 +200,10 @@ export const CreatePkiSyncForm = ({ destination, onComplete, onCancel, initialDa
|
||||
);
|
||||
|
||||
return (
|
||||
<form className={twMerge(isFinalStep && "max-h-[70vh] overflow-y-auto")}>
|
||||
<form className="flex max-h-[70vh] flex-col overflow-hidden">
|
||||
<FormProvider {...formMethods}>
|
||||
<Tab.Group selectedIndex={selectedTabIndex} onChange={setSelectedTabIndex}>
|
||||
<Tab.List className="-pb-1 mb-6 w-full border-b-2 border-mineshaft-600">
|
||||
<Tab.List className="-pb-1 mb-6 w-full flex-shrink-0 border-b-2 border-mineshaft-600">
|
||||
{FORM_TABS.map((tab, index) => (
|
||||
<Tab
|
||||
onClick={async (e) => {
|
||||
@@ -179,10 +212,9 @@ export const CreatePkiSyncForm = ({ destination, onComplete, onCancel, initialDa
|
||||
setSelectedTabIndex((prev) => (isEnabled ? index : prev));
|
||||
}}
|
||||
className={({ selected }) =>
|
||||
`-mb-[0.14rem] whitespace-nowrap ${index > selectedTabIndex ? "opacity-30" : ""} px-4 py-2 text-sm font-medium outline-hidden disabled:opacity-60 ${
|
||||
selected
|
||||
? "border-b-2 border-mineshaft-300 text-mineshaft-200"
|
||||
: "text-bunker-300"
|
||||
`-mb-[0.14rem] whitespace-nowrap ${index > selectedTabIndex ? "opacity-30" : ""} px-4 py-2 text-sm font-medium outline-hidden disabled:opacity-60 ${selected
|
||||
? "border-b-2 border-mineshaft-300 text-mineshaft-200"
|
||||
: "text-bunker-300"
|
||||
}`
|
||||
}
|
||||
key={tab.key}
|
||||
@@ -191,11 +223,11 @@ export const CreatePkiSyncForm = ({ destination, onComplete, onCancel, initialDa
|
||||
</Tab>
|
||||
))}
|
||||
</Tab.List>
|
||||
<Tab.Panels>
|
||||
<Tab.Panel>
|
||||
<Tab.Panels className="flex-1 overflow-y-auto">
|
||||
<Tab.Panel className="max-h-full overflow-y-auto">
|
||||
<PkiSyncDestinationFields />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<Tab.Panel className="max-h-full overflow-y-auto">
|
||||
<PkiSyncOptionsFields destination={destination} />
|
||||
<Controller
|
||||
control={control}
|
||||
@@ -225,20 +257,25 @@ export const CreatePkiSyncForm = ({ destination, onComplete, onCancel, initialDa
|
||||
}}
|
||||
/>
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
{destination === PkiSync.Chef && (
|
||||
<Tab.Panel className="max-h-full overflow-y-auto">
|
||||
<PkiSyncFieldMappingsFields destination={destination} />
|
||||
</Tab.Panel>
|
||||
)}
|
||||
<Tab.Panel className="max-h-full overflow-y-auto">
|
||||
<PkiSyncDetailsFields />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<Tab.Panel className="max-h-full overflow-y-auto">
|
||||
<PkiSyncCertificatesFields />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<Tab.Panel className="max-h-full overflow-y-auto">
|
||||
<PkiSyncReviewFields />
|
||||
</Tab.Panel>
|
||||
</Tab.Panels>
|
||||
</Tab.Group>
|
||||
</FormProvider>
|
||||
|
||||
<div className="flex w-full flex-row-reverse justify-between gap-4 pt-4">
|
||||
<div className="mt-4 flex w-full flex-shrink-0 flex-row-reverse justify-between gap-4 border-t border-mineshaft-600 pt-4">
|
||||
<Button onClick={handleNext} colorSchema="secondary">
|
||||
{isFinalStep ? "Create Sync" : "Next"}
|
||||
</Button>
|
||||
|
||||
@@ -11,6 +11,7 @@ import { TPkiSync, useUpdatePkiSync } from "@app/hooks/api/pkiSyncs";
|
||||
import { TUpdatePkiSyncForm, UpdatePkiSyncFormSchema } from "./schemas/pki-sync-schema";
|
||||
import { PkiSyncDestinationFields } from "./PkiSyncDestinationFields";
|
||||
import { PkiSyncDetailsFields } from "./PkiSyncDetailsFields";
|
||||
import { PkiSyncFieldMappingsFields } from "./PkiSyncFieldMappingsFields";
|
||||
import { PkiSyncOptionsFields } from "./PkiSyncOptionsFields";
|
||||
import { PkiSyncSourceFields } from "./PkiSyncSourceFields";
|
||||
|
||||
@@ -66,6 +67,9 @@ export const EditPkiSyncForm = ({ pkiSync, fields, onComplete }: Props) => {
|
||||
case PkiSyncEditFields.Options:
|
||||
Component = <PkiSyncOptionsFields destination={pkiSync.destination} />;
|
||||
break;
|
||||
case PkiSyncEditFields.Mappings:
|
||||
Component = <PkiSyncFieldMappingsFields destination={pkiSync.destination} />;
|
||||
break;
|
||||
case PkiSyncEditFields.Source:
|
||||
Component = <PkiSyncSourceFields />;
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
|
||||
import { FormControl, Input } from "@app/components/v2";
|
||||
import { PkiSync } from "@app/hooks/api/pkiSyncs";
|
||||
|
||||
import { TPkiSyncForm } from "./schemas/pki-sync-schema";
|
||||
|
||||
type Props = {
|
||||
destination?: PkiSync;
|
||||
};
|
||||
|
||||
export const PkiSyncFieldMappingsFields = ({ destination }: Props) => {
|
||||
const { control, watch } = useFormContext<TPkiSyncForm>();
|
||||
const currentDestination = destination || watch("destination");
|
||||
|
||||
// Only show field mappings for Chef
|
||||
if (currentDestination !== PkiSync.Chef) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className="mb-4 text-sm text-bunker-300">
|
||||
Configure how certificate fields are mapped to your Chef data bag items.
|
||||
</p>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<Controller
|
||||
control={control}
|
||||
name="syncOptions.fieldMappings.certificate"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
label="Certificate Field"
|
||||
tooltipText="The field name used to store the certificate content in the Chef data bag item."
|
||||
>
|
||||
<Input {...field} placeholder="certificate" />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
control={control}
|
||||
name="syncOptions.fieldMappings.privateKey"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
label="Private Key Field"
|
||||
tooltipText="The field name used to store the private key content in the Chef data bag item."
|
||||
>
|
||||
<Input {...field} placeholder="private_key" />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
control={control}
|
||||
name="syncOptions.fieldMappings.certificateChain"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
label="Certificate Chain Field"
|
||||
tooltipText="The field name used to store the certificate chain content in the Chef data bag item."
|
||||
>
|
||||
<Input {...field} placeholder="certificate_chain" />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
control={control}
|
||||
name="syncOptions.fieldMappings.caCertificate"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
isError={Boolean(error)}
|
||||
errorText={error?.message}
|
||||
label="CA Certificate Field"
|
||||
tooltipText="The field name used to store the CA certificate content in the Chef data bag item."
|
||||
>
|
||||
<Input {...field} placeholder="ca_certificate" />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 rounded-lg border border-mineshaft-600 bg-mineshaft-800 p-4">
|
||||
<h4 className="mb-2 text-sm font-medium text-mineshaft-100">Preview JSON Structure</h4>
|
||||
<pre className="text-xs text-bunker-300">
|
||||
{`{
|
||||
"id": "certificate-item-name",
|
||||
"${watch("syncOptions.fieldMappings.certificate") || "certificate"}": "<certificate-content>",
|
||||
"${watch("syncOptions.fieldMappings.privateKey") || "private_key"}": "<private-key-content>",
|
||||
"${watch("syncOptions.fieldMappings.certificateChain") || "certificate_chain"}": "<certificate-chain-content>",
|
||||
"${watch("syncOptions.fieldMappings.caCertificate") || "ca_certificate"}": "<ca-certificate-content>"
|
||||
}`}
|
||||
</pre>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
+20
-1
@@ -4,6 +4,19 @@ import { PkiSync } from "@app/hooks/api/pkiSyncs";
|
||||
|
||||
import { BasePkiSyncSchema } from "./base-pki-sync-schema";
|
||||
|
||||
const ChefFieldMappingsSchema = z.object({
|
||||
certificate: z.string().min(1, "Certificate field name is required").default("certificate"),
|
||||
privateKey: z.string().min(1, "Private key field name is required").default("private_key"),
|
||||
certificateChain: z
|
||||
.string()
|
||||
.min(1, "Certificate chain field name is required")
|
||||
.default("certificate_chain"),
|
||||
caCertificate: z
|
||||
.string()
|
||||
.min(1, "CA certificate field name is required")
|
||||
.default("ca_certificate")
|
||||
});
|
||||
|
||||
const ChefSyncOptionsSchema = z.object({
|
||||
canImportCertificates: z.boolean().default(false),
|
||||
canRemoveCertificates: z.boolean().default(true),
|
||||
@@ -44,7 +57,13 @@ const ChefSyncOptionsSchema = z.object({
|
||||
message:
|
||||
"Certificate item name schema must include exactly one {{certificateId}} placeholder. It can also include {{environment}}, {{profileId}}, {{commonName}}, or {{friendlyName}} placeholders. Only alphanumeric characters (a-z, A-Z, 0-9), hyphens (-), and underscores (_) are allowed besides the placeholders."
|
||||
}
|
||||
)
|
||||
),
|
||||
fieldMappings: ChefFieldMappingsSchema.optional().default({
|
||||
certificate: "certificate",
|
||||
privateKey: "private_key",
|
||||
certificateChain: "certificate_chain",
|
||||
caCertificate: "ca_certificate"
|
||||
})
|
||||
});
|
||||
|
||||
export const ChefPkiSyncDestinationSchema = BasePkiSyncSchema(ChefSyncOptionsSchema).merge(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export enum PkiSyncEditFields {
|
||||
Details = "details",
|
||||
Options = "options",
|
||||
Mappings = "mappings",
|
||||
Source = "source",
|
||||
Destination = "destination"
|
||||
}
|
||||
|
||||
@@ -2,6 +2,13 @@ import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
|
||||
import { CertificateSyncStatus, PkiSyncStatus } from "../enums";
|
||||
|
||||
export type TChefFieldMappings = {
|
||||
certificate: string;
|
||||
privateKey: string;
|
||||
certificateChain: string;
|
||||
caCertificate: string;
|
||||
};
|
||||
|
||||
export type RootPkiSyncOptions = {
|
||||
canImportCertificates: boolean;
|
||||
canRemoveCertificates: boolean;
|
||||
@@ -11,6 +18,7 @@ export type RootPkiSyncOptions = {
|
||||
enableVersioning?: boolean;
|
||||
preserveItemOnRenewal?: boolean;
|
||||
updateExistingCertificates?: boolean;
|
||||
fieldMappings?: TChefFieldMappings;
|
||||
};
|
||||
|
||||
export type TRootPkiSync = {
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
PkiSyncCertificatesSection,
|
||||
PkiSyncDestinationSection,
|
||||
PkiSyncDetailsSection,
|
||||
PkiSyncFieldMappingsSection,
|
||||
PkiSyncOptionsSection
|
||||
} from "./components";
|
||||
|
||||
@@ -63,6 +64,7 @@ const PageContent = () => {
|
||||
|
||||
const handleEditDetails = () => handlePopUpOpen("editSync", PkiSyncEditFields.Details);
|
||||
const handleEditOptions = () => handlePopUpOpen("editSync", PkiSyncEditFields.Options);
|
||||
const handleEditMappings = () => handlePopUpOpen("editSync", PkiSyncEditFields.Mappings);
|
||||
const handleEditDestination = () => handlePopUpOpen("editSync", PkiSyncEditFields.Destination);
|
||||
|
||||
return (
|
||||
@@ -103,6 +105,7 @@ const PageContent = () => {
|
||||
<div className="mr-4 flex w-72 flex-col gap-4">
|
||||
<PkiSyncDetailsSection pkiSync={pkiSync} onEditDetails={handleEditDetails} />
|
||||
<PkiSyncOptionsSection pkiSync={pkiSync} onEditOptions={handleEditOptions} />
|
||||
<PkiSyncFieldMappingsSection pkiSync={pkiSync} onEditMappings={handleEditMappings} />
|
||||
</div>
|
||||
<div className="flex flex-1 flex-col gap-4">
|
||||
<PkiSyncDestinationSection
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
import { subject } from "@casl/ability";
|
||||
import { faEdit } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { IconButton } from "@app/components/v2";
|
||||
import { Badge } from "@app/components/v3";
|
||||
import { ProjectPermissionSub } from "@app/context";
|
||||
import { ProjectPermissionPkiSyncActions } from "@app/context/ProjectPermissionContext/types";
|
||||
import { PkiSync, TPkiSync } from "@app/hooks/api/pkiSyncs";
|
||||
|
||||
const GenericFieldLabel = ({
|
||||
label,
|
||||
children,
|
||||
labelClassName
|
||||
}: {
|
||||
label: string;
|
||||
children: React.ReactNode;
|
||||
labelClassName?: string;
|
||||
}) => (
|
||||
<div className="mb-3">
|
||||
<p className={`mb-1 text-sm font-medium text-mineshaft-300 ${labelClassName || ""}`}>{label}</p>
|
||||
<div className="text-sm text-mineshaft-400">{children}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
type Props = {
|
||||
pkiSync: TPkiSync;
|
||||
onEditMappings: VoidFunction;
|
||||
};
|
||||
|
||||
export const PkiSyncFieldMappingsSection = ({ pkiSync, onEditMappings }: Props) => {
|
||||
// Only show for Chef PKI syncs
|
||||
if (pkiSync.destination !== PkiSync.Chef) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fieldMappings = pkiSync.syncOptions?.fieldMappings;
|
||||
|
||||
const permissionSubject = subject(ProjectPermissionSub.PkiSyncs, {
|
||||
subscriberId: pkiSync.subscriberId || ""
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex w-full flex-col gap-3 rounded-lg border border-mineshaft-600 bg-mineshaft-900 px-4 py-3">
|
||||
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-2">
|
||||
<h3 className="text-lg font-medium text-mineshaft-100">Field Mappings</h3>
|
||||
<ProjectPermissionCan I={ProjectPermissionPkiSyncActions.Edit} a={permissionSubject}>
|
||||
{(isAllowed) => (
|
||||
<IconButton
|
||||
variant="plain"
|
||||
colorSchema="secondary"
|
||||
isDisabled={!isAllowed}
|
||||
ariaLabel="Edit field mappings"
|
||||
onClick={onEditMappings}
|
||||
>
|
||||
<FontAwesomeIcon icon={faEdit} />
|
||||
</IconButton>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
</div>
|
||||
<div className="pt-1">
|
||||
<div className="space-y-3">
|
||||
<GenericFieldLabel label="Certificate Field">
|
||||
<Badge variant="neutral" className="max-w-full truncate">
|
||||
{fieldMappings?.certificate || "certificate"}
|
||||
</Badge>
|
||||
</GenericFieldLabel>
|
||||
|
||||
<GenericFieldLabel label="Private Key Field">
|
||||
<Badge variant="neutral" className="max-w-full truncate">
|
||||
{fieldMappings?.privateKey || "private_key"}
|
||||
</Badge>
|
||||
</GenericFieldLabel>
|
||||
|
||||
<GenericFieldLabel label="Certificate Chain Field">
|
||||
<Badge variant="neutral" className="max-w-full truncate">
|
||||
{fieldMappings?.certificateChain || "certificate_chain"}
|
||||
</Badge>
|
||||
</GenericFieldLabel>
|
||||
|
||||
<GenericFieldLabel label="CA Certificate Field">
|
||||
<Badge variant="neutral" className="max-w-full truncate">
|
||||
{fieldMappings?.caCertificate || "ca_certificate"}
|
||||
</Badge>
|
||||
</GenericFieldLabel>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -3,5 +3,6 @@ export { PkiSyncAuditLogsSection } from "./PkiSyncAuditLogsSection";
|
||||
export { PkiSyncCertificatesSection } from "./PkiSyncCertificatesSection";
|
||||
export { PkiSyncDestinationSection } from "./PkiSyncDestinationSection";
|
||||
export { PkiSyncDetailsSection } from "./PkiSyncDetailsSection";
|
||||
export { PkiSyncFieldMappingsSection } from "./PkiSyncFieldMappingsSection";
|
||||
export { PkiSyncOptionsSection } from "./PkiSyncOptionsSection";
|
||||
export { PkiSyncSourceSection } from "./PkiSyncSourceSection";
|
||||
|
||||
Reference in New Issue
Block a user