From b634e09ad312cb077774b03c417b998df138513d Mon Sep 17 00:00:00 2001 From: x032205 Date: Fri, 19 Dec 2025 14:21:35 -0500 Subject: [PATCH] show cert auth setup after resource creation and on account modal if credentials are cert --- .../PamAccountForm/SshAccountForm.tsx | 14 ++- .../components/PamAddResourceModal.tsx | 45 +++++++-- .../PamResourceForm/SSHResourceForm.tsx | 90 +---------------- .../pages/pam/components/SshCaSetupModal.tsx | 28 ++++++ .../pam/components/SshCaSetupSection.tsx | 98 +++++++++++++++++++ 5 files changed, 170 insertions(+), 105 deletions(-) create mode 100644 frontend/src/pages/pam/components/SshCaSetupModal.tsx create mode 100644 frontend/src/pages/pam/components/SshCaSetupSection.tsx diff --git a/frontend/src/pages/pam/PamAccountsPage/components/PamAccountForm/SshAccountForm.tsx b/frontend/src/pages/pam/PamAccountsPage/components/PamAccountForm/SshAccountForm.tsx index 305d8a2fdf..05d8eb6f0d 100644 --- a/frontend/src/pages/pam/PamAccountsPage/components/PamAccountForm/SshAccountForm.tsx +++ b/frontend/src/pages/pam/PamAccountsPage/components/PamAccountForm/SshAccountForm.tsx @@ -16,6 +16,7 @@ import { PamResourceType, TSSHAccount } from "@app/hooks/api/pam"; import { UNCHANGED_PASSWORD_SENTINEL } from "@app/hooks/api/pam/constants"; import { SSHAuthMethod } from "@app/hooks/api/pam/types/ssh-resource"; +import { SshCaSetupSection } from "../../../components/SshCaSetupSection"; import { GenericAccountFields, genericAccountFieldsSchema } from "./GenericAccountFields"; type Props = { @@ -57,7 +58,7 @@ const formSchema = genericAccountFieldsSchema.extend({ type FormData = z.infer; -const SshAccountFields = ({ isUpdate }: { isUpdate: boolean }) => { +const SshAccountFields = ({ isUpdate, resourceId }: { isUpdate: boolean; resourceId: string }) => { const { control, setValue } = useFormContext(); const [showPassword, setShowPassword] = useState(false); @@ -185,17 +186,14 @@ const SshAccountFields = ({ isUpdate }: { isUpdate: boolean }) => { /> )} - {authMethod === SSHAuthMethod.Certificate && ( -

- Certificate-based authentication will use the certificate configured on the SSH resource. -

- )} + {authMethod === SSHAuthMethod.Certificate && } ); }; -export const SshAccountForm = ({ account, onSubmit }: Props) => { +export const SshAccountForm = ({ account, resourceId, onSubmit }: Props) => { const isUpdate = Boolean(account); + const effectiveResourceId = resourceId || account?.resource.id || ""; const getDefaultCredentials = () => { if (!account) return undefined; @@ -248,7 +246,7 @@ export const SshAccountForm = ({ account, onSubmit }: Props) => { }} > - +
- + {isUpdate && }
+
+ + + ); +}; diff --git a/frontend/src/pages/pam/components/SshCaSetupSection.tsx b/frontend/src/pages/pam/components/SshCaSetupSection.tsx new file mode 100644 index 0000000000..e435d0e32f --- /dev/null +++ b/frontend/src/pages/pam/components/SshCaSetupSection.tsx @@ -0,0 +1,98 @@ +import { useState } from "react"; +import { faCopy } from "@fortawesome/free-regular-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { ChevronDownIcon, ShieldIcon } from "lucide-react"; +import { twMerge } from "tailwind-merge"; + +import { createNotification } from "@app/components/notifications"; +import { IconButton, Input } from "@app/components/v2"; +import { getAuthToken } from "@app/hooks/api/reactQuery"; + +type Props = { + resourceId: string; + isOptional?: boolean; + className?: string; +}; + +export const SshCaSetupSection = ({ resourceId, isOptional = false, className }: Props) => { + const { protocol, hostname, port } = window.location; + const portSuffix = port && port !== "80" ? `:${port}` : ""; + const siteURL = `${protocol}//${hostname}${portSuffix}`; + + const [cmdOpen, setCmdOpen] = useState(false); + + const setupSshCaCommand = `curl -H "Authorization: Bearer ${getAuthToken()}" "${siteURL}/api/v1/pam/resources/ssh/${resourceId}/ssh-ca-setup" | sudo bash`; + + return ( + + ); +};