mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 16:27:46 +00:00
misc: addressed comments
This commit is contained in:
@@ -35,7 +35,7 @@ export const registerPamSessionRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
credentials: z.any() // UNION DOES NOT WORK WITH ZOD SCHEMA
|
credentials: SessionCredentialsSchema
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -24,11 +24,10 @@ import { TGatewayV2ServiceFactory } from "../gateway-v2/gateway-v2-service";
|
|||||||
import { TLicenseServiceFactory } from "../license/license-service";
|
import { TLicenseServiceFactory } from "../license/license-service";
|
||||||
import { TPamFolderDALFactory } from "../pam-folder/pam-folder-dal";
|
import { TPamFolderDALFactory } from "../pam-folder/pam-folder-dal";
|
||||||
import { getFullPamFolderPath } from "../pam-folder/pam-folder-fns";
|
import { getFullPamFolderPath } from "../pam-folder/pam-folder-fns";
|
||||||
import { TMySQLResourceConnectionDetails } from "../pam-resource/mysql/mysql-resource-types";
|
|
||||||
import { TPamResourceDALFactory } from "../pam-resource/pam-resource-dal";
|
import { TPamResourceDALFactory } from "../pam-resource/pam-resource-dal";
|
||||||
import { PamResource } from "../pam-resource/pam-resource-enums";
|
import { PamResource } from "../pam-resource/pam-resource-enums";
|
||||||
import { TPamAccountCredentials } from "../pam-resource/pam-resource-types";
|
import { TPamAccountCredentials } from "../pam-resource/pam-resource-types";
|
||||||
import { TPostgresResourceConnectionDetails } from "../pam-resource/postgres/postgres-resource-types";
|
import { TSqlResourceConnectionDetails } from "../pam-resource/shared/sql/sql-resource-types";
|
||||||
import { TPamSessionDALFactory } from "../pam-session/pam-session-dal";
|
import { TPamSessionDALFactory } from "../pam-session/pam-session-dal";
|
||||||
import { PamSessionStatus } from "../pam-session/pam-session-enums";
|
import { PamSessionStatus } from "../pam-session/pam-session-enums";
|
||||||
import { OrgPermissionGatewayActions, OrgPermissionSubjects } from "../permission/org-permission";
|
import { OrgPermissionGatewayActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||||
@@ -492,7 +491,7 @@ export const pamAccountServiceFactory = ({
|
|||||||
encryptedConnectionDetails: resource.encryptedConnectionDetails,
|
encryptedConnectionDetails: resource.encryptedConnectionDetails,
|
||||||
kmsService,
|
kmsService,
|
||||||
projectId: account.projectId
|
projectId: account.projectId
|
||||||
})) as TMySQLResourceConnectionDetails | TPostgresResourceConnectionDetails;
|
})) as TSqlResourceConnectionDetails;
|
||||||
|
|
||||||
const credentials = await decryptAccountCredentials({
|
const credentials = await decryptAccountCredentials({
|
||||||
encryptedCredentials: account.encryptedCredentials,
|
encryptedCredentials: account.encryptedCredentials,
|
||||||
@@ -517,9 +516,7 @@ export const pamAccountServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
metadata = {
|
metadata = {
|
||||||
username: credentials.username,
|
username: credentials.username
|
||||||
accountName: account.name,
|
|
||||||
accountPath
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -20,25 +20,25 @@ export const SSHResourceListItemSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const SSHResourceConnectionDetailsSchema = z.object({
|
export const SSHResourceConnectionDetailsSchema = z.object({
|
||||||
host: z.string().trim(),
|
host: z.string().trim().max(255),
|
||||||
port: z.number()
|
port: z.number()
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SSHPasswordCredentialsSchema = z.object({
|
export const SSHPasswordCredentialsSchema = z.object({
|
||||||
authMethod: z.literal(SSHAuthMethod.Password),
|
authMethod: z.literal(SSHAuthMethod.Password),
|
||||||
username: z.string().trim(),
|
username: z.string().trim().max(255),
|
||||||
password: z.string().trim()
|
password: z.string().trim().max(255)
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SSHPublicKeyCredentialsSchema = z.object({
|
export const SSHPublicKeyCredentialsSchema = z.object({
|
||||||
authMethod: z.literal(SSHAuthMethod.PublicKey),
|
authMethod: z.literal(SSHAuthMethod.PublicKey),
|
||||||
username: z.string().trim(),
|
username: z.string().trim().max(255),
|
||||||
privateKey: z.string().trim()
|
privateKey: z.string().trim().max(5000)
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SSHCertificateCredentialsSchema = z.object({
|
export const SSHCertificateCredentialsSchema = z.object({
|
||||||
authMethod: z.literal(SSHAuthMethod.Certificate),
|
authMethod: z.literal(SSHAuthMethod.Certificate),
|
||||||
username: z.string().trim()
|
username: z.string().trim().max(255)
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SSHAccountCredentialsSchema = z.discriminatedUnion("authMethod", [
|
export const SSHAccountCredentialsSchema = z.discriminatedUnion("authMethod", [
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { TPamSessions } from "@app/db/schemas";
|
|||||||
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||||
import { KmsDataKey } from "@app/services/kms/kms-types";
|
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||||
|
|
||||||
import { TPamSanitizedSession, TPamSessionCommandLog, TTerminalEvent } from "./pam-session.types";
|
import { TPamSanitizedSession, TPamSessionCommandLog, TTerminalEvent } from "./pam-session-types";
|
||||||
|
|
||||||
export const decryptSessionCommandLogs = async ({
|
export const decryptSessionCommandLogs = async ({
|
||||||
projectId,
|
projectId,
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ import { TProjectDALFactory } from "@app/services/project/project-dal";
|
|||||||
import { TLicenseServiceFactory } from "../license/license-service";
|
import { TLicenseServiceFactory } from "../license/license-service";
|
||||||
import { OrgPermissionGatewayActions, OrgPermissionSubjects } from "../permission/org-permission";
|
import { OrgPermissionGatewayActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||||
import { ProjectPermissionPamSessionActions, ProjectPermissionSub } from "../permission/project-permission";
|
import { ProjectPermissionPamSessionActions, ProjectPermissionSub } from "../permission/project-permission";
|
||||||
import { TUpdateSessionLogsDTO } from "./pam-session.types";
|
|
||||||
import { TPamSessionDALFactory } from "./pam-session-dal";
|
import { TPamSessionDALFactory } from "./pam-session-dal";
|
||||||
import { PamSessionStatus } from "./pam-session-enums";
|
import { PamSessionStatus } from "./pam-session-enums";
|
||||||
import { decryptSession } from "./pam-session-fns";
|
import { decryptSession } from "./pam-session-fns";
|
||||||
|
import { TUpdateSessionLogsDTO } from "./pam-session-types";
|
||||||
|
|
||||||
type TPamSessionServiceFactoryDep = {
|
type TPamSessionServiceFactoryDep = {
|
||||||
pamSessionDAL: TPamSessionDALFactory;
|
pamSessionDAL: TPamSessionDALFactory;
|
||||||
|
|||||||
@@ -61,18 +61,15 @@ export const PamAccessAccountModal = ({ isOpen, onOpenChange, account }: Props)
|
|||||||
const command = useMemo(() => {
|
const command = useMemo(() => {
|
||||||
if (!account) return "";
|
if (!account) return "";
|
||||||
|
|
||||||
if (
|
switch (account.resource.resourceType) {
|
||||||
account.resource.resourceType === PamResourceType.Postgres ||
|
case PamResourceType.Postgres:
|
||||||
account.resource.resourceType === PamResourceType.MySQL
|
case PamResourceType.MySQL:
|
||||||
) {
|
return `infisical pam db access-account ${account.id} --duration ${cliDuration}`;
|
||||||
return `infisical pam db access-account ${account.id} --duration ${cliDuration}`;
|
case PamResourceType.SSH:
|
||||||
|
return `infisical pam ssh access-account ${account.id} --duration ${cliDuration}`;
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account.resource.resourceType === PamResourceType.SSH) {
|
|
||||||
return `infisical pam ssh ${account.id} --duration ${cliDuration}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}, [account, cliDuration]);
|
}, [account, cliDuration]);
|
||||||
|
|
||||||
if (!account) return null;
|
if (!account) return null;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { DiscriminativePick } from "@app/types";
|
|||||||
import { PamAccountHeader } from "../PamAccountHeader";
|
import { PamAccountHeader } from "../PamAccountHeader";
|
||||||
import { MySQLAccountForm } from "./MySQLAccountForm";
|
import { MySQLAccountForm } from "./MySQLAccountForm";
|
||||||
import { PostgresAccountForm } from "./PostgresAccountForm";
|
import { PostgresAccountForm } from "./PostgresAccountForm";
|
||||||
import { SSHAccountForm } from "./SSHAccountForm";
|
import { SshAccountForm } from "./SshAccountForm";
|
||||||
|
|
||||||
type FormProps = {
|
type FormProps = {
|
||||||
onComplete: (account: TPamAccount) => void;
|
onComplete: (account: TPamAccount) => void;
|
||||||
@@ -68,7 +68,7 @@ const CreateForm = ({
|
|||||||
);
|
);
|
||||||
case PamResourceType.SSH:
|
case PamResourceType.SSH:
|
||||||
return (
|
return (
|
||||||
<SSHAccountForm onSubmit={onSubmit} resourceId={resourceId} resourceType={resourceType} />
|
<SshAccountForm onSubmit={onSubmit} resourceId={resourceId} resourceType={resourceType} />
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unhandled resource: ${resourceType}`);
|
throw new Error(`Unhandled resource: ${resourceType}`);
|
||||||
@@ -99,7 +99,7 @@ const UpdateForm = ({ account, onComplete }: UpdateFormProps) => {
|
|||||||
case PamResourceType.MySQL:
|
case PamResourceType.MySQL:
|
||||||
return <MySQLAccountForm account={account as any} onSubmit={onSubmit} />;
|
return <MySQLAccountForm account={account as any} onSubmit={onSubmit} />;
|
||||||
case PamResourceType.SSH:
|
case PamResourceType.SSH:
|
||||||
return <SSHAccountForm account={account as any} onSubmit={onSubmit} />;
|
return <SshAccountForm account={account as any} onSubmit={onSubmit} />;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unhandled resource: ${account.resource.resourceType}`);
|
throw new Error(`Unhandled resource: ${account.resource.resourceType}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
import { FormProvider, useForm } from "react-hook-form";
|
|
||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
import { Button, ModalClose } from "@app/components/v2";
|
|
||||||
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 { GenericAccountFields, genericAccountFieldsSchema } from "./GenericAccountFields";
|
|
||||||
import { BaseSshAccountSchema } from "./shared/ssh-account-schemas";
|
|
||||||
import { SshAccountFields } from "./shared/SshAccountFields";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
account?: TSSHAccount;
|
|
||||||
resourceId?: string;
|
|
||||||
resourceType?: PamResourceType;
|
|
||||||
onSubmit: (formData: FormData) => Promise<void>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const formSchema = genericAccountFieldsSchema.extend({
|
|
||||||
credentials: BaseSshAccountSchema,
|
|
||||||
// We don't support rotation for now, just feed a false value to
|
|
||||||
// make the schema happy
|
|
||||||
rotationEnabled: z.boolean().default(false)
|
|
||||||
});
|
|
||||||
|
|
||||||
type FormData = z.infer<typeof formSchema>;
|
|
||||||
|
|
||||||
export const SSHAccountForm = ({ account, onSubmit }: Props) => {
|
|
||||||
const isUpdate = Boolean(account);
|
|
||||||
|
|
||||||
const getDefaultCredentials = () => {
|
|
||||||
if (!account) return undefined;
|
|
||||||
|
|
||||||
if (account.credentials.authMethod === SSHAuthMethod.Password) {
|
|
||||||
return {
|
|
||||||
...account.credentials,
|
|
||||||
password: UNCHANGED_PASSWORD_SENTINEL
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (account.credentials.authMethod === SSHAuthMethod.PublicKey) {
|
|
||||||
return {
|
|
||||||
...account.credentials,
|
|
||||||
privateKey: UNCHANGED_PASSWORD_SENTINEL
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return account.credentials;
|
|
||||||
};
|
|
||||||
|
|
||||||
const form = useForm<FormData>({
|
|
||||||
resolver: zodResolver(formSchema),
|
|
||||||
defaultValues: account
|
|
||||||
? {
|
|
||||||
...account,
|
|
||||||
credentials: getDefaultCredentials()
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
name: "",
|
|
||||||
description: "",
|
|
||||||
credentials: {
|
|
||||||
authMethod: SSHAuthMethod.Password,
|
|
||||||
username: "",
|
|
||||||
password: ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const {
|
|
||||||
handleSubmit,
|
|
||||||
formState: { isSubmitting, isDirty }
|
|
||||||
} = form;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FormProvider {...form}>
|
|
||||||
<form
|
|
||||||
onSubmit={(e) => {
|
|
||||||
handleSubmit(onSubmit)(e);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<GenericAccountFields />
|
|
||||||
<SshAccountFields isUpdate={isUpdate} />
|
|
||||||
<div className="mt-6 flex items-center">
|
|
||||||
<Button
|
|
||||||
className="mr-4"
|
|
||||||
size="sm"
|
|
||||||
type="submit"
|
|
||||||
colorSchema="secondary"
|
|
||||||
isLoading={isSubmitting}
|
|
||||||
isDisabled={isSubmitting || !isDirty}
|
|
||||||
>
|
|
||||||
{isUpdate ? "Update Account" : "Create Account"}
|
|
||||||
</Button>
|
|
||||||
<ModalClose asChild>
|
|
||||||
<Button colorSchema="secondary" variant="plain">
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</ModalClose>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</FormProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
+132
-3
@@ -1,11 +1,63 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
import { Controller, FormProvider, useForm, useFormContext, useWatch } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
import { FormControl, Input, Select, SelectItem, TextArea } from "@app/components/v2";
|
import {
|
||||||
|
Button,
|
||||||
|
FormControl,
|
||||||
|
Input,
|
||||||
|
ModalClose,
|
||||||
|
Select,
|
||||||
|
SelectItem,
|
||||||
|
TextArea
|
||||||
|
} from "@app/components/v2";
|
||||||
|
import { PamResourceType, TSSHAccount } from "@app/hooks/api/pam";
|
||||||
import { UNCHANGED_PASSWORD_SENTINEL } from "@app/hooks/api/pam/constants";
|
import { UNCHANGED_PASSWORD_SENTINEL } from "@app/hooks/api/pam/constants";
|
||||||
import { SSHAuthMethod } from "@app/hooks/api/pam/types/ssh-resource";
|
import { SSHAuthMethod } from "@app/hooks/api/pam/types/ssh-resource";
|
||||||
|
|
||||||
export const SshAccountFields = ({ isUpdate }: { isUpdate: boolean }) => {
|
import { GenericAccountFields, genericAccountFieldsSchema } from "./GenericAccountFields";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
account?: TSSHAccount;
|
||||||
|
resourceId?: string;
|
||||||
|
resourceType?: PamResourceType;
|
||||||
|
onSubmit: (formData: FormData) => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SSHPasswordCredentialsSchema = z.object({
|
||||||
|
authMethod: z.literal(SSHAuthMethod.Password),
|
||||||
|
username: z.string().trim().min(1, "Username is required"),
|
||||||
|
password: z.string().trim().min(1, "Password is required")
|
||||||
|
});
|
||||||
|
|
||||||
|
export const SSHPublicKeyCredentialsSchema = z.object({
|
||||||
|
authMethod: z.literal(SSHAuthMethod.PublicKey),
|
||||||
|
username: z.string().trim().min(1, "Username is required"),
|
||||||
|
privateKey: z.string().trim().min(1, "Private key is required")
|
||||||
|
});
|
||||||
|
|
||||||
|
export const SSHCertificateCredentialsSchema = z.object({
|
||||||
|
authMethod: z.literal(SSHAuthMethod.Certificate),
|
||||||
|
username: z.string().trim().min(1, "Username is required")
|
||||||
|
});
|
||||||
|
|
||||||
|
export const BaseSshAccountSchema = z.discriminatedUnion("authMethod", [
|
||||||
|
SSHPasswordCredentialsSchema,
|
||||||
|
SSHPublicKeyCredentialsSchema,
|
||||||
|
SSHCertificateCredentialsSchema
|
||||||
|
]);
|
||||||
|
|
||||||
|
const formSchema = genericAccountFieldsSchema.extend({
|
||||||
|
credentials: BaseSshAccountSchema,
|
||||||
|
// We don't support rotation for now, just feed a false value to
|
||||||
|
// make the schema happy
|
||||||
|
rotationEnabled: z.boolean().default(false)
|
||||||
|
});
|
||||||
|
|
||||||
|
type FormData = z.infer<typeof formSchema>;
|
||||||
|
|
||||||
|
const SshAccountFields = ({ isUpdate }: { isUpdate: boolean }) => {
|
||||||
const { control, setValue } = useFormContext();
|
const { control, setValue } = useFormContext();
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
|
|
||||||
@@ -141,3 +193,80 @@ export const SshAccountFields = ({ isUpdate }: { isUpdate: boolean }) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const SshAccountForm = ({ account, onSubmit }: Props) => {
|
||||||
|
const isUpdate = Boolean(account);
|
||||||
|
|
||||||
|
const getDefaultCredentials = () => {
|
||||||
|
if (!account) return undefined;
|
||||||
|
|
||||||
|
if (account.credentials.authMethod === SSHAuthMethod.Password) {
|
||||||
|
return {
|
||||||
|
...account.credentials,
|
||||||
|
password: UNCHANGED_PASSWORD_SENTINEL
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account.credentials.authMethod === SSHAuthMethod.PublicKey) {
|
||||||
|
return {
|
||||||
|
...account.credentials,
|
||||||
|
privateKey: UNCHANGED_PASSWORD_SENTINEL
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return account.credentials;
|
||||||
|
};
|
||||||
|
|
||||||
|
const form = useForm<FormData>({
|
||||||
|
resolver: zodResolver(formSchema),
|
||||||
|
defaultValues: account
|
||||||
|
? {
|
||||||
|
...account,
|
||||||
|
credentials: getDefaultCredentials()
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
name: "",
|
||||||
|
description: "",
|
||||||
|
credentials: {
|
||||||
|
authMethod: SSHAuthMethod.Password,
|
||||||
|
username: "",
|
||||||
|
password: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
handleSubmit,
|
||||||
|
formState: { isSubmitting, isDirty }
|
||||||
|
} = form;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormProvider {...form}>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
handleSubmit(onSubmit)(e);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<GenericAccountFields />
|
||||||
|
<SshAccountFields isUpdate={isUpdate} />
|
||||||
|
<div className="mt-6 flex items-center">
|
||||||
|
<Button
|
||||||
|
className="mr-4"
|
||||||
|
size="sm"
|
||||||
|
type="submit"
|
||||||
|
colorSchema="secondary"
|
||||||
|
isLoading={isSubmitting}
|
||||||
|
isDisabled={isSubmitting || !isDirty}
|
||||||
|
>
|
||||||
|
{isUpdate ? "Update Account" : "Create Account"}
|
||||||
|
</Button>
|
||||||
|
<ModalClose asChild>
|
||||||
|
<Button colorSchema="secondary" variant="plain">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</ModalClose>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</FormProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
-26
@@ -1,26 +0,0 @@
|
|||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
import { SSHAuthMethod } from "@app/hooks/api/pam/types/ssh-resource";
|
|
||||||
|
|
||||||
export const SSHPasswordCredentialsSchema = z.object({
|
|
||||||
authMethod: z.literal(SSHAuthMethod.Password),
|
|
||||||
username: z.string().trim().min(1, "Username is required"),
|
|
||||||
password: z.string().trim().min(1, "Password is required")
|
|
||||||
});
|
|
||||||
|
|
||||||
export const SSHPublicKeyCredentialsSchema = z.object({
|
|
||||||
authMethod: z.literal(SSHAuthMethod.PublicKey),
|
|
||||||
username: z.string().trim().min(1, "Username is required"),
|
|
||||||
privateKey: z.string().trim().min(1, "Private key is required")
|
|
||||||
});
|
|
||||||
|
|
||||||
export const SSHCertificateCredentialsSchema = z.object({
|
|
||||||
authMethod: z.literal(SSHAuthMethod.Certificate),
|
|
||||||
username: z.string().trim().min(1, "Username is required")
|
|
||||||
});
|
|
||||||
|
|
||||||
export const BaseSshAccountSchema = z.discriminatedUnion("authMethod", [
|
|
||||||
SSHPasswordCredentialsSchema,
|
|
||||||
SSHPublicKeyCredentialsSchema,
|
|
||||||
SSHCertificateCredentialsSchema
|
|
||||||
]);
|
|
||||||
+6
-2
@@ -5,15 +5,19 @@ import { z } from "zod";
|
|||||||
import { Button, ModalClose } from "@app/components/v2";
|
import { Button, ModalClose } from "@app/components/v2";
|
||||||
import { PamResourceType, TSSHResource } from "@app/hooks/api/pam";
|
import { PamResourceType, TSSHResource } from "@app/hooks/api/pam";
|
||||||
|
|
||||||
import { GenericResourceFields, genericResourceFieldsSchema } from "./GenericResourceFields";
|
|
||||||
import { BaseSshConnectionDetailsSchema } from "./shared/ssh-resource-schemas";
|
|
||||||
import { SshResourceFields } from "./shared/SshResourceFields";
|
import { SshResourceFields } from "./shared/SshResourceFields";
|
||||||
|
import { GenericResourceFields, genericResourceFieldsSchema } from "./GenericResourceFields";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
resource?: TSSHResource;
|
resource?: TSSHResource;
|
||||||
onSubmit: (formData: FormData) => Promise<void>;
|
onSubmit: (formData: FormData) => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const BaseSshConnectionDetailsSchema = z.object({
|
||||||
|
host: z.string().trim().min(1, "Host is required"),
|
||||||
|
port: z.number().int().min(1).max(65535)
|
||||||
|
});
|
||||||
|
|
||||||
const formSchema = genericResourceFieldsSchema.extend({
|
const formSchema = genericResourceFieldsSchema.extend({
|
||||||
resourceType: z.literal(PamResourceType.SSH),
|
resourceType: z.literal(PamResourceType.SSH),
|
||||||
connectionDetails: BaseSshConnectionDetailsSchema
|
connectionDetails: BaseSshConnectionDetailsSchema
|
||||||
|
|||||||
-31
@@ -1,31 +0,0 @@
|
|||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
import { SSHAuthMethod } from "@app/hooks/api/pam/types/ssh-resource";
|
|
||||||
|
|
||||||
export const BaseSshConnectionDetailsSchema = z.object({
|
|
||||||
host: z.string().trim().min(1, "Host is required"),
|
|
||||||
port: z.number().int().min(1).max(65535)
|
|
||||||
});
|
|
||||||
|
|
||||||
export const SSHPasswordCredentialsSchema = z.object({
|
|
||||||
authMethod: z.literal(SSHAuthMethod.Password),
|
|
||||||
username: z.string().trim().min(1, "Username is required"),
|
|
||||||
password: z.string().trim().min(1, "Password is required")
|
|
||||||
});
|
|
||||||
|
|
||||||
export const SSHPublicKeyCredentialsSchema = z.object({
|
|
||||||
authMethod: z.literal(SSHAuthMethod.PublicKey),
|
|
||||||
username: z.string().trim().min(1, "Username is required"),
|
|
||||||
privateKey: z.string().trim().min(1, "Private key is required")
|
|
||||||
});
|
|
||||||
|
|
||||||
export const SSHCertificateCredentialsSchema = z.object({
|
|
||||||
authMethod: z.literal(SSHAuthMethod.Certificate),
|
|
||||||
username: z.string().trim().min(1, "Username is required")
|
|
||||||
});
|
|
||||||
|
|
||||||
export const BaseSshAccountSchema = z.discriminatedUnion("authMethod", [
|
|
||||||
SSHPasswordCredentialsSchema,
|
|
||||||
SSHPublicKeyCredentialsSchema,
|
|
||||||
SSHCertificateCredentialsSchema
|
|
||||||
]);
|
|
||||||
Reference in New Issue
Block a user