mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 16:27:46 +00:00
feat: finalized kms settings in org-level
This commit is contained in:
@@ -19,6 +19,23 @@ const sanitizedExternalSchema = KmsKeysSchema.extend({
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const sanitizedExternalSchemaForGetAll = KmsKeysSchema.pick({
|
||||||
|
id: true,
|
||||||
|
description: true,
|
||||||
|
isDisabled: true,
|
||||||
|
createdAt: true,
|
||||||
|
updatedAt: true,
|
||||||
|
slug: true
|
||||||
|
})
|
||||||
|
.extend({
|
||||||
|
externalKms: ExternalKmsSchema.pick({
|
||||||
|
provider: true,
|
||||||
|
status: true,
|
||||||
|
statusDetails: true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.array();
|
||||||
|
|
||||||
const sanitizedExternalSchemaForGetById = KmsKeysSchema.extend({
|
const sanitizedExternalSchemaForGetById = KmsKeysSchema.extend({
|
||||||
external: ExternalKmsSchema.pick({
|
external: ExternalKmsSchema.pick({
|
||||||
id: true,
|
id: true,
|
||||||
@@ -159,6 +176,31 @@ export const registerExternalKmsRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "GET",
|
||||||
|
url: "/",
|
||||||
|
config: {
|
||||||
|
rateLimit: readLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
externalKmsList: sanitizedExternalSchemaForGetAll
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const externalKmsList = await server.services.externalKms.list({
|
||||||
|
actor: req.permission.type,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
actorOrgId: req.permission.orgId
|
||||||
|
});
|
||||||
|
return { externalKmsList };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: "/slug/:slug",
|
url: "/slug/:slug",
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ export const externalKmsDALFactory = (db: TDbClient) => {
|
|||||||
isReserved: el.isReserved,
|
isReserved: el.isReserved,
|
||||||
orgId: el.orgId,
|
orgId: el.orgId,
|
||||||
slug: el.slug,
|
slug: el.slug,
|
||||||
|
createdAt: el.createdAt,
|
||||||
|
updatedAt: el.updatedAt,
|
||||||
externalKms: {
|
externalKms: {
|
||||||
id: el.externalKmsId,
|
id: el.externalKmsId,
|
||||||
provider: el.externalKmsProvider,
|
provider: el.externalKmsProvider,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export * from "./incidentContacts";
|
|||||||
export * from "./integrationAuth";
|
export * from "./integrationAuth";
|
||||||
export * from "./integrations";
|
export * from "./integrations";
|
||||||
export * from "./keys";
|
export * from "./keys";
|
||||||
|
export * from "./kms";
|
||||||
export * from "./ldapConfig";
|
export * from "./ldapConfig";
|
||||||
export * from "./oidcConfig";
|
export * from "./oidcConfig";
|
||||||
export * from "./organization";
|
export * from "./organization";
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export { useAddAwsExternalKms } from "./mutations";
|
export { useAddAwsExternalKms, useRemoveExternalKms, useUpdateAwsExternalKms } from "./mutations";
|
||||||
|
export { useGetExternalKmsById, useGetExternalKmsList } from "./queries";
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import { useMutation } from "@tanstack/react-query";
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { apiRequest } from "@app/config/request";
|
import { apiRequest } from "@app/config/request";
|
||||||
|
|
||||||
export const useAddAwsExternalKms = () => {
|
import { kmsKeys } from "./queries";
|
||||||
|
|
||||||
|
export const useAddAwsExternalKms = (orgId: string) => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({
|
mutationFn: async ({
|
||||||
slug,
|
slug,
|
||||||
@@ -48,6 +51,78 @@ export const useAddAwsExternalKms = () => {
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
onSuccess() {}
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries(kmsKeys.getExternalKmsList(orgId));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUpdateAwsExternalKms = (orgId: string) => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async ({
|
||||||
|
kmsId,
|
||||||
|
slug,
|
||||||
|
description,
|
||||||
|
credentialType,
|
||||||
|
accessKey,
|
||||||
|
secretKey,
|
||||||
|
assumeRoleArn,
|
||||||
|
externalId,
|
||||||
|
awsRegion,
|
||||||
|
kmsKeyId
|
||||||
|
}: {
|
||||||
|
kmsId: string;
|
||||||
|
slug?: string;
|
||||||
|
description?: string;
|
||||||
|
credentialType?: string;
|
||||||
|
accessKey?: string;
|
||||||
|
secretKey?: string;
|
||||||
|
assumeRoleArn?: string;
|
||||||
|
externalId?: string;
|
||||||
|
awsRegion: string;
|
||||||
|
kmsKeyId?: string;
|
||||||
|
}) => {
|
||||||
|
const { data } = await apiRequest.patch(`/api/v1/external-kms/${kmsId}`, {
|
||||||
|
slug,
|
||||||
|
description,
|
||||||
|
provider: {
|
||||||
|
type: "aws",
|
||||||
|
inputs: {
|
||||||
|
credential: {
|
||||||
|
type: credentialType,
|
||||||
|
data: {
|
||||||
|
accessKey,
|
||||||
|
secretKey,
|
||||||
|
assumeRoleArn,
|
||||||
|
externalId
|
||||||
|
}
|
||||||
|
},
|
||||||
|
awsRegion,
|
||||||
|
kmsKeyId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
onSuccess: (_, { kmsId }) => {
|
||||||
|
queryClient.invalidateQueries(kmsKeys.getExternalKmsList(orgId));
|
||||||
|
queryClient.invalidateQueries(kmsKeys.getExternalKmsById(kmsId));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useRemoveExternalKms = (orgId: string) => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: async (kmsId: string) => {
|
||||||
|
const { data } = await apiRequest.delete(`/api/v1/external-kms/${kmsId}`);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries(kmsKeys.getExternalKmsList(orgId));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
import { apiRequest } from "@app/config/request";
|
||||||
|
|
||||||
|
import { Kms, KmsListEntry } from "./types";
|
||||||
|
|
||||||
|
export const kmsKeys = {
|
||||||
|
getExternalKmsList: (orgId: string) => ["get-all-external-kms", { orgId }],
|
||||||
|
getExternalKmsById: (id: string) => ["get-external-kms", { id }]
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetExternalKmsList = (orgId: string) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: kmsKeys.getExternalKmsList(orgId),
|
||||||
|
queryFn: async () => {
|
||||||
|
const {
|
||||||
|
data: { externalKmsList }
|
||||||
|
} = await apiRequest.get<{ externalKmsList: KmsListEntry[] }>("/api/v1/external-kms");
|
||||||
|
return externalKmsList;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetExternalKmsById = (kmsId: string) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: kmsKeys.getExternalKmsById(kmsId),
|
||||||
|
enabled: Boolean(kmsId),
|
||||||
|
queryFn: async () => {
|
||||||
|
const {
|
||||||
|
data: { externalKms }
|
||||||
|
} = await apiRequest.get<{ externalKms: Kms }>(`/api/v1/external-kms/${kmsId}`);
|
||||||
|
return externalKms;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
export type Kms = {
|
||||||
|
id: string;
|
||||||
|
description: string;
|
||||||
|
orgId: string;
|
||||||
|
slug: string;
|
||||||
|
external: {
|
||||||
|
id: string;
|
||||||
|
status: string;
|
||||||
|
statusDetails: string;
|
||||||
|
provider: string;
|
||||||
|
providerInput: Record<string, any>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type KmsListEntry = {
|
||||||
|
id: string;
|
||||||
|
description: string;
|
||||||
|
isDisabled: boolean;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
slug: string;
|
||||||
|
externalKms: {
|
||||||
|
provider: string;
|
||||||
|
status: string;
|
||||||
|
statusDetails: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum ExternalKmsProvider {
|
||||||
|
AWS = "aws"
|
||||||
|
}
|
||||||
+2
-5
@@ -4,6 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|||||||
import { AnimatePresence, motion } from "framer-motion";
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
|
|
||||||
import { Modal, ModalContent } from "@app/components/v2";
|
import { Modal, ModalContent } from "@app/components/v2";
|
||||||
|
import { ExternalKmsProvider } from "@app/hooks/api/kms/types";
|
||||||
|
|
||||||
import { AwsKmsForm } from "./AwsKmsForm";
|
import { AwsKmsForm } from "./AwsKmsForm";
|
||||||
|
|
||||||
@@ -17,10 +18,6 @@ enum WizardSteps {
|
|||||||
ProviderInputs = "provider-inputs"
|
ProviderInputs = "provider-inputs"
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ExternalKmsProvider {
|
|
||||||
AWS = "aws"
|
|
||||||
}
|
|
||||||
|
|
||||||
const EXTERNAL_KMS_LIST = [
|
const EXTERNAL_KMS_LIST = [
|
||||||
{
|
{
|
||||||
icon: faAws,
|
icon: faAws,
|
||||||
@@ -90,7 +87,7 @@ export const AddExternalKmsForm = ({ isOpen, onToggle }: Props) => {
|
|||||||
animate={{ opacity: 1, translateX: 0 }}
|
animate={{ opacity: 1, translateX: 0 }}
|
||||||
exit={{ opacity: 0, translateX: -30 }}
|
exit={{ opacity: 0, translateX: -30 }}
|
||||||
>
|
>
|
||||||
<AwsKmsForm onCancel={() => {}} onCompleted={() => {}} />
|
<AwsKmsForm onCancel={() => onToggle(false)} onCompleted={() => onToggle(false)} />
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
export { AddExternalKmsForm } from "./AddExternalKmsForm";
|
|
||||||
+84
-27
@@ -5,7 +5,9 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { Button, FormControl, Input, Select, SelectItem } from "@app/components/v2";
|
import { Button, FormControl, Input, Select, SelectItem } from "@app/components/v2";
|
||||||
import { useAddAwsExternalKms } from "@app/hooks/api/kms";
|
import { useOrganization } from "@app/context";
|
||||||
|
import { useAddAwsExternalKms, useUpdateAwsExternalKms } from "@app/hooks/api";
|
||||||
|
import { Kms } from "@app/hooks/api/kms/types";
|
||||||
|
|
||||||
const AWS_REGIONS = [
|
const AWS_REGIONS = [
|
||||||
{ name: "US East (Ohio)", slug: "us-east-2" },
|
{ name: "US East (Ohio)", slug: "us-east-2" },
|
||||||
@@ -78,47 +80,95 @@ type TForm = z.infer<typeof formSchema>;
|
|||||||
type Props = {
|
type Props = {
|
||||||
onCompleted: () => void;
|
onCompleted: () => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
|
kms?: Kms;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AwsKmsForm = ({ onCompleted, onCancel }: Props) => {
|
export const AwsKmsForm = ({ onCompleted, onCancel, kms }: Props) => {
|
||||||
const {
|
const {
|
||||||
control,
|
control,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
watch,
|
watch,
|
||||||
|
setValue,
|
||||||
formState: { isSubmitting }
|
formState: { isSubmitting }
|
||||||
} = useForm<TForm>({
|
} = useForm<TForm>({
|
||||||
resolver: zodResolver(formSchema)
|
resolver: zodResolver(formSchema),
|
||||||
|
defaultValues: {
|
||||||
|
slug: kms?.slug,
|
||||||
|
description: kms?.description,
|
||||||
|
credential: {
|
||||||
|
type: kms?.external?.providerInput?.credential?.type,
|
||||||
|
data: {
|
||||||
|
accessKey: kms?.external?.providerInput?.credential?.data?.accessKey,
|
||||||
|
secretKey: kms?.external?.providerInput?.credential?.data?.secretKey,
|
||||||
|
assumeRoleArn: kms?.external?.providerInput?.credential?.data?.assumeRoleArn,
|
||||||
|
externalId: kms?.external?.providerInput?.credential?.data?.externalId
|
||||||
|
}
|
||||||
|
},
|
||||||
|
awsRegion: kms?.external?.providerInput?.awsRegion,
|
||||||
|
kmsKeyId: kms?.external?.providerInput?.kmsKeyId
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { currentOrg } = useOrganization();
|
||||||
|
const { mutateAsync: addAwsExternalKms } = useAddAwsExternalKms(currentOrg?.id!);
|
||||||
|
const { mutateAsync: updateAwsExternalKms } = useUpdateAwsExternalKms(currentOrg?.id!);
|
||||||
|
|
||||||
const selectedAwsAuthType = watch("credential.type");
|
const selectedAwsAuthType = watch("credential.type");
|
||||||
|
|
||||||
const { mutateAsync: addAwsExternalKms } = useAddAwsExternalKms();
|
|
||||||
|
|
||||||
const handleAddAwsKms = async (data: TForm) => {
|
const handleAddAwsKms = async (data: TForm) => {
|
||||||
const { slug, description, credential, awsRegion, kmsKeyId } = data;
|
const { slug, description, credential, awsRegion, kmsKeyId } = data;
|
||||||
await addAwsExternalKms({
|
try {
|
||||||
slug,
|
if (kms) {
|
||||||
description,
|
await updateAwsExternalKms({
|
||||||
credentialType: credential.type,
|
kmsId: kms.id,
|
||||||
awsRegion,
|
slug,
|
||||||
kmsKeyId,
|
description,
|
||||||
...(credential.type === KmsAwsCredentialType.AccessKey
|
credentialType: credential.type,
|
||||||
? {
|
awsRegion,
|
||||||
accessKey: credential.data.accessKey,
|
kmsKeyId,
|
||||||
secretKey: credential.data.secretKey
|
...(credential.type === KmsAwsCredentialType.AccessKey
|
||||||
}
|
? {
|
||||||
: {
|
accessKey: credential.data.accessKey,
|
||||||
assumeRoleArn: credential.data.assumeRoleArn,
|
secretKey: credential.data.secretKey
|
||||||
externalId: credential.data.externalId
|
}
|
||||||
})
|
: {
|
||||||
});
|
assumeRoleArn: credential.data.assumeRoleArn,
|
||||||
|
externalId: credential.data.externalId
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
createNotification({
|
createNotification({
|
||||||
text: "Successfully added AWS External KMS",
|
text: "Successfully updated AWS External KMS",
|
||||||
type: "success"
|
type: "success"
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
await addAwsExternalKms({
|
||||||
|
slug,
|
||||||
|
description,
|
||||||
|
credentialType: credential.type,
|
||||||
|
awsRegion,
|
||||||
|
kmsKeyId,
|
||||||
|
...(credential.type === KmsAwsCredentialType.AccessKey
|
||||||
|
? {
|
||||||
|
accessKey: credential.data.accessKey,
|
||||||
|
secretKey: credential.data.secretKey
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
assumeRoleArn: credential.data.assumeRoleArn,
|
||||||
|
externalId: credential.data.externalId
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
onCompleted();
|
createNotification({
|
||||||
|
text: "Successfully added AWS External KMS",
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onCompleted();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -154,7 +204,14 @@ export const AwsKmsForm = ({ onCompleted, onCancel }: Props) => {
|
|||||||
<Select
|
<Select
|
||||||
defaultValue={field.value}
|
defaultValue={field.value}
|
||||||
{...field}
|
{...field}
|
||||||
onValueChange={(e) => onChange(e)}
|
onValueChange={(e) => {
|
||||||
|
setValue("credential.data.accessKey", "");
|
||||||
|
setValue("credential.data.secretKey", "");
|
||||||
|
setValue("credential.data.assumeRoleArn", "");
|
||||||
|
setValue("credential.data.externalId", "");
|
||||||
|
|
||||||
|
onChange(e);
|
||||||
|
}}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
>
|
>
|
||||||
<SelectItem value={KmsAwsCredentialType.AssumeRole}>AWS Assume Role</SelectItem>
|
<SelectItem value={KmsAwsCredentialType.AssumeRole}>AWS Assume Role</SelectItem>
|
||||||
+129
-15
@@ -1,17 +1,31 @@
|
|||||||
import { faPlus } from "@fortawesome/free-solid-svg-icons";
|
import { faEllipsis, faLock, faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import { Button, UpgradePlanModal } from "@app/components/v2";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import {
|
import {
|
||||||
OrgPermissionActions,
|
Button,
|
||||||
OrgPermissionSubjects,
|
DeleteActionModal,
|
||||||
useOrganization,
|
DropdownMenu,
|
||||||
useSubscription
|
DropdownMenuContent,
|
||||||
} from "@app/context";
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
EmptyState,
|
||||||
|
Table,
|
||||||
|
TableContainer,
|
||||||
|
TableSkeleton,
|
||||||
|
TBody,
|
||||||
|
Td,
|
||||||
|
THead,
|
||||||
|
Tr,
|
||||||
|
UpgradePlanModal
|
||||||
|
} from "@app/components/v2";
|
||||||
|
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
||||||
import { withPermission } from "@app/hoc";
|
import { withPermission } from "@app/hoc";
|
||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
|
import { useGetExternalKmsList, useRemoveExternalKms } from "@app/hooks/api";
|
||||||
|
|
||||||
import { AddExternalKmsForm } from "./AddExternalKmsForm";
|
import { AddExternalKmsForm } from "./AddExternalKmsForm";
|
||||||
|
import { UpdateExternalKmsForm } from "./UpdateExternalKmsForm";
|
||||||
|
|
||||||
export const OrgEncryptionTab = withPermission(
|
export const OrgEncryptionTab = withPermission(
|
||||||
() => {
|
() => {
|
||||||
@@ -19,17 +33,41 @@ export const OrgEncryptionTab = withPermission(
|
|||||||
const orgId = currentOrg?.id || "";
|
const orgId = currentOrg?.id || "";
|
||||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
|
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
|
||||||
"upgradePlan",
|
"upgradePlan",
|
||||||
"addExternalKMS"
|
"addExternalKms",
|
||||||
|
"editExternalKms",
|
||||||
|
"removeExternalKms"
|
||||||
] as const);
|
] as const);
|
||||||
const { subscription } = useSubscription();
|
const { data: externalKmsList, isLoading: isExternalKmsListLoading } =
|
||||||
|
useGetExternalKmsList(orgId);
|
||||||
|
|
||||||
|
const { mutateAsync: removeExternalKms } = useRemoveExternalKms(currentOrg?.id!);
|
||||||
|
|
||||||
|
const handleRemoveExternalKms = async () => {
|
||||||
|
const { kmsId } = popUp?.removeExternalKms?.data as {
|
||||||
|
kmsId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await removeExternalKms(kmsId);
|
||||||
|
|
||||||
|
createNotification({
|
||||||
|
text: "Successfully deleted external KMS",
|
||||||
|
type: "success"
|
||||||
|
});
|
||||||
|
|
||||||
|
handlePopUpToggle("removeExternalKms", false);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<p className="text-xl font-semibold text-mineshaft-100">Encryption</p>
|
<p className="text-xl font-semibold text-mineshaft-100">Key Management System (KMS)</p>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handlePopUpOpen("addExternalKMS");
|
handlePopUpOpen("addExternalKms");
|
||||||
// if (subscription && !subscription?.auditLogStreams) {
|
// if (subscription && !subscription?.auditLogStreams) {
|
||||||
// handlePopUpOpen("upgradePlan");
|
// handlePopUpOpen("upgradePlan");
|
||||||
// return;
|
// return;
|
||||||
@@ -42,16 +80,92 @@ export const OrgEncryptionTab = withPermission(
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<p className="mb-4 text-gray-400">
|
<p className="mb-4 text-gray-400">
|
||||||
Configure the Key Management System used for encrypting/decrypting your data at rest
|
Integrate with external KMS systems for encrypting your organization's data
|
||||||
</p>
|
</p>
|
||||||
|
<TableContainer>
|
||||||
|
<Table>
|
||||||
|
<THead>
|
||||||
|
<Tr>
|
||||||
|
<Td>Provider</Td>
|
||||||
|
<Td>Alias</Td>
|
||||||
|
</Tr>
|
||||||
|
</THead>
|
||||||
|
<TBody>
|
||||||
|
{isExternalKmsListLoading && <TableSkeleton columns={2} innerKey="kms-loading" />}
|
||||||
|
{!isExternalKmsListLoading && externalKmsList && externalKmsList?.length === 0 && (
|
||||||
|
<Tr>
|
||||||
|
<Td colSpan={5}>
|
||||||
|
<EmptyState title="No external KMS found" icon={faLock} />
|
||||||
|
</Td>
|
||||||
|
</Tr>
|
||||||
|
)}
|
||||||
|
{!isExternalKmsListLoading &&
|
||||||
|
externalKmsList?.map((kms) => (
|
||||||
|
<Tr key={kms.id}>
|
||||||
|
<Td className="max-w-xs overflow-hidden text-ellipsis hover:overflow-auto hover:break-all">
|
||||||
|
{kms.externalKms.provider}
|
||||||
|
</Td>
|
||||||
|
<Td>{kms.slug}</Td>
|
||||||
|
<Td>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild className="rounded-lg">
|
||||||
|
<div className="flex justify-end hover:text-primary-400 data-[state=open]:text-primary-400">
|
||||||
|
<FontAwesomeIcon size="sm" icon={faEllipsis} />
|
||||||
|
</div>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="start" className="p-1">
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handlePopUpOpen("editExternalKms", {
|
||||||
|
kmsId: kms.id
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handlePopUpOpen("removeExternalKms", {
|
||||||
|
slug: kms.slug,
|
||||||
|
kmsId: kms.id,
|
||||||
|
provider: kms.externalKms.provider
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</Td>
|
||||||
|
</Tr>
|
||||||
|
))}
|
||||||
|
</TBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
<UpgradePlanModal
|
<UpgradePlanModal
|
||||||
isOpen={popUp.upgradePlan.isOpen}
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
text="You can add audit log streams if you switch to Infisical's Enterprise plan."
|
text="You can configure external KMS if you switch to Infisical's Enterprise plan."
|
||||||
/>
|
/>
|
||||||
<AddExternalKmsForm
|
<AddExternalKmsForm
|
||||||
isOpen={popUp.addExternalKMS.isOpen}
|
isOpen={popUp.addExternalKms.isOpen}
|
||||||
onToggle={(state) => handlePopUpToggle("addExternalKMS", state)}
|
onToggle={(state) => handlePopUpToggle("addExternalKms", state)}
|
||||||
|
/>
|
||||||
|
<UpdateExternalKmsForm
|
||||||
|
isOpen={popUp.editExternalKms.isOpen}
|
||||||
|
kmsId={(popUp.editExternalKms.data as { kmsId: string })?.kmsId}
|
||||||
|
onOpenChange={(state) => handlePopUpToggle("editExternalKms", state)}
|
||||||
|
/>
|
||||||
|
<DeleteActionModal
|
||||||
|
isOpen={popUp.removeExternalKms.isOpen}
|
||||||
|
title={`Are you sure want to remove ${
|
||||||
|
(popUp?.removeExternalKms?.data as { slug: string })?.slug || ""
|
||||||
|
} from ${(popUp?.removeExternalKms?.data as { provider: string })?.provider || ""}?`}
|
||||||
|
onChange={(isOpen) => handlePopUpToggle("removeExternalKms", isOpen)}
|
||||||
|
deleteKey="confirm"
|
||||||
|
onDeleteApproved={handleRemoveExternalKms}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
import { ContentLoader, Modal, ModalContent } from "@app/components/v2";
|
||||||
|
import { useGetExternalKmsById } from "@app/hooks/api";
|
||||||
|
import { ExternalKmsProvider } from "@app/hooks/api/kms/types";
|
||||||
|
|
||||||
|
import { AwsKmsForm } from "./AwsKmsForm";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isOpen: boolean;
|
||||||
|
kmsId: string;
|
||||||
|
onOpenChange: (state: boolean) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const UpdateExternalKmsForm = ({ isOpen, kmsId, onOpenChange }: Props) => {
|
||||||
|
const { data: externalKms, isLoading } = useGetExternalKmsById(kmsId);
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||||
|
<ModalContent title="Edit configuration">
|
||||||
|
{isLoading && <ContentLoader />}
|
||||||
|
{externalKms?.external?.provider === ExternalKmsProvider.AWS && (
|
||||||
|
<AwsKmsForm
|
||||||
|
kms={externalKms}
|
||||||
|
onCancel={() => onOpenChange(false)}
|
||||||
|
onCompleted={() => onOpenChange(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user