mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
misc: addressed comments
This commit is contained in:
@@ -35,7 +35,7 @@ export const registerPamSessionRouter = async (server: FastifyZodProvider) => {
|
||||
}),
|
||||
response: {
|
||||
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 { TPamFolderDALFactory } from "../pam-folder/pam-folder-dal";
|
||||
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 { PamResource } from "../pam-resource/pam-resource-enums";
|
||||
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 { PamSessionStatus } from "../pam-session/pam-session-enums";
|
||||
import { OrgPermissionGatewayActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||
@@ -492,7 +491,7 @@ export const pamAccountServiceFactory = ({
|
||||
encryptedConnectionDetails: resource.encryptedConnectionDetails,
|
||||
kmsService,
|
||||
projectId: account.projectId
|
||||
})) as TMySQLResourceConnectionDetails | TPostgresResourceConnectionDetails;
|
||||
})) as TSqlResourceConnectionDetails;
|
||||
|
||||
const credentials = await decryptAccountCredentials({
|
||||
encryptedCredentials: account.encryptedCredentials,
|
||||
@@ -517,9 +516,7 @@ export const pamAccountServiceFactory = ({
|
||||
});
|
||||
|
||||
metadata = {
|
||||
username: credentials.username,
|
||||
accountName: account.name,
|
||||
accountPath
|
||||
username: credentials.username
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -20,25 +20,25 @@ export const SSHResourceListItemSchema = z.object({
|
||||
});
|
||||
|
||||
export const SSHResourceConnectionDetailsSchema = z.object({
|
||||
host: z.string().trim(),
|
||||
host: z.string().trim().max(255),
|
||||
port: z.number()
|
||||
});
|
||||
|
||||
export const SSHPasswordCredentialsSchema = z.object({
|
||||
authMethod: z.literal(SSHAuthMethod.Password),
|
||||
username: z.string().trim(),
|
||||
password: z.string().trim()
|
||||
username: z.string().trim().max(255),
|
||||
password: z.string().trim().max(255)
|
||||
});
|
||||
|
||||
export const SSHPublicKeyCredentialsSchema = z.object({
|
||||
authMethod: z.literal(SSHAuthMethod.PublicKey),
|
||||
username: z.string().trim(),
|
||||
privateKey: z.string().trim()
|
||||
username: z.string().trim().max(255),
|
||||
privateKey: z.string().trim().max(5000)
|
||||
});
|
||||
|
||||
export const SSHCertificateCredentialsSchema = z.object({
|
||||
authMethod: z.literal(SSHAuthMethod.Certificate),
|
||||
username: z.string().trim()
|
||||
username: z.string().trim().max(255)
|
||||
});
|
||||
|
||||
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 { 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 ({
|
||||
projectId,
|
||||
|
||||
@@ -12,10 +12,10 @@ import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||
import { TLicenseServiceFactory } from "../license/license-service";
|
||||
import { OrgPermissionGatewayActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||
import { ProjectPermissionPamSessionActions, ProjectPermissionSub } from "../permission/project-permission";
|
||||
import { TUpdateSessionLogsDTO } from "./pam-session.types";
|
||||
import { TPamSessionDALFactory } from "./pam-session-dal";
|
||||
import { PamSessionStatus } from "./pam-session-enums";
|
||||
import { decryptSession } from "./pam-session-fns";
|
||||
import { TUpdateSessionLogsDTO } from "./pam-session-types";
|
||||
|
||||
type TPamSessionServiceFactoryDep = {
|
||||
pamSessionDAL: TPamSessionDALFactory;
|
||||
|
||||
@@ -61,18 +61,15 @@ export const PamAccessAccountModal = ({ isOpen, onOpenChange, account }: Props)
|
||||
const command = useMemo(() => {
|
||||
if (!account) return "";
|
||||
|
||||
if (
|
||||
account.resource.resourceType === PamResourceType.Postgres ||
|
||||
account.resource.resourceType === PamResourceType.MySQL
|
||||
) {
|
||||
return `infisical pam db access-account ${account.id} --duration ${cliDuration}`;
|
||||
switch (account.resource.resourceType) {
|
||||
case PamResourceType.Postgres:
|
||||
case PamResourceType.MySQL:
|
||||
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]);
|
||||
|
||||
if (!account) return null;
|
||||
|
||||
@@ -10,7 +10,7 @@ import { DiscriminativePick } from "@app/types";
|
||||
import { PamAccountHeader } from "../PamAccountHeader";
|
||||
import { MySQLAccountForm } from "./MySQLAccountForm";
|
||||
import { PostgresAccountForm } from "./PostgresAccountForm";
|
||||
import { SSHAccountForm } from "./SSHAccountForm";
|
||||
import { SshAccountForm } from "./SshAccountForm";
|
||||
|
||||
type FormProps = {
|
||||
onComplete: (account: TPamAccount) => void;
|
||||
@@ -68,7 +68,7 @@ const CreateForm = ({
|
||||
);
|
||||
case PamResourceType.SSH:
|
||||
return (
|
||||
<SSHAccountForm onSubmit={onSubmit} resourceId={resourceId} resourceType={resourceType} />
|
||||
<SshAccountForm onSubmit={onSubmit} resourceId={resourceId} resourceType={resourceType} />
|
||||
);
|
||||
default:
|
||||
throw new Error(`Unhandled resource: ${resourceType}`);
|
||||
@@ -99,7 +99,7 @@ const UpdateForm = ({ account, onComplete }: UpdateFormProps) => {
|
||||
case PamResourceType.MySQL:
|
||||
return <MySQLAccountForm account={account as any} onSubmit={onSubmit} />;
|
||||
case PamResourceType.SSH:
|
||||
return <SSHAccountForm account={account as any} onSubmit={onSubmit} />;
|
||||
return <SshAccountForm account={account as any} onSubmit={onSubmit} />;
|
||||
default:
|
||||
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>
|
||||
);
|
||||
};
|
||||
@@ -1,11 +1,63 @@
|
||||
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 { 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 [showPassword, setShowPassword] = useState(false);
|
||||
|
||||
@@ -141,3 +193,80 @@ export const SshAccountFields = ({ isUpdate }: { isUpdate: boolean }) => {
|
||||
</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>
|
||||
);
|
||||
};
|
||||
@@ -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
|
||||
]);
|
||||
@@ -5,15 +5,19 @@ import { z } from "zod";
|
||||
import { Button, ModalClose } from "@app/components/v2";
|
||||
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 { GenericResourceFields, genericResourceFieldsSchema } from "./GenericResourceFields";
|
||||
|
||||
type Props = {
|
||||
resource?: TSSHResource;
|
||||
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({
|
||||
resourceType: z.literal(PamResourceType.SSH),
|
||||
connectionDetails: BaseSshConnectionDetailsSchema
|
||||
|
||||
@@ -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