Update the remote subnets

This commit is contained in:
Owen
2025-11-20 15:17:48 -05:00
parent 3750c36aa7
commit 9420b41e39
4 changed files with 113 additions and 11 deletions

View File

@@ -3,7 +3,6 @@ import { clients, orgs, sites } from "@server/db";
import { and, eq, isNotNull } from "drizzle-orm";
import config from "@server/lib/config";
import z from "zod";
import { getClientSiteResourceAccess } from "./rebuildClientAssociations";
import logger from "@server/logger";
interface IPRange {

View File

@@ -36,6 +36,7 @@ import {
SubnetProxyTarget
} from "@server/lib/ip";
import {
addRemoteSubnets,
addTargets as addSubnetProxyTargets,
removeTargets as removeSubnetProxyTargets
} from "@server/routers/client/targets";
@@ -644,6 +645,8 @@ async function handleSubnetProxyTargetUpdates(
return;
}
let proxyJobs = [];
let olmJobs = [];
// Generate targets for added associations
if (clientSiteResourcesToAdd.length > 0) {
const addedClients = allClients.filter((client) =>
@@ -660,11 +663,21 @@ async function handleSubnetProxyTargetUpdates(
logger.info(
`Adding ${targetsToAdd.length} subnet proxy targets for siteResource ${siteResource.siteResourceId}`
);
await addSubnetProxyTargets(newt.newtId, targetsToAdd);
proxyJobs.push(
addSubnetProxyTargets(newt.newtId, targetsToAdd)
);
}
for (const client of addedClients) {
olmJobs.push(
addRemoteSubnets(client.clientId, siteResource.siteId, generateRemoteSubnets([siteResource]))
);
}
}
}
// here we use the existingSiteResource from BEFORE we updated the destination so we dont need to worry about updating destinations here
// Generate targets for removed associations
if (clientSiteResourcesToRemove.length > 0) {
const removedClients = existingClients.filter((client) =>
@@ -681,8 +694,18 @@ async function handleSubnetProxyTargetUpdates(
logger.info(
`Removing ${targetsToRemove.length} subnet proxy targets for siteResource ${siteResource.siteResourceId}`
);
await removeSubnetProxyTargets(newt.newtId, targetsToRemove);
proxyJobs.push(
removeSubnetProxyTargets(newt.newtId, targetsToRemove)
);
}
for (const client of removedClients) {
olmJobs.push(
addRemoteSubnets(client.clientId, siteResource.siteId, generateRemoteSubnets([siteResource]))
);
}
}
}
await Promise.all(proxyJobs);
}

View File

@@ -1,5 +1,7 @@
import { sendToClient } from "#dynamic/routers/ws";
import { db, olms } from "@server/db";
import { SubnetProxyTarget } from "@server/lib/ip";
import { eq } from "drizzle-orm";
export async function addTargets(newtId: string, targets: SubnetProxyTarget[]) {
await sendToClient(newtId, {
@@ -21,8 +23,8 @@ export async function removeTargets(
export async function updateTargets(
newtId: string,
targets: {
oldTargets: SubnetProxyTarget[],
newTargets: SubnetProxyTarget[]
oldTargets: SubnetProxyTarget[];
newTargets: SubnetProxyTarget[];
}
) {
await sendToClient(newtId, {
@@ -30,3 +32,57 @@ export async function updateTargets(
data: targets
});
}
export async function addRemoteSubnets(
clientId: number,
siteId: number,
remoteSubnets: string[],
olmId?: string
) {
if (!olmId) {
const [olm] = await db
.select()
.from(olms)
.where(eq(olms.clientId, clientId))
.limit(1);
if (!olm) {
throw new Error(`Olm with ID ${clientId} not found`);
}
olmId = olm.olmId;
}
await sendToClient(olmId, {
type: `olm/wg/peer/add-remote-subnets`,
data: {
siteId: siteId,
remoteSubnets: remoteSubnets
}
});
}
export async function removeRemoteSubnets(
clientId: number,
siteId: number,
remoteSubnets: string[],
olmId?: string
) {
if (!olmId) {
const [olm] = await db
.select()
.from(olms)
.where(eq(olms.clientId, clientId))
.limit(1);
if (!olm) {
throw new Error(`Olm with ID ${clientId} not found`);
}
olmId = olm.olmId;
}
await sendToClient(olmId, {
type: `olm/wg/peer/remove-remote-subnets`,
data: {
siteId: siteId,
remoteSubnets: remoteSubnets
}
});
}

View File

@@ -17,8 +17,12 @@ import { eq, and, ne } from "drizzle-orm";
import { fromError } from "zod-validation-error";
import logger from "@server/logger";
import { OpenAPITags, registry } from "@server/openApi";
import { updateTargets } from "@server/routers/client/targets";
import { generateSubnetProxyTargets } from "@server/lib/ip";
import {
addRemoteSubnets,
removeRemoteSubnets,
updateTargets
} from "@server/routers/client/targets";
import { generateRemoteSubnets, generateSubnetProxyTargets } from "@server/lib/ip";
import {
getClientSiteResourceAccess,
rebuildClientAssociations
@@ -221,11 +225,11 @@ export async function updateSiteResource(
}
const { mergedAllClients } = await rebuildClientAssociations(
updatedSiteResource,
existingSiteResource, // we want to rebuild based on the existing resource then we will apply the change to the destination below
trx
); // we need to call this because we added to the admin role
);
// after everything is rebuilt above we still need to update the targets if the destination changed
// after everything is rebuilt above we still need to update the targets and remote subnets if the destination changed
if (
existingSiteResource.destination !==
updatedSiteResource.destination
@@ -255,6 +259,26 @@ export async function updateSiteResource(
oldTargets: oldTargets,
newTargets: newTargets
});
let olmJobs: Promise<void>[] = [];
for (const client of mergedAllClients) { // we also need to update the remote subnets on the olms for each client that has access to this site
olmJobs.push(
removeRemoteSubnets(
client.clientId,
updatedSiteResource.siteId,
generateRemoteSubnets([existingSiteResource])
)
);
olmJobs.push(
addRemoteSubnets(
client.clientId,
updatedSiteResource.siteId,
generateRemoteSubnets([updatedSiteResource])
)
);
}
await Promise.all(olmJobs);
}
logger.info(