mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 13:27:22 +00:00
Revise ssh host alias field handling/validation
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
@@ -8,6 +7,7 @@ import { isValidHostname } from "@app/ee/services/ssh-host/ssh-host-validators";
|
|||||||
import { SSH_HOSTS } from "@app/lib/api-docs";
|
import { SSH_HOSTS } from "@app/lib/api-docs";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
import { publicSshCaLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { publicSshCaLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@@ -102,15 +102,7 @@ export const registerSshHostRouter = async (server: FastifyZodProvider) => {
|
|||||||
message: "Hostname must be a valid hostname"
|
message: "Hostname must be a valid hostname"
|
||||||
})
|
})
|
||||||
.describe(SSH_HOSTS.CREATE.hostname),
|
.describe(SSH_HOSTS.CREATE.hostname),
|
||||||
alias: z
|
alias: slugSchema({ min: 0, max: 64, field: "alias" }).describe(SSH_HOSTS.CREATE.alias).default(""),
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.nullable()
|
|
||||||
.default(null)
|
|
||||||
.refine((v) => v == null || slugify(v) === v, {
|
|
||||||
message: "Alias must be a valid slug"
|
|
||||||
})
|
|
||||||
.describe(SSH_HOSTS.CREATE.alias),
|
|
||||||
userCertTtl: z
|
userCertTtl: z
|
||||||
.string()
|
.string()
|
||||||
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
||||||
@@ -185,15 +177,7 @@ export const registerSshHostRouter = async (server: FastifyZodProvider) => {
|
|||||||
})
|
})
|
||||||
.optional()
|
.optional()
|
||||||
.describe(SSH_HOSTS.UPDATE.hostname),
|
.describe(SSH_HOSTS.UPDATE.hostname),
|
||||||
alias: z
|
alias: slugSchema({ min: 0, max: 64, field: "alias" }).describe(SSH_HOSTS.UPDATE.alias).optional(),
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.nullable()
|
|
||||||
.refine((v) => v == null || slugify(v) === v, {
|
|
||||||
message: "Alias must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe(SSH_HOSTS.UPDATE.alias),
|
|
||||||
userCertTtl: z
|
userCertTtl: z
|
||||||
.string()
|
.string()
|
||||||
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ export const sshHostServiceFactory = ({
|
|||||||
{
|
{
|
||||||
projectId,
|
projectId,
|
||||||
hostname,
|
hostname,
|
||||||
alias,
|
alias: alias === "" ? null : alias,
|
||||||
userCertTtl,
|
userCertTtl,
|
||||||
hostCertTtl,
|
hostCertTtl,
|
||||||
userSshCaId,
|
userSshCaId,
|
||||||
@@ -300,7 +300,7 @@ export const sshHostServiceFactory = ({
|
|||||||
sshHostId,
|
sshHostId,
|
||||||
{
|
{
|
||||||
hostname,
|
hostname,
|
||||||
alias,
|
alias: alias === "" ? null : alias,
|
||||||
userCertTtl,
|
userCertTtl,
|
||||||
hostCertTtl
|
hostCertTtl
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export type TListSshHostsDTO = Omit<TProjectPermission, "projectId">;
|
|||||||
|
|
||||||
export type TCreateSshHostDTO = {
|
export type TCreateSshHostDTO = {
|
||||||
hostname: string;
|
hostname: string;
|
||||||
alias: string | null;
|
alias?: string;
|
||||||
userCertTtl: string;
|
userCertTtl: string;
|
||||||
hostCertTtl: string;
|
hostCertTtl: string;
|
||||||
loginMappings: {
|
loginMappings: {
|
||||||
@@ -20,7 +20,7 @@ export type TCreateSshHostDTO = {
|
|||||||
export type TUpdateSshHostDTO = {
|
export type TUpdateSshHostDTO = {
|
||||||
sshHostId: string;
|
sshHostId: string;
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
alias?: string | null;
|
alias?: string;
|
||||||
userCertTtl?: string;
|
userCertTtl?: string;
|
||||||
hostCertTtl?: string;
|
hostCertTtl?: string;
|
||||||
loginMappings?: {
|
loginMappings?: {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export type TSshHost = {
|
|||||||
export type TCreateSshHostDTO = {
|
export type TCreateSshHostDTO = {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
alias: string | null;
|
alias?: string;
|
||||||
userCertTtl?: string;
|
userCertTtl?: string;
|
||||||
hostCertTtl?: string;
|
hostCertTtl?: string;
|
||||||
loginMappings: {
|
loginMappings: {
|
||||||
@@ -30,7 +30,7 @@ export type TCreateSshHostDTO = {
|
|||||||
export type TUpdateSshHostDTO = {
|
export type TUpdateSshHostDTO = {
|
||||||
sshHostId: string;
|
sshHostId: string;
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
alias?: string | null;
|
alias?: string;
|
||||||
userCertTtl?: string;
|
userCertTtl?: string;
|
||||||
hostCertTtl?: string;
|
hostCertTtl?: string;
|
||||||
loginMappings?: {
|
loginMappings?: {
|
||||||
|
|||||||
@@ -134,15 +134,15 @@ export const SshHostModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const processedAlias = alias.trim() || null;
|
const trimmedAlias = alias.trim();
|
||||||
|
|
||||||
// check if there is already a different host with the same non-null alias
|
// check if there is already a different host with the same non-null alias
|
||||||
if (processedAlias) {
|
if (trimmedAlias) {
|
||||||
const existingAliases =
|
const existingAliases =
|
||||||
sshHosts?.filter((h) => h.id !== sshHost?.id && h.alias !== null).map((h) => h.alias) ||
|
sshHosts?.filter((h) => h.id !== sshHost?.id && h.alias !== null).map((h) => h.alias) ||
|
||||||
[];
|
[];
|
||||||
|
|
||||||
if (existingAliases.includes(processedAlias)) {
|
if (existingAliases.includes(trimmedAlias)) {
|
||||||
createNotification({
|
createNotification({
|
||||||
text: "A host with this alias already exists.",
|
text: "A host with this alias already exists.",
|
||||||
type: "error"
|
type: "error"
|
||||||
@@ -155,7 +155,7 @@ export const SshHostModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
await updateMutateAsync({
|
await updateMutateAsync({
|
||||||
sshHostId: sshHost.id,
|
sshHostId: sshHost.id,
|
||||||
hostname,
|
hostname,
|
||||||
alias: processedAlias,
|
alias: trimmedAlias,
|
||||||
userCertTtl,
|
userCertTtl,
|
||||||
loginMappings: loginMappings.map(({ loginUser, allowedPrincipals }) => ({
|
loginMappings: loginMappings.map(({ loginUser, allowedPrincipals }) => ({
|
||||||
loginUser,
|
loginUser,
|
||||||
@@ -168,7 +168,7 @@ export const SshHostModal = ({ popUp, handlePopUpToggle }: Props) => {
|
|||||||
await createMutateAsync({
|
await createMutateAsync({
|
||||||
projectId,
|
projectId,
|
||||||
hostname,
|
hostname,
|
||||||
alias: processedAlias,
|
alias: trimmedAlias,
|
||||||
userCertTtl,
|
userCertTtl,
|
||||||
loginMappings: loginMappings.map(({ loginUser, allowedPrincipals }) => ({
|
loginMappings: loginMappings.map(({ loginUser, allowedPrincipals }) => ({
|
||||||
loginUser,
|
loginUser,
|
||||||
|
|||||||
Reference in New Issue
Block a user