mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-23 02:56:37 +00:00
WIP - more conversion
This commit is contained in:
@@ -4,10 +4,12 @@ import {
|
|||||||
db,
|
db,
|
||||||
exitNodes,
|
exitNodes,
|
||||||
Site,
|
Site,
|
||||||
siteResources
|
siteNetworks,
|
||||||
|
siteResources,
|
||||||
|
sites
|
||||||
} from "@server/db";
|
} from "@server/db";
|
||||||
import { MessageHandler } from "@server/routers/ws";
|
import { MessageHandler } from "@server/routers/ws";
|
||||||
import { clients, Olm, sites } from "@server/db";
|
import { clients, Olm } from "@server/db";
|
||||||
import { and, eq, or } from "drizzle-orm";
|
import { and, eq, or } from "drizzle-orm";
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
import { initPeerAddHandshake } from "./peers";
|
import { initPeerAddHandshake } from "./peers";
|
||||||
@@ -44,20 +46,31 @@ export const handleOlmServerInitAddPeerHandshake: MessageHandler = async (
|
|||||||
|
|
||||||
const { siteId, resourceId, chainId } = message.data;
|
const { siteId, resourceId, chainId } = message.data;
|
||||||
|
|
||||||
let site: Site | null = null;
|
const sendCancel = async () => {
|
||||||
|
await sendToClient(
|
||||||
|
olm.olmId,
|
||||||
|
{
|
||||||
|
type: "olm/wg/peer/chain/cancel",
|
||||||
|
data: { chainId }
|
||||||
|
},
|
||||||
|
{ incrementConfigVersion: false }
|
||||||
|
).catch((error) => {
|
||||||
|
logger.warn(`Error sending message:`, error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let sitesToProcess: Site[] = [];
|
||||||
|
|
||||||
if (siteId) {
|
if (siteId) {
|
||||||
// get the site
|
|
||||||
const [siteRes] = await db
|
const [siteRes] = await db
|
||||||
.select()
|
.select()
|
||||||
.from(sites)
|
.from(sites)
|
||||||
.where(eq(sites.siteId, siteId))
|
.where(eq(sites.siteId, siteId))
|
||||||
.limit(1);
|
.limit(1);
|
||||||
if (siteRes) {
|
if (siteRes) {
|
||||||
site = siteRes;
|
sitesToProcess = [siteRes];
|
||||||
}
|
}
|
||||||
}
|
} else if (resourceId) {
|
||||||
|
|
||||||
if (resourceId && !site) {
|
|
||||||
const resources = await db
|
const resources = await db
|
||||||
.select()
|
.select()
|
||||||
.from(siteResources)
|
.from(siteResources)
|
||||||
@@ -72,27 +85,17 @@ export const handleOlmServerInitAddPeerHandshake: MessageHandler = async (
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!resources || resources.length === 0) {
|
if (!resources || resources.length === 0) {
|
||||||
logger.error(`handleOlmServerPeerAddMessage: Resource not found`);
|
logger.error(
|
||||||
// cancel the request from the olm side to not keep doing this
|
`handleOlmServerInitAddPeerHandshake: Resource not found`
|
||||||
await sendToClient(
|
);
|
||||||
olm.olmId,
|
await sendCancel();
|
||||||
{
|
|
||||||
type: "olm/wg/peer/chain/cancel",
|
|
||||||
data: {
|
|
||||||
chainId
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ incrementConfigVersion: false }
|
|
||||||
).catch((error) => {
|
|
||||||
logger.warn(`Error sending message:`, error);
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resources.length > 1) {
|
if (resources.length > 1) {
|
||||||
// error but this should not happen because the nice id cant contain a dot and the alias has to have a dot and both have to be unique within the org so there should never be multiple matches
|
// error but this should not happen because the nice id cant contain a dot and the alias has to have a dot and both have to be unique within the org so there should never be multiple matches
|
||||||
logger.error(
|
logger.error(
|
||||||
`handleOlmServerPeerAddMessage: Multiple resources found matching the criteria`
|
`handleOlmServerInitAddPeerHandshake: Multiple resources found matching the criteria`
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -117,125 +120,120 @@ export const handleOlmServerInitAddPeerHandshake: MessageHandler = async (
|
|||||||
|
|
||||||
if (currentResourceAssociationCaches.length === 0) {
|
if (currentResourceAssociationCaches.length === 0) {
|
||||||
logger.error(
|
logger.error(
|
||||||
`handleOlmServerPeerAddMessage: Client ${client.clientId} does not have access to resource ${resource.siteResourceId}`
|
`handleOlmServerInitAddPeerHandshake: Client ${client.clientId} does not have access to resource ${resource.siteResourceId}`
|
||||||
);
|
);
|
||||||
// cancel the request from the olm side to not keep doing this
|
await sendCancel();
|
||||||
await sendToClient(
|
|
||||||
olm.olmId,
|
|
||||||
{
|
|
||||||
type: "olm/wg/peer/chain/cancel",
|
|
||||||
data: {
|
|
||||||
chainId
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ incrementConfigVersion: false }
|
|
||||||
).catch((error) => {
|
|
||||||
logger.warn(`Error sending message:`, error);
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const siteIdFromResource = resource.siteId;
|
if (!resource.networkId) {
|
||||||
|
|
||||||
// get the site
|
|
||||||
const [siteRes] = await db
|
|
||||||
.select()
|
|
||||||
.from(sites)
|
|
||||||
.where(eq(sites.siteId, siteIdFromResource));
|
|
||||||
if (!siteRes) {
|
|
||||||
logger.error(
|
logger.error(
|
||||||
`handleOlmServerPeerAddMessage: Site with ID ${site} not found`
|
`handleOlmServerInitAddPeerHandshake: Resource ${resource.siteResourceId} has no network`
|
||||||
);
|
);
|
||||||
|
await sendCancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
site = siteRes;
|
// Get all sites associated with this resource's network via siteNetworks
|
||||||
|
const siteRows = await db
|
||||||
|
.select({ siteId: siteNetworks.siteId })
|
||||||
|
.from(siteNetworks)
|
||||||
|
.where(eq(siteNetworks.networkId, resource.networkId));
|
||||||
|
|
||||||
|
if (!siteRows || siteRows.length === 0) {
|
||||||
|
logger.error(
|
||||||
|
`handleOlmServerInitAddPeerHandshake: No sites found for resource ${resource.siteResourceId}`
|
||||||
|
);
|
||||||
|
await sendCancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch full site objects for all network members
|
||||||
|
const foundSites = await Promise.all(
|
||||||
|
siteRows.map(async ({ siteId: sid }) => {
|
||||||
|
const [s] = await db
|
||||||
|
.select()
|
||||||
|
.from(sites)
|
||||||
|
.where(eq(sites.siteId, sid))
|
||||||
|
.limit(1);
|
||||||
|
return s ?? null;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
sitesToProcess = foundSites.filter((s): s is Site => s !== null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!site) {
|
if (sitesToProcess.length === 0) {
|
||||||
logger.error(`handleOlmServerPeerAddMessage: Site not found`);
|
logger.error(
|
||||||
|
`handleOlmServerInitAddPeerHandshake: No sites to process`
|
||||||
|
);
|
||||||
|
await sendCancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the client can access this site using the cache
|
let handshakeInitiated = false;
|
||||||
const currentSiteAssociationCaches = await db
|
|
||||||
.select()
|
|
||||||
.from(clientSitesAssociationsCache)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(clientSitesAssociationsCache.clientId, client.clientId),
|
|
||||||
eq(clientSitesAssociationsCache.siteId, site.siteId)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (currentSiteAssociationCaches.length === 0) {
|
for (const site of sitesToProcess) {
|
||||||
logger.error(
|
// Check if the client can access this site using the cache
|
||||||
`handleOlmServerPeerAddMessage: Client ${client.clientId} does not have access to site ${site.siteId}`
|
const currentSiteAssociationCaches = await db
|
||||||
);
|
.select()
|
||||||
// cancel the request from the olm side to not keep doing this
|
.from(clientSitesAssociationsCache)
|
||||||
await sendToClient(
|
.where(
|
||||||
olm.olmId,
|
and(
|
||||||
|
eq(clientSitesAssociationsCache.clientId, client.clientId),
|
||||||
|
eq(clientSitesAssociationsCache.siteId, site.siteId)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (currentSiteAssociationCaches.length === 0) {
|
||||||
|
logger.warn(
|
||||||
|
`handleOlmServerInitAddPeerHandshake: Client ${client.clientId} does not have access to site ${site.siteId}, skipping`
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!site.exitNodeId) {
|
||||||
|
logger.error(
|
||||||
|
`handleOlmServerInitAddPeerHandshake: Site ${site.siteId} has no exit node, skipping`
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [exitNode] = await db
|
||||||
|
.select()
|
||||||
|
.from(exitNodes)
|
||||||
|
.where(eq(exitNodes.exitNodeId, site.exitNodeId));
|
||||||
|
|
||||||
|
if (!exitNode) {
|
||||||
|
logger.error(
|
||||||
|
`handleOlmServerInitAddPeerHandshake: Exit node not found for site ${site.siteId}, skipping`
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger the peer add handshake — if the peer was already added this will be a no-op
|
||||||
|
await initPeerAddHandshake(
|
||||||
|
client.clientId,
|
||||||
{
|
{
|
||||||
type: "olm/wg/peer/chain/cancel",
|
siteId: site.siteId,
|
||||||
data: {
|
exitNode: {
|
||||||
chainId
|
publicKey: exitNode.publicKey,
|
||||||
|
endpoint: exitNode.endpoint
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ incrementConfigVersion: false }
|
|
||||||
).catch((error) => {
|
|
||||||
logger.warn(`Error sending message:`, error);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!site.exitNodeId) {
|
|
||||||
logger.error(
|
|
||||||
`handleOlmServerPeerAddMessage: Site with ID ${site.siteId} has no exit node`
|
|
||||||
);
|
|
||||||
// cancel the request from the olm side to not keep doing this
|
|
||||||
await sendToClient(
|
|
||||||
olm.olmId,
|
olm.olmId,
|
||||||
{
|
chainId
|
||||||
type: "olm/wg/peer/chain/cancel",
|
|
||||||
data: {
|
|
||||||
chainId
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ incrementConfigVersion: false }
|
|
||||||
).catch((error) => {
|
|
||||||
logger.warn(`Error sending message:`, error);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the exit node from the side
|
|
||||||
const [exitNode] = await db
|
|
||||||
.select()
|
|
||||||
.from(exitNodes)
|
|
||||||
.where(eq(exitNodes.exitNodeId, site.exitNodeId));
|
|
||||||
|
|
||||||
if (!exitNode) {
|
|
||||||
logger.error(
|
|
||||||
`handleOlmServerPeerAddMessage: Site with ID ${site.siteId} has no exit node`
|
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
|
handshakeInitiated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// also trigger the peer add handshake in case the peer was not already added to the olm and we need to hole punch
|
if (!handshakeInitiated) {
|
||||||
// if it has already been added this will be a no-op
|
logger.error(
|
||||||
await initPeerAddHandshake(
|
`handleOlmServerInitAddPeerHandshake: No accessible sites with valid exit nodes found, cancelling chain`
|
||||||
// this will kick off the add peer process for the client
|
);
|
||||||
client.clientId,
|
await sendCancel();
|
||||||
{
|
}
|
||||||
siteId: site.siteId,
|
|
||||||
exitNode: {
|
|
||||||
publicKey: exitNode.publicKey,
|
|
||||||
endpoint: exitNode.endpoint
|
|
||||||
}
|
|
||||||
},
|
|
||||||
olm.olmId,
|
|
||||||
chainId
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -1,43 +1,25 @@
|
|||||||
import {
|
import {
|
||||||
Client,
|
|
||||||
clientSiteResourcesAssociationsCache,
|
clientSiteResourcesAssociationsCache,
|
||||||
db,
|
db,
|
||||||
ExitNode,
|
networks,
|
||||||
Org,
|
siteNetworks,
|
||||||
orgs,
|
|
||||||
roleClients,
|
|
||||||
roles,
|
|
||||||
siteResources,
|
siteResources,
|
||||||
Transaction,
|
|
||||||
userClients,
|
|
||||||
userOrgs,
|
|
||||||
users
|
|
||||||
} from "@server/db";
|
} from "@server/db";
|
||||||
import { MessageHandler } from "@server/routers/ws";
|
import { MessageHandler } from "@server/routers/ws";
|
||||||
import {
|
import {
|
||||||
clients,
|
clients,
|
||||||
clientSitesAssociationsCache,
|
clientSitesAssociationsCache,
|
||||||
exitNodes,
|
|
||||||
Olm,
|
Olm,
|
||||||
olms,
|
|
||||||
sites
|
sites
|
||||||
} from "@server/db";
|
} from "@server/db";
|
||||||
import { and, eq, inArray, isNotNull, isNull } from "drizzle-orm";
|
import { and, eq, inArray, isNotNull, isNull } from "drizzle-orm";
|
||||||
import { addPeer, deletePeer } from "../newt/peers";
|
|
||||||
import logger from "@server/logger";
|
import logger from "@server/logger";
|
||||||
import { listExitNodes } from "#dynamic/lib/exitNodes";
|
|
||||||
import {
|
import {
|
||||||
generateAliasConfig,
|
generateAliasConfig,
|
||||||
getNextAvailableClientSubnet
|
|
||||||
} from "@server/lib/ip";
|
} from "@server/lib/ip";
|
||||||
import { generateRemoteSubnets } from "@server/lib/ip";
|
import { generateRemoteSubnets } from "@server/lib/ip";
|
||||||
import { rebuildClientAssociationsFromClient } from "@server/lib/rebuildClientAssociations";
|
|
||||||
import { checkOrgAccessPolicy } from "#dynamic/lib/checkOrgAccessPolicy";
|
|
||||||
import { validateSessionToken } from "@server/auth/sessions/app";
|
|
||||||
import config from "@server/lib/config";
|
|
||||||
import {
|
import {
|
||||||
addPeer as newtAddPeer,
|
addPeer as newtAddPeer,
|
||||||
deletePeer as newtDeletePeer
|
|
||||||
} from "@server/routers/newt/peers";
|
} from "@server/routers/newt/peers";
|
||||||
|
|
||||||
export const handleOlmServerPeerAddMessage: MessageHandler = async (
|
export const handleOlmServerPeerAddMessage: MessageHandler = async (
|
||||||
@@ -153,13 +135,21 @@ export const handleOlmServerPeerAddMessage: MessageHandler = async (
|
|||||||
clientSiteResourcesAssociationsCache.siteResourceId
|
clientSiteResourcesAssociationsCache.siteResourceId
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.where(
|
.innerJoin(
|
||||||
|
networks,
|
||||||
|
eq(siteResources.networkId, networks.networkId)
|
||||||
|
)
|
||||||
|
.innerJoin(
|
||||||
|
siteNetworks,
|
||||||
and(
|
and(
|
||||||
eq(siteResources.siteId, site.siteId),
|
eq(networks.networkId, siteNetworks.networkId),
|
||||||
eq(
|
eq(siteNetworks.siteId, site.siteId)
|
||||||
clientSiteResourcesAssociationsCache.clientId,
|
)
|
||||||
client.clientId
|
)
|
||||||
)
|
.where(
|
||||||
|
eq(
|
||||||
|
clientSiteResourcesAssociationsCache.clientId,
|
||||||
|
client.clientId
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user