mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 04:27:29 +00:00
fix: review changes
This commit is contained in:
@@ -26,7 +26,7 @@ const AwsConnectionAssumeRoleCredentialsSchema = z.object({
|
|||||||
.trim()
|
.trim()
|
||||||
.min(1)
|
.min(1)
|
||||||
.optional()
|
.optional()
|
||||||
.describe("AWS assume role external id for furthur security in authentication")
|
.describe("AWS assume role external id for further security in authentication")
|
||||||
});
|
});
|
||||||
|
|
||||||
const AwsConnectionAccessTokenCredentialsSchema = z.object({
|
const AwsConnectionAccessTokenCredentialsSchema = z.object({
|
||||||
@@ -64,7 +64,10 @@ export const SanitizedExternalKmsAwsSchema = ExternalKmsAwsSchema.extend({
|
|||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
type: z.literal(KmsAwsCredentialType.AssumeRole),
|
type: z.literal(KmsAwsCredentialType.AssumeRole),
|
||||||
data: AwsConnectionAssumeRoleCredentialsSchema.pick({})
|
data: AwsConnectionAssumeRoleCredentialsSchema.pick({
|
||||||
|
assumeRoleArn: true,
|
||||||
|
externalId: true
|
||||||
|
})
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ export type AddExternalKmsType = z.infer<typeof AddExternalKmsSchema>;
|
|||||||
|
|
||||||
// we need separate schema for update because the credential field is not required on GCP
|
// we need separate schema for update because the credential field is not required on GCP
|
||||||
export const ExternalKmsUpdateInputSchema = z.discriminatedUnion("type", [
|
export const ExternalKmsUpdateInputSchema = z.discriminatedUnion("type", [
|
||||||
z.object({ type: z.literal(ExternalKmsProvider.Aws), inputs: ExternalKmsAwsSchema }),
|
z.object({ type: z.literal(ExternalKmsProvider.Aws), inputs: ExternalKmsAwsSchema.partial() }),
|
||||||
z.object({
|
z.object({
|
||||||
type: z.literal(ExternalKmsProvider.Gcp),
|
type: z.literal(ExternalKmsProvider.Gcp),
|
||||||
inputs: ExternalKmsGcpSchema.pick({ gcpRegion: true, keyName: true })
|
inputs: ExternalKmsGcpSchema.pick({ gcpRegion: true, keyName: true })
|
||||||
|
|||||||
+149
-106
@@ -11,7 +11,8 @@ import {
|
|||||||
AddExternalKmsType,
|
AddExternalKmsType,
|
||||||
ExternalKmsProvider,
|
ExternalKmsProvider,
|
||||||
Kms,
|
Kms,
|
||||||
KmsAwsCredentialType
|
KmsAwsCredentialType,
|
||||||
|
UpdateExternalKmsSchema
|
||||||
} from "@app/hooks/api/kms/types";
|
} from "@app/hooks/api/kms/types";
|
||||||
|
|
||||||
const AWS_REGIONS = [
|
const AWS_REGIONS = [
|
||||||
@@ -50,10 +51,12 @@ type Props = {
|
|||||||
onCompleted: () => void;
|
onCompleted: () => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
kms?: Kms;
|
kms?: Kms;
|
||||||
mode?: "full" | "credentials";
|
mode?: "full" | "credentials" | "details";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props) => {
|
export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props) => {
|
||||||
|
const validationSchema = kms ? UpdateExternalKmsSchema : AddExternalKmsSchema;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@@ -61,24 +64,35 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
|
|||||||
setValue,
|
setValue,
|
||||||
formState: { isSubmitting }
|
formState: { isSubmitting }
|
||||||
} = useForm<AddExternalKmsType>({
|
} = useForm<AddExternalKmsType>({
|
||||||
resolver: zodResolver(AddExternalKmsSchema),
|
resolver: zodResolver(validationSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
name: kms?.name,
|
name: kms?.name,
|
||||||
description: kms?.description ?? "",
|
description: kms?.description ?? "",
|
||||||
configuration: {
|
configuration: {
|
||||||
type: ExternalKmsProvider.Aws,
|
type: ExternalKmsProvider.Aws,
|
||||||
inputs: {
|
inputs: {
|
||||||
credential: {
|
...(mode !== "details" &&
|
||||||
type: kms?.externalKms?.configuration?.credential?.type,
|
kms?.externalKms?.configuration?.credential?.type &&
|
||||||
data: {
|
kms.externalKms.configuration.credential.data
|
||||||
accessKey: kms?.externalKms?.configuration?.credential?.data?.accessKey,
|
? {
|
||||||
secretKey: kms?.externalKms?.configuration?.credential?.data?.secretKey,
|
credential: {
|
||||||
assumeRoleArn: kms?.externalKms?.configuration?.credential?.data?.assumeRoleArn,
|
type: kms.externalKms.configuration.credential.type,
|
||||||
externalId: kms?.externalKms?.configuration?.credential?.data?.externalId
|
data: {
|
||||||
}
|
accessKey: kms.externalKms.configuration.credential.data?.accessKey ?? "",
|
||||||
},
|
secretKey: kms.externalKms.configuration.credential.data?.secretKey ?? "",
|
||||||
awsRegion: kms?.externalKms?.configuration?.awsRegion,
|
assumeRoleArn:
|
||||||
kmsKeyId: kms?.externalKms?.configuration?.kmsKeyId
|
kms.externalKms.configuration.credential.data?.assumeRoleArn ?? "",
|
||||||
|
externalId: kms.externalKms.configuration.credential.data?.externalId ?? ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
...(mode !== "credentials"
|
||||||
|
? {
|
||||||
|
awsRegion: kms?.externalKms?.configuration?.awsRegion ?? "",
|
||||||
|
kmsKeyId: kms?.externalKms?.configuration?.kmsKeyId ?? ""
|
||||||
|
}
|
||||||
|
: {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,16 +111,33 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
|
|||||||
const { name, description, configuration } = data;
|
const { name, description, configuration } = data;
|
||||||
try {
|
try {
|
||||||
if (kms) {
|
if (kms) {
|
||||||
|
if (configuration.type !== ExternalKmsProvider.Aws) {
|
||||||
|
throw new Error("Invalid configuration type");
|
||||||
|
}
|
||||||
|
const awsInputs = configuration.inputs;
|
||||||
|
|
||||||
if (mode === "credentials") {
|
if (mode === "credentials") {
|
||||||
await updateAwsExternalKms({
|
await updateAwsExternalKms({
|
||||||
kmsId: kms.id,
|
kmsId: kms.id,
|
||||||
configuration
|
configuration: {
|
||||||
|
type: ExternalKmsProvider.Aws,
|
||||||
|
inputs: {
|
||||||
|
credential: { ...awsInputs.credential }
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await updateAwsExternalKms({
|
await updateAwsExternalKms({
|
||||||
kmsId: kms.id,
|
kmsId: kms.id,
|
||||||
name,
|
name,
|
||||||
description
|
description,
|
||||||
|
configuration: {
|
||||||
|
type: ExternalKmsProvider.Aws,
|
||||||
|
inputs: {
|
||||||
|
awsRegion: awsInputs.awsRegion,
|
||||||
|
kmsKeyId: awsInputs.kmsKeyId
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +145,7 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
|
|||||||
text:
|
text:
|
||||||
mode === "credentials"
|
mode === "credentials"
|
||||||
? "Successfully updated AWS External KMS credentials"
|
? "Successfully updated AWS External KMS credentials"
|
||||||
: "Successfully updated AWS External KMS",
|
: "Successfully updated AWS External KMS Details",
|
||||||
type: "success"
|
type: "success"
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -138,7 +169,7 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(handleAwsKmsFormSubmit)} autoComplete="off">
|
<form onSubmit={handleSubmit(handleAwsKmsFormSubmit)} autoComplete="off">
|
||||||
{mode === "full" && (
|
{(mode === "full" || mode === "details") && (
|
||||||
<>
|
<>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
@@ -160,86 +191,127 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Controller
|
{(mode === "full" || mode === "credentials") && (
|
||||||
control={control}
|
|
||||||
name="configuration.inputs.credential.type"
|
|
||||||
defaultValue={KmsAwsCredentialType.AssumeRole}
|
|
||||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
|
||||||
<FormControl
|
|
||||||
label="Authentication Mode"
|
|
||||||
errorText={error?.message}
|
|
||||||
isError={Boolean(error)}
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
defaultValue={field.value}
|
|
||||||
{...field}
|
|
||||||
onValueChange={(e) => {
|
|
||||||
setValue("configuration.inputs.credential.data.accessKey", "");
|
|
||||||
setValue("configuration.inputs.credential.data.secretKey", "");
|
|
||||||
setValue("configuration.inputs.credential.data.assumeRoleArn", "");
|
|
||||||
setValue("configuration.inputs.credential.data.externalId", "");
|
|
||||||
|
|
||||||
onChange(e);
|
|
||||||
}}
|
|
||||||
className="w-full"
|
|
||||||
>
|
|
||||||
<SelectItem value={KmsAwsCredentialType.AssumeRole}>AWS Assume Role</SelectItem>
|
|
||||||
<SelectItem value={KmsAwsCredentialType.AccessKey}>Access Key</SelectItem>
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{selectedAwsAuthType === KmsAwsCredentialType.AccessKey ? (
|
|
||||||
<>
|
<>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="configuration.inputs.credential.data.accessKey"
|
name="configuration.inputs.credential.type"
|
||||||
render={({ field, fieldState: { error } }) => (
|
defaultValue={KmsAwsCredentialType.AssumeRole}
|
||||||
|
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Access Key ID"
|
label="Authentication Mode"
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
>
|
>
|
||||||
<Input placeholder="" {...field} />
|
<Select
|
||||||
</FormControl>
|
defaultValue={field.value}
|
||||||
)}
|
{...field}
|
||||||
/>
|
onValueChange={(e) => {
|
||||||
<Controller
|
setValue("configuration.inputs.credential.data.accessKey", "");
|
||||||
control={control}
|
setValue("configuration.inputs.credential.data.secretKey", "");
|
||||||
name="configuration.inputs.credential.data.secretKey"
|
setValue("configuration.inputs.credential.data.assumeRoleArn", "");
|
||||||
render={({ field, fieldState: { error } }) => (
|
setValue("configuration.inputs.credential.data.externalId", "");
|
||||||
<FormControl
|
|
||||||
label="Secret Access Key"
|
onChange(e);
|
||||||
errorText={error?.message}
|
}}
|
||||||
isError={Boolean(error)}
|
className="w-full"
|
||||||
>
|
>
|
||||||
<Input type="password" autoComplete="new-password" placeholder="" {...field} />
|
<SelectItem value={KmsAwsCredentialType.AssumeRole}>AWS Assume Role</SelectItem>
|
||||||
|
<SelectItem value={KmsAwsCredentialType.AccessKey}>Access Key</SelectItem>
|
||||||
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{selectedAwsAuthType === KmsAwsCredentialType.AccessKey ? (
|
||||||
|
<>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="configuration.inputs.credential.data.accessKey"
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
label="Access Key ID"
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error)}
|
||||||
|
>
|
||||||
|
<Input placeholder="" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="configuration.inputs.credential.data.secretKey"
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
label="Secret Access Key"
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error)}
|
||||||
|
>
|
||||||
|
<Input type="password" autoComplete="new-password" placeholder="" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="configuration.inputs.credential.data.assumeRoleArn"
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
label="IAM Role ARN For Role Assumption"
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error)}
|
||||||
|
>
|
||||||
|
<Input placeholder="" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="configuration.inputs.credential.data.externalId"
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
label="Assume Role External ID"
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error)}
|
||||||
|
>
|
||||||
|
<Input placeholder="" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
)}
|
||||||
|
{(mode === "full" || mode === "details") && (
|
||||||
<>
|
<>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="configuration.inputs.credential.data.assumeRoleArn"
|
name="configuration.inputs.awsRegion"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl label="AWS Region" errorText={error?.message} isError={Boolean(error)}>
|
||||||
label="IAM Role ARN For Role Assumption"
|
<Select
|
||||||
errorText={error?.message}
|
defaultValue={field.value}
|
||||||
isError={Boolean(error)}
|
{...field}
|
||||||
>
|
onValueChange={(e) => onChange(e)}
|
||||||
<Input placeholder="" {...field} />
|
className="w-full border border-mineshaft-500"
|
||||||
|
>
|
||||||
|
{AWS_REGIONS.map((awsRegion) => (
|
||||||
|
<SelectItem value={awsRegion.slug} key={`kms-aws-region-${awsRegion.slug}`}>
|
||||||
|
{awsRegion.name} <Badge variant="neutral">{awsRegion.slug}</Badge>
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="configuration.inputs.credential.data.externalId"
|
name="configuration.inputs.kmsKeyId"
|
||||||
render={({ field, fieldState: { error } }) => (
|
render={({ field, fieldState: { error } }) => (
|
||||||
<FormControl
|
<FormControl
|
||||||
label="Assume Role External ID"
|
label="AWS KMS Key ID"
|
||||||
errorText={error?.message}
|
errorText={error?.message}
|
||||||
isError={Boolean(error)}
|
isError={Boolean(error)}
|
||||||
>
|
>
|
||||||
@@ -249,35 +321,6 @@ export const AwsKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
name="configuration.inputs.awsRegion"
|
|
||||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
|
||||||
<FormControl label="AWS Region" errorText={error?.message} isError={Boolean(error)}>
|
|
||||||
<Select
|
|
||||||
defaultValue={field.value}
|
|
||||||
{...field}
|
|
||||||
onValueChange={(e) => onChange(e)}
|
|
||||||
className="w-full border border-mineshaft-500"
|
|
||||||
>
|
|
||||||
{AWS_REGIONS.map((awsRegion) => (
|
|
||||||
<SelectItem value={awsRegion.slug} key={`kms-aws-region-${awsRegion.slug}`}>
|
|
||||||
{awsRegion.name} <Badge variant="neutral">{awsRegion.slug}</Badge>
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
name="configuration.inputs.kmsKeyId"
|
|
||||||
render={({ field, fieldState: { error } }) => (
|
|
||||||
<FormControl label="AWS KMS Key ID" errorText={error?.message} isError={Boolean(error)}>
|
|
||||||
<Input placeholder="" {...field} />
|
|
||||||
</FormControl>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<div className="mt-6 flex items-center space-x-4">
|
<div className="mt-6 flex items-center space-x-4">
|
||||||
<Button type="submit" isLoading={isSubmitting}>
|
<Button type="submit" isLoading={isSubmitting}>
|
||||||
{mode === "credentials" ? "Update Credentials" : "Save"}
|
{mode === "credentials" ? "Update Credentials" : "Save"}
|
||||||
|
|||||||
+6
-7
@@ -1,4 +1,4 @@
|
|||||||
import { ContentLoader, Modal, ModalContent } from "@app/components/v2";
|
import { Modal, ModalContent } from "@app/components/v2";
|
||||||
import { useGetExternalKmsById } from "@app/hooks/api";
|
import { useGetExternalKmsById } from "@app/hooks/api";
|
||||||
import { ExternalKmsProvider } from "@app/hooks/api/kms/types";
|
import { ExternalKmsProvider } from "@app/hooks/api/kms/types";
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ export const EditExternalKmsCredentialsModal = ({
|
|||||||
provider,
|
provider,
|
||||||
onOpenChange
|
onOpenChange
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { data: externalKms, isPending } = useGetExternalKmsById({ kmsId, provider });
|
const { data: kms } = useGetExternalKmsById({ kmsId, provider });
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||||
<ModalContent
|
<ModalContent
|
||||||
@@ -26,18 +26,17 @@ export const EditExternalKmsCredentialsModal = ({
|
|||||||
subTitle="Update the credentials for this KMS."
|
subTitle="Update the credentials for this KMS."
|
||||||
bodyClassName="overflow-visible"
|
bodyClassName="overflow-visible"
|
||||||
>
|
>
|
||||||
{isPending && <ContentLoader />}
|
{kms?.externalKms?.provider === ExternalKmsProvider.Aws && (
|
||||||
{externalKms?.externalKms?.provider === ExternalKmsProvider.Aws && (
|
|
||||||
<AwsKmsForm
|
<AwsKmsForm
|
||||||
kms={externalKms}
|
kms={kms}
|
||||||
mode="credentials"
|
mode="credentials"
|
||||||
onCancel={() => onOpenChange(false)}
|
onCancel={() => onOpenChange(false)}
|
||||||
onCompleted={() => onOpenChange(false)}
|
onCompleted={() => onOpenChange(false)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{externalKms?.externalKms?.provider === ExternalKmsProvider.Gcp && (
|
{kms?.externalKms?.provider === ExternalKmsProvider.Gcp && (
|
||||||
<GcpKmsForm
|
<GcpKmsForm
|
||||||
kms={externalKms}
|
kms={kms}
|
||||||
mode="credentials"
|
mode="credentials"
|
||||||
onCancel={() => onOpenChange(false)}
|
onCancel={() => onOpenChange(false)}
|
||||||
onCompleted={() => onOpenChange(false)}
|
onCompleted={() => onOpenChange(false)}
|
||||||
|
|||||||
+23
-87
@@ -1,20 +1,9 @@
|
|||||||
import { FormProvider, useForm } from "react-hook-form";
|
import { Modal, ModalContent } from "@app/components/v2";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { useGetExternalKmsById } from "@app/hooks/api";
|
||||||
import { z } from "zod";
|
import { ExternalKmsProvider } from "@app/hooks/api/kms/types";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { AwsKmsForm } from "./AwsKmsForm";
|
||||||
import {
|
import { GcpKmsForm } from "./GcpKmsForm";
|
||||||
Button,
|
|
||||||
ContentLoader,
|
|
||||||
FormControl,
|
|
||||||
Input,
|
|
||||||
Modal,
|
|
||||||
ModalClose,
|
|
||||||
ModalContent
|
|
||||||
} from "@app/components/v2";
|
|
||||||
import { useOrganization } from "@app/context";
|
|
||||||
import { useGetExternalKmsById, useUpdateExternalKms } from "@app/hooks/api";
|
|
||||||
import { ExternalKmsProvider, Kms } from "@app/hooks/api/kms/types";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -23,85 +12,32 @@ type Props = {
|
|||||||
provider: ExternalKmsProvider;
|
provider: ExternalKmsProvider;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formSchema = z.object({
|
|
||||||
name: z.string().min(1).trim(),
|
|
||||||
description: z.string().trim().optional()
|
|
||||||
});
|
|
||||||
|
|
||||||
type FormData = z.infer<typeof formSchema>;
|
|
||||||
|
|
||||||
type ContentProps = { kms: Kms; provider: ExternalKmsProvider; onComplete: () => void };
|
|
||||||
|
|
||||||
const Content = ({ kms, onComplete, provider }: ContentProps) => {
|
|
||||||
const { currentOrg } = useOrganization();
|
|
||||||
const { mutateAsync: updateExternalKms, isPending } = useUpdateExternalKms(
|
|
||||||
currentOrg.id,
|
|
||||||
provider
|
|
||||||
);
|
|
||||||
|
|
||||||
const form = useForm<FormData>({
|
|
||||||
resolver: zodResolver(formSchema),
|
|
||||||
defaultValues: {
|
|
||||||
name: kms.name,
|
|
||||||
description: kms.description ?? ""
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const {
|
|
||||||
handleSubmit,
|
|
||||||
formState: { isDirty }
|
|
||||||
} = form;
|
|
||||||
|
|
||||||
const onSubmit = async (formData: FormData) => {
|
|
||||||
if (!kms) return;
|
|
||||||
|
|
||||||
await updateExternalKms({
|
|
||||||
kmsId: kms.id,
|
|
||||||
name: formData.name,
|
|
||||||
description: formData.description
|
|
||||||
});
|
|
||||||
|
|
||||||
createNotification({
|
|
||||||
text: "Successfully updated KMS details",
|
|
||||||
type: "success"
|
|
||||||
});
|
|
||||||
onComplete();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FormProvider {...form}>
|
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
|
||||||
<FormControl label="Alias">
|
|
||||||
<Input {...form.register("name")} />
|
|
||||||
</FormControl>
|
|
||||||
<FormControl label="Description">
|
|
||||||
<Input {...form.register("description")} />
|
|
||||||
</FormControl>
|
|
||||||
<div className="mt-6 flex items-center space-x-4">
|
|
||||||
<Button type="submit" isLoading={isPending} isDisabled={!isDirty}>
|
|
||||||
Update Details
|
|
||||||
</Button>
|
|
||||||
<ModalClose asChild>
|
|
||||||
<Button variant="outline_bg">Cancel</Button>
|
|
||||||
</ModalClose>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</FormProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const EditExternalKmsDetailsModal = ({ isOpen, onOpenChange, kmsId, provider }: Props) => {
|
export const EditExternalKmsDetailsModal = ({ isOpen, onOpenChange, kmsId, provider }: Props) => {
|
||||||
const { data: kms, isPending } = useGetExternalKmsById({ kmsId, provider });
|
const { data: kms } = useGetExternalKmsById({ kmsId, provider });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||||
<ModalContent
|
<ModalContent
|
||||||
className="max-w-2xl"
|
|
||||||
title="Edit KMS Details"
|
title="Edit KMS Details"
|
||||||
subTitle="Update the name and description for this KMS."
|
subTitle="Update the name and description for this KMS."
|
||||||
|
bodyClassName="overflow-visible"
|
||||||
>
|
>
|
||||||
{isPending && <ContentLoader />}
|
{kms?.externalKms?.provider === ExternalKmsProvider.Aws && (
|
||||||
{kms && <Content kms={kms} provider={provider} onComplete={() => onOpenChange(false)} />}
|
<AwsKmsForm
|
||||||
|
kms={kms}
|
||||||
|
mode="details"
|
||||||
|
onCancel={() => onOpenChange(false)}
|
||||||
|
onCompleted={() => onOpenChange(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{kms?.externalKms?.provider === ExternalKmsProvider.Gcp && (
|
||||||
|
<GcpKmsForm
|
||||||
|
kms={kms}
|
||||||
|
mode="details"
|
||||||
|
onCancel={() => onOpenChange(false)}
|
||||||
|
onCompleted={() => onOpenChange(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|||||||
+125
-103
@@ -24,7 +24,7 @@ type Props = {
|
|||||||
onCompleted: () => void;
|
onCompleted: () => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
kms?: Kms;
|
kms?: Kms;
|
||||||
mode?: "full" | "credentials";
|
mode?: "full" | "credentials" | "details";
|
||||||
};
|
};
|
||||||
|
|
||||||
const GCP_REGIONS = [
|
const GCP_REGIONS = [
|
||||||
@@ -145,53 +145,70 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
|
|||||||
// handles the form submission
|
// handles the form submission
|
||||||
const handleGcpKmsFormSubmit = async (data: AddExternalKmsGcpFormSchemaType) => {
|
const handleGcpKmsFormSubmit = async (data: AddExternalKmsGcpFormSchemaType) => {
|
||||||
const { name, description, gcpRegion: gcpRegionObject, keyObject } = data;
|
const { name, description, gcpRegion: gcpRegionObject, keyObject } = data;
|
||||||
const gcpRegion = gcpRegionObject.value;
|
|
||||||
if (!keys.find((k) => k.value === keyObject?.value)) {
|
|
||||||
setError("keyObject", {
|
|
||||||
message: "Please select a valid key."
|
|
||||||
});
|
|
||||||
resetField("keyObject");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (kms) {
|
if (kms) {
|
||||||
if (mode === "credentials") {
|
if (mode === "details") {
|
||||||
await updateGcpExternalKms({
|
|
||||||
kmsId: kms.id,
|
|
||||||
name: kms.name,
|
|
||||||
description: kms.description,
|
|
||||||
configuration: {
|
|
||||||
type: ExternalKmsProvider.Gcp,
|
|
||||||
inputs: {
|
|
||||||
gcpRegion,
|
|
||||||
keyName: keyObject?.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await updateGcpExternalKms({
|
await updateGcpExternalKms({
|
||||||
kmsId: kms.id,
|
kmsId: kms.id,
|
||||||
name,
|
name,
|
||||||
description,
|
description
|
||||||
|
});
|
||||||
|
|
||||||
|
createNotification({
|
||||||
|
text: "Successfully updated GCP External KMS Details",
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
} else if (mode === "credentials") {
|
||||||
|
const gcpRegion = gcpRegionObject?.value;
|
||||||
|
if (!gcpRegion) {
|
||||||
|
setError("gcpRegion", {
|
||||||
|
message: "Please select a GCP region."
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyObject && !keys.find((k) => k.value === keyObject.value)) {
|
||||||
|
setError("keyObject", {
|
||||||
|
message: "Please select a valid key."
|
||||||
|
});
|
||||||
|
resetField("keyObject");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateGcpExternalKms({
|
||||||
|
kmsId: kms.id,
|
||||||
configuration: {
|
configuration: {
|
||||||
type: ExternalKmsProvider.Gcp,
|
type: ExternalKmsProvider.Gcp,
|
||||||
inputs: {
|
inputs: {
|
||||||
gcpRegion,
|
gcpRegion,
|
||||||
keyName: keyObject?.value
|
keyName: keyObject?.value ?? kms.externalKms.configuration.keyName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createNotification({
|
||||||
|
text: "Successfully updated GCP External KMS configuration",
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const gcpRegion = gcpRegionObject?.value;
|
||||||
|
if (!gcpRegion) {
|
||||||
|
setError("gcpRegion", {
|
||||||
|
message: "Please select a GCP region."
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keys.find((k) => k.value === keyObject?.value)) {
|
||||||
|
setError("keyObject", {
|
||||||
|
message: "Please select a valid key."
|
||||||
|
});
|
||||||
|
resetField("keyObject");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
createNotification({
|
|
||||||
text:
|
|
||||||
mode === "credentials"
|
|
||||||
? "Successfully updated GCP External KMS configuration"
|
|
||||||
: "Successfully updated GCP External KMS",
|
|
||||||
type: "success"
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const credentialJson = await getCredentialFileJson();
|
const credentialJson = await getCredentialFileJson();
|
||||||
if (!credentialJson) {
|
if (!credentialJson) {
|
||||||
return;
|
return;
|
||||||
@@ -230,8 +247,9 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
|
|||||||
if (!kms && !credentialJson) {
|
if (!kms && !credentialJson) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const gcpRegion = getValues("gcpRegion").value;
|
const gcpRegionObject = getValues("gcpRegion");
|
||||||
if (!gcpRegion.length) {
|
const gcpRegion = gcpRegionObject?.value;
|
||||||
|
if (!gcpRegion) {
|
||||||
setError("gcpRegion", {
|
setError("gcpRegion", {
|
||||||
message: "Please select a GCP region to fetch GCP Keys."
|
message: "Please select a GCP region to fetch GCP Keys."
|
||||||
});
|
});
|
||||||
@@ -284,7 +302,7 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(handleGcpKmsFormSubmit)} autoComplete="off">
|
<form onSubmit={handleSubmit(handleGcpKmsFormSubmit)} autoComplete="off">
|
||||||
{mode === "full" && (
|
{(mode === "full" || mode === "details") && (
|
||||||
<>
|
<>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
@@ -306,75 +324,79 @@ export const GcpKmsForm = ({ onCompleted, onCancel, kms, mode = "full" }: Props)
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Controller
|
{(mode === "full" || mode === "credentials") && (
|
||||||
control={control}
|
<>
|
||||||
name="gcpRegion"
|
<Controller
|
||||||
render={({ field, fieldState: { error } }) => (
|
control={control}
|
||||||
<FormControl label="GCP Region" errorText={error?.message} isError={Boolean(error)}>
|
name="gcpRegion"
|
||||||
<FilterableSelect
|
render={({ field, fieldState: { error } }) => (
|
||||||
className="w-full"
|
<FormControl label="GCP Region" errorText={error?.message} isError={Boolean(error)}>
|
||||||
placeholder="Select a GCP region"
|
<FilterableSelect
|
||||||
name="gcpRegion"
|
className="w-full"
|
||||||
options={GCP_REGIONS}
|
placeholder="Select a GCP region"
|
||||||
value={field.value}
|
name="gcpRegion"
|
||||||
onChange={(e) => {
|
options={GCP_REGIONS}
|
||||||
resetField("keyObject");
|
value={field.value}
|
||||||
field.onChange(e);
|
onChange={(e) => {
|
||||||
fetchGCPKeys();
|
resetField("keyObject");
|
||||||
}}
|
field.onChange(e);
|
||||||
formatOptionLabel={formatOptionLabel}
|
fetchGCPKeys();
|
||||||
|
}}
|
||||||
|
formatOptionLabel={formatOptionLabel}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{!kms && (
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="credentialFile"
|
||||||
|
render={({ field: { value, onChange, ref, ...rest }, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
label="Service Account Credential JSON"
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error)}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
{...rest}
|
||||||
|
ref={ref}
|
||||||
|
type="file"
|
||||||
|
accept=".json"
|
||||||
|
placeholder=""
|
||||||
|
value={value?.filename}
|
||||||
|
onChange={(e) => {
|
||||||
|
onChange(e.target.files);
|
||||||
|
fetchGCPKeys();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{!kms && (
|
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
name="credentialFile"
|
|
||||||
render={({ field: { value, onChange, ref, ...rest }, fieldState: { error } }) => (
|
|
||||||
<FormControl
|
|
||||||
label="Service Account Credential JSON"
|
|
||||||
errorText={error?.message}
|
|
||||||
isError={Boolean(error)}
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
{...rest}
|
|
||||||
ref={ref}
|
|
||||||
type="file"
|
|
||||||
accept=".json"
|
|
||||||
placeholder=""
|
|
||||||
value={value?.filename}
|
|
||||||
onChange={(e) => {
|
|
||||||
onChange(e.target.files);
|
|
||||||
fetchGCPKeys();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
)}
|
||||||
/>
|
<Controller
|
||||||
)}
|
control={control}
|
||||||
<Controller
|
name="keyObject"
|
||||||
control={control}
|
render={({ field, fieldState: { error } }) => (
|
||||||
name="keyObject"
|
<FormControl label="GCP Key Name" errorText={error?.message} isError={Boolean(error)}>
|
||||||
render={({ field, fieldState: { error } }) => (
|
<FilterableSelect
|
||||||
<FormControl label="GCP Key Name" errorText={error?.message} isError={Boolean(error)}>
|
className="w-full"
|
||||||
<FilterableSelect
|
placeholder={getPlaceholderText()}
|
||||||
className="w-full"
|
isDisabled={!isCredentialValid || !keys.length}
|
||||||
placeholder={getPlaceholderText()}
|
name="key"
|
||||||
isDisabled={!isCredentialValid || !keys.length}
|
options={keys}
|
||||||
name="key"
|
value={field.value}
|
||||||
options={keys}
|
onChange={field.onChange}
|
||||||
value={field.value}
|
/>
|
||||||
onChange={field.onChange}
|
</FormControl>
|
||||||
/>
|
)}
|
||||||
</FormControl>
|
/>
|
||||||
)}
|
{kms && (
|
||||||
/>
|
<span className="text-xs text-mineshaft-300">
|
||||||
{kms && (
|
To change your GCP credentials, create a new external KMS and assign it to project you
|
||||||
<span className="text-xs text-mineshaft-300">
|
want to use it with.
|
||||||
To change your GCP credentials, create a new external KMS and assign it to project you
|
</span>
|
||||||
want to use it with.
|
)}
|
||||||
</span>
|
</>
|
||||||
)}
|
)}
|
||||||
<div className="mt-6 flex items-center space-x-4">
|
<div className="mt-6 flex items-center space-x-4">
|
||||||
<Button type="submit" isLoading={isSubmitting}>
|
<Button type="submit" isLoading={isSubmitting}>
|
||||||
|
|||||||
Reference in New Issue
Block a user