import { ChangeEvent, useRef, useState } from "react"; import { Controller, useForm } from "react-hook-form"; import { faUpload } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; import FileSaver from "file-saver"; import { z } from "zod"; import { createNotification } from "@app/components/notifications"; import { ProjectPermissionCan } from "@app/components/permissions"; import { Button, FormControl, IconButton, Modal, ModalContent, Select, SelectItem } from "@app/components/v2"; import { ProjectPermissionActions, ProjectPermissionSub, useOrganization, useProject } from "@app/context"; import { usePopUp, useToggle } from "@app/hooks"; import { useGetActiveProjectKms, useGetExternalKmsList, useLoadProjectKmsBackup, useUpdateProjectKms } from "@app/hooks/api"; import { fetchProjectKmsBackup } from "@app/hooks/api/kms/queries"; import { INTERNAL_KMS_KEY_ID, KmsType } from "@app/hooks/api/kms/types"; import { Organization, Project } from "@app/hooks/api/types"; const formSchema = z.object({ kmsKeyId: z.string() }); type TForm = z.infer; const BackupConfirmationModal = ({ isOpen, onOpenChange, org, project }: { isOpen: boolean; onOpenChange: (state: boolean) => void; org?: Organization; project?: Project; }) => { const [isGeneratingBackup, setGeneratingBackup] = useToggle(); const downloadKmsBackup = async () => { if (!project || !org) { return; } setGeneratingBackup.on(); try { const { secretManager } = await fetchProjectKmsBackup(project.id); const [, , kmsFunction] = secretManager.split("."); const file = secretManager; const blob = new Blob([file], { type: "text/plain;charset=utf-8" }); FileSaver.saveAs(blob, `kms-backup-${org.slug}-${project.slug}-${kmsFunction}.infisical.txt`); onOpenChange(false); } catch (err) { console.error(err); createNotification({ text: "Failed to create KMS backup", type: "error" }); } setGeneratingBackup.off(); }; return (

In case of interruptions with your configured external KMS, you can load a backup to set the project's KMS back to the default Infisical KMS.

); }; const LoadBackupModal = ({ isOpen, onOpenChange, org, workspace: project }: { isOpen: boolean; onOpenChange: (state: boolean) => void; org?: Organization; workspace: Project; }) => { const fileUploadRef = useRef(null); const { mutateAsync: loadKmsBackup, isPending } = useLoadProjectKmsBackup(project.id); const [backupContent, setBackupContent] = useState(""); const [backupFileName, setBackupFileName] = useState(""); const uploadKmsBackup = async () => { if (!project || !org) { return; } try { await loadKmsBackup(backupContent); createNotification({ text: "Successfully loaded KMS backup", type: "success" }); onOpenChange(false); } catch (err) { console.error(err); } }; const parseFile = (file?: File) => { if (!file) { createNotification({ text: "Failed to parse uploaded file.", type: "error" }); return; } const reader = new FileReader(); reader.onload = (event) => { if (!event?.target?.result) return; const data = event.target.result.toString(); setBackupContent(data); }; try { reader.readAsText(file); } catch (error) { console.log(error); } }; const handleFileUpload = (e: ChangeEvent) => { e.preventDefault(); parseFile(e.target?.files?.[0]); setBackupFileName(e.target?.files?.[0]?.name || ""); }; return ( { setBackupContent(""); setBackupFileName(""); onOpenChange(state); }} >

By loading a backup, the project's KMS will be switched to the default Infisical KMS.

{ fileUploadRef?.current?.click(); }} >
{backupFileName && (
{backupFileName}
)} {backupContent && ( )}
); }; export const EncryptionTab = () => { const { currentOrg } = useOrganization(); const { currentProject } = useProject(); const { data: externalKmsList } = useGetExternalKmsList(currentOrg.id); const { data: activeKms } = useGetActiveProjectKms(currentProject.id); const { mutateAsync: updateProjectKms, isPending: isUpdatingProjectKms } = useUpdateProjectKms( currentProject.id ); const { popUp, handlePopUpToggle, handlePopUpOpen } = usePopUp([ "createBackupConfirmation", "loadBackup" ] as const); const kmsKeyId = activeKms?.isExternal ? activeKms.id : INTERNAL_KMS_KEY_ID; const { handleSubmit, control, formState: { isSubmitting, isDirty } } = useForm({ resolver: zodResolver(formSchema), values: { kmsKeyId } }); const onUpdateProjectKms = async (data: TForm) => { try { await updateProjectKms( data.kmsKeyId === INTERNAL_KMS_KEY_ID ? { type: KmsType.Internal } : { type: KmsType.External, kmsId: data.kmsKeyId } ); createNotification({ text: "Successfully updated project KMS", type: "success" }); } catch (err) { console.error(err); } }; return (

Key Management

{kmsKeyId !== INTERNAL_KMS_KEY_ID && (
)}

Select which Key Management System to use for encrypting your project data

{(isAllowed) => ( ( )} control={control} name="kmsKeyId" /> )} {(isAllowed) => ( )}
handlePopUpToggle("createBackupConfirmation", state)} org={currentOrg} project={currentProject} /> handlePopUpToggle("loadBackup", state)} org={currentOrg} workspace={currentProject} />
); };