import { useEffect, useState } from "react"; import { Helmet } from "react-helmet"; import { Controller, useForm } from "react-hook-form"; import { faArrowUpRightFromSquare, faBookOpen, faBugs } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; import { useNavigate, useSearch } from "@tanstack/react-router"; import { motion } from "framer-motion"; import { z } from "zod"; import { Button, Card, CardTitle, FormControl, Input, Modal, ModalContent, Select, SelectItem, Switch, Tab, TabList, TabPanel, Tabs } from "@app/components/v2"; import { SecretPathInput } from "@app/components/v2/SecretPathInput"; import { ROUTE_PATHS } from "@app/const/routes"; import { useWorkspace } from "@app/context"; import { usePopUp } from "@app/hooks"; import { useCreateIntegration } from "@app/hooks/api"; import { useGetIntegrationAuthApps, useGetIntegrationAuthById } from "@app/hooks/api/integrationAuth"; import { IntegrationsListPageTabs } from "@app/types/integrations"; enum TabSections { Connection = "connection", Options = "options" } const schema = z.object({ selectedSourceEnvironment: z.string(), secretPath: z.string(), targetAppId: z.string(), secretPrefix: z.string().trim().optional(), secretSuffix: z.string().trim().optional(), shouldLabel: z.boolean().optional(), labelName: z.string().trim().optional(), labelValue: z.string().trim().optional() }); type FormData = z.infer; export const GcpSecretManagerConfigurePage = () => { const navigate = useNavigate(); const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([ "confirmIntegration" ] as const); const { currentWorkspace } = useWorkspace(); const { control, handleSubmit, setValue, watch } = useForm({ resolver: zodResolver(schema), defaultValues: { secretPath: "/", secretPrefix: "", secretSuffix: "", shouldLabel: false, labelName: "managed-by", labelValue: "infisical", selectedSourceEnvironment: currentWorkspace.environments[0].slug } }); const shouldLabel = watch("shouldLabel"); const selectedSourceEnvironment = watch("selectedSourceEnvironment"); const { mutateAsync } = useCreateIntegration(); const integrationAuthId = useSearch({ from: ROUTE_PATHS.SecretManager.Integratons.GcpSecretManagerConfigurePage.id, select: (el) => el.integrationAuthId }); const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? ""); const { data: integrationAuthApps, isPending: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({ integrationAuthId: (integrationAuthId as string) ?? "" }); const [isLoading, setIsLoading] = useState(false); useEffect(() => { if (shouldLabel) { setValue("labelName", "managed-by"); setValue("labelValue", "infisical"); return; } setValue("labelName", ""); setValue("labelValue", ""); }, [shouldLabel]); useEffect(() => { if (integrationAuthApps) { if (integrationAuthApps.length > 0) { setValue("targetAppId", integrationAuthApps[0].appId as string); } else { setValue("targetAppId", "none"); } } }, [integrationAuthApps]); const onFormSubmit = async ({ selectedSourceEnvironment: sce, secretPath, targetAppId, secretPrefix, secretSuffix, shouldLabel: sl, labelName, labelValue }: FormData) => { try { setIsLoading(true); if (!integrationAuth?.id) return; await mutateAsync({ integrationAuthId: integrationAuth?.id, isActive: true, app: integrationAuthApps?.find( (integrationAuthApp) => integrationAuthApp.appId === targetAppId )?.name, appId: targetAppId, sourceEnvironment: sce, secretPath, metadata: { ...(secretPrefix ? { secretPrefix } : {}), ...(secretSuffix ? { secretSuffix } : {}), ...(sl ? { secretGCPLabel: { labelName, labelValue } } : {}) } }); setIsLoading(false); navigate({ to: "/secret-manager/$projectId/integrations", params: { projectId: currentWorkspace.id }, search: { selectedTab: IntegrationsListPageTabs.NativeIntegrations } }); } catch (err) { console.error(err); setIsLoading(false); } }; return integrationAuth && selectedSourceEnvironment && integrationAuthApps ? (
{ if (!data.secretPrefix && !data.secretSuffix && !data.shouldLabel) { handlePopUpOpen("confirmIntegration", data); return; } onFormSubmit(data); })} className="flex h-full w-full flex-col items-center justify-center" > Set Up GCP Secret Manager Integration
GCP logo
GCP Secret Manager Integration
Docs
Connection Options
( )} /> ( )} /> { return ( ); }} /> ( )} /> ( )} />
( onChange(isChecked)} isChecked={value} > Label in GCP Secret Manager )} />
{shouldLabel && (
( )} /> ( )} />
)}
{/*
Pro Tip
After creating an integration, your secrets will start syncing immediately. To avoid overwriting existing secrets in GCP Secret Manager, you may consider adding a secret prefix/suffix and/or enabling labeling in the options tab.
*/} handlePopUpToggle("confirmIntegration", isOpen)} >
} >

You're about to overwrite any existing secrets in GCP Secret Manager.

To avoid this behavior, you may consider adding a secret prefix/suffix or enabling labeling in the options tab.

) : (
Set Up GCP Secret Manager Integration {isIntegrationAuthAppsLoading ? ( infisical loading indicator ) : (

Something went wrong. Please contact{" "} support@infisical.com {" "} if the issue persists.

)}
); };