Use ssh like mode host

This commit is contained in:
Owen
2026-06-11 11:11:50 -07:00
parent 71273e1b1c
commit 5baf0c3c09
6 changed files with 28 additions and 13 deletions

View File

@@ -415,7 +415,11 @@ export async function updatePrivateResources(
} else { } else {
let aliasAddress: string | null = null; let aliasAddress: string | null = null;
let releaseAliasLock: (() => Promise<void>) | null = null; let releaseAliasLock: (() => Promise<void>) | null = null;
if (resourceData.mode === "host" || resourceData.mode === "http") { if (
resourceData.mode === "host" ||
resourceData.mode === "http" ||
resourceData.mode === "ssh"
) {
const { value, release } = await getNextAvailableAliasAddress( const { value, release } = await getNextAvailableAliasAddress(
orgId, orgId,
trx trx

View File

@@ -504,7 +504,7 @@ export function generateRemoteSubnets(
const parseResult = cidrSchema.safeParse(sr.destination); const parseResult = cidrSchema.safeParse(sr.destination);
return parseResult.success; return parseResult.success;
} }
if (sr.mode === "host") { if (sr.mode === "host" || sr.mode === "ssh") {
// check if its a valid IP using zod // check if its a valid IP using zod
const ipSchema = z.union([z.ipv4(), z.ipv6()]); const ipSchema = z.union([z.ipv4(), z.ipv6()]);
const parseResult = ipSchema.safeParse(sr.destination); const parseResult = ipSchema.safeParse(sr.destination);
@@ -514,7 +514,7 @@ export function generateRemoteSubnets(
}) })
.map((sr) => { .map((sr) => {
if (sr.mode === "cidr") return sr.destination; if (sr.mode === "cidr") return sr.destination;
if (sr.mode === "host") { if (sr.mode === "host" || sr.mode === "ssh") {
return `${sr.destination}/32`; return `${sr.destination}/32`;
} }
return ""; // This should never be reached due to filtering, but satisfies TypeScript return ""; // This should never be reached due to filtering, but satisfies TypeScript
@@ -531,7 +531,7 @@ export function generateAliasConfig(allSiteResources: SiteResource[]): Alias[] {
.filter( .filter(
(sr) => (sr) =>
sr.aliasAddress && sr.aliasAddress &&
((sr.alias && sr.mode == "host") || ((sr.alias && (sr.mode == "host" || sr.mode == "ssh")) ||
(sr.fullDomain && sr.mode == "http")) (sr.fullDomain && sr.mode == "http"))
) )
.map((sr) => ({ .map((sr) => ({
@@ -577,6 +577,10 @@ export function generateSubnetProxyTargets(
continue; continue;
} }
if (!siteResource.destination) {
continue;
}
const clientPrefix = `${clientSite.subnet.split("/")[0]}/32`; const clientPrefix = `${clientSite.subnet.split("/")[0]}/32`;
const portRange = [ const portRange = [
...parsePortRangeString(siteResource.tcpPortRangeString, "tcp"), ...parsePortRangeString(siteResource.tcpPortRangeString, "tcp"),
@@ -584,7 +588,7 @@ export function generateSubnetProxyTargets(
]; ];
const disableIcmp = siteResource.disableIcmp ?? false; const disableIcmp = siteResource.disableIcmp ?? false;
if (siteResource.mode == "host") { if (siteResource.mode == "host" || siteResource.mode == "ssh") {
let destination = siteResource.destination; let destination = siteResource.destination;
// check if this is a valid ip // check if this is a valid ip
const ipSchema = z.union([z.ipv4(), z.ipv6()]); const ipSchema = z.union([z.ipv4(), z.ipv6()]);
@@ -665,6 +669,11 @@ export async function generateSubnetProxyTargetV2(
return; return;
} }
if (!siteResource.destination) {
// ssh can have no destination
return;
}
const targets: SubnetProxyTargetV2[] = []; const targets: SubnetProxyTargetV2[] = [];
const portRange = [ const portRange = [
@@ -673,7 +682,7 @@ export async function generateSubnetProxyTargetV2(
]; ];
const disableIcmp = siteResource.disableIcmp ?? false; const disableIcmp = siteResource.disableIcmp ?? false;
if (siteResource.mode == "host") { if (siteResource.mode == "host" || siteResource.mode == "ssh") {
let destination = siteResource.destination; let destination = siteResource.destination;
// check if this is a valid ip // check if this is a valid ip
const ipSchema = z.union([z.ipv4(), z.ipv6()]); const ipSchema = z.union([z.ipv4(), z.ipv6()]);

View File

@@ -181,6 +181,7 @@ class TelemetryClient {
let numPrivResourceHosts = 0; let numPrivResourceHosts = 0;
let numPrivResourceCidr = 0; let numPrivResourceCidr = 0;
let numPrivResourceHttp = 0; let numPrivResourceHttp = 0;
let numPrivResourceSsh = 0;
for (const res of allPrivateResources) { for (const res of allPrivateResources) {
if (res.mode === "host") { if (res.mode === "host") {
numPrivResourceHosts += 1; numPrivResourceHosts += 1;
@@ -188,6 +189,8 @@ class TelemetryClient {
numPrivResourceCidr += 1; numPrivResourceCidr += 1;
} else if (res.mode === "http") { } else if (res.mode === "http") {
numPrivResourceHttp += 1; numPrivResourceHttp += 1;
} else if (res.mode === "ssh") {
numPrivResourceSsh += 1;
} }
if (res.alias) { if (res.alias) {
@@ -207,6 +210,7 @@ class TelemetryClient {
numPrivateResourceHosts: numPrivResourceHosts, numPrivateResourceHosts: numPrivResourceHosts,
numPrivateResourceCidr: numPrivResourceCidr, numPrivateResourceCidr: numPrivResourceCidr,
numPrivateResourceHttp: numPrivResourceHttp, numPrivateResourceHttp: numPrivResourceHttp,
numPrivateResourceSsh: numPrivResourceSsh,
numAlertRules: numAlertRules.count, numAlertRules: numAlertRules.count,
numUserDevices: userDevicesCount.count, numUserDevices: userDevicesCount.count,
numMachineClients: machineClients.count, numMachineClients: machineClients.count,

View File

@@ -1,6 +1,6 @@
import { Request, Response, NextFunction } from "express"; import { Request, Response, NextFunction } from "express";
import { z } from "zod"; import { z } from "zod";
import { db, Org } from "@server/db"; import { db, Org, primaryDb } from "@server/db";
import response from "@server/lib/response"; import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
@@ -635,9 +635,7 @@ export async function validateOidcCallback(
} }
}); });
db.transaction(async (trx) => { calculateUserClientsForOrgs(userId!, primaryDb).catch((err) => {
await calculateUserClientsForOrgs(userId!, trx);
}).catch((err) => {
logger.error( logger.error(
"Error calculating user clients after syncing orgs and roles for OIDC user", "Error calculating user clients after syncing orgs and roles for OIDC user",
{ error: err } { error: err }

View File

@@ -7,7 +7,7 @@ import {
userOrgRoles, userOrgRoles,
userOrgs userOrgs
} from "@server/db"; } from "@server/db";
import { and, eq, inArray, asc, isNotNull, ne } from "drizzle-orm"; import { and, eq, inArray, asc, isNotNull, ne, or } from "drizzle-orm";
import createHttpError from "http-errors"; import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode"; import HttpCode from "@server/types/HttpCode";
import response from "@server/lib/response"; import response from "@server/lib/response";
@@ -224,7 +224,7 @@ export async function listUserResourceAliases(
const whereClause = and( const whereClause = and(
eq(siteResources.orgId, orgId), eq(siteResources.orgId, orgId),
eq(siteResources.enabled, true), eq(siteResources.enabled, true),
eq(siteResources.mode, "host"), or(eq(siteResources.mode, "host"), eq(siteResources.mode, "ssh")),
isNotNull(siteResources.alias), isNotNull(siteResources.alias),
ne(siteResources.alias, ""), ne(siteResources.alias, ""),
inArray(siteResources.siteResourceId, accessibleSiteResourceIds) inArray(siteResources.siteResourceId, accessibleSiteResourceIds)

View File

@@ -445,7 +445,7 @@ export async function createSiteResource(
let aliasAddress: string | null = null; let aliasAddress: string | null = null;
let releaseAliasLock: (() => Promise<void>) | null = null; let releaseAliasLock: (() => Promise<void>) | null = null;
if (mode === "host" || mode === "http") { if (mode === "host" || mode === "http" || mode === "ssh") {
const { value, release } = const { value, release } =
await getNextAvailableAliasAddress(orgId); await getNextAvailableAliasAddress(orgId);
aliasAddress = value; aliasAddress = value;