diff --git a/server/db/pg/schema/privateSchema.ts b/server/db/pg/schema/privateSchema.ts index 0f1914fad..2cf5f154c 100644 --- a/server/db/pg/schema/privateSchema.ts +++ b/server/db/pg/schema/privateSchema.ts @@ -332,6 +332,7 @@ export const connectionAuditLog = pgTable( clientId: integer("clientId").references(() => clients.clientId, { onDelete: "cascade" }), + clientEndpoint: text("clientEndpoint"), userId: text("userId").references(() => users.userId, { onDelete: "cascade" }), diff --git a/server/db/sqlite/schema/privateSchema.ts b/server/db/sqlite/schema/privateSchema.ts index 05c917887..c096c5a94 100644 --- a/server/db/sqlite/schema/privateSchema.ts +++ b/server/db/sqlite/schema/privateSchema.ts @@ -332,6 +332,7 @@ export const connectionAuditLog = sqliteTable( clientId: integer("clientId").references(() => clients.clientId, { onDelete: "cascade" }), + clientEndpoint: text("clientEndpoint"), userId: text("userId").references(() => users.userId, { onDelete: "cascade" }), diff --git a/server/private/lib/logConnectionAudit.ts b/server/private/lib/logConnectionAudit.ts index 039b75ec9..ce4856da0 100644 --- a/server/private/lib/logConnectionAudit.ts +++ b/server/private/lib/logConnectionAudit.ts @@ -46,6 +46,7 @@ export interface ConnectionLogRecord { orgId: string; siteId: number; clientId: number | null; + clientEndpoint: string | null; userId: string | null; sourceAddr: string; destAddr: string; diff --git a/server/private/routers/auditLogs/queryConnectionAuditLog.ts b/server/private/routers/auditLogs/queryConnectionAuditLog.ts index 715652838..930ee6111 100644 --- a/server/private/routers/auditLogs/queryConnectionAuditLog.ts +++ b/server/private/routers/auditLogs/queryConnectionAuditLog.ts @@ -124,15 +124,11 @@ function getWhere(data: Q) { data.clientId ? eq(connectionAuditLog.clientId, data.clientId) : undefined, - data.siteId - ? eq(connectionAuditLog.siteId, data.siteId) - : undefined, + data.siteId ? eq(connectionAuditLog.siteId, data.siteId) : undefined, data.siteResourceId ? eq(connectionAuditLog.siteResourceId, data.siteResourceId) : undefined, - data.userId - ? eq(connectionAuditLog.userId, data.userId) - : undefined + data.userId ? eq(connectionAuditLog.userId, data.userId) : undefined ); } @@ -144,6 +140,7 @@ export function queryConnection(data: Q) { orgId: connectionAuditLog.orgId, siteId: connectionAuditLog.siteId, clientId: connectionAuditLog.clientId, + clientEndpoint: connectionAuditLog.clientEndpoint, userId: connectionAuditLog.userId, sourceAddr: connectionAuditLog.sourceAddr, destAddr: connectionAuditLog.destAddr, @@ -203,10 +200,7 @@ async function enrichWithDetails( ]; // Fetch resource details from main database - const resourceMap = new Map< - number, - { name: string; niceId: string } - >(); + const resourceMap = new Map(); if (siteResourceIds.length > 0) { const resourceDetails = await primaryDb .select({ @@ -268,10 +262,7 @@ async function enrichWithDetails( } // Fetch user details from main database - const userMap = new Map< - string, - { email: string | null } - >(); + const userMap = new Map(); if (userIds.length > 0) { const userDetails = await primaryDb .select({ @@ -290,29 +281,25 @@ async function enrichWithDetails( return logs.map((log) => ({ ...log, resourceName: log.siteResourceId - ? resourceMap.get(log.siteResourceId)?.name ?? null + ? (resourceMap.get(log.siteResourceId)?.name ?? null) : null, resourceNiceId: log.siteResourceId - ? resourceMap.get(log.siteResourceId)?.niceId ?? null - : null, - siteName: log.siteId - ? siteMap.get(log.siteId)?.name ?? null + ? (resourceMap.get(log.siteResourceId)?.niceId ?? null) : null, + siteName: log.siteId ? (siteMap.get(log.siteId)?.name ?? null) : null, siteNiceId: log.siteId - ? siteMap.get(log.siteId)?.niceId ?? null + ? (siteMap.get(log.siteId)?.niceId ?? null) : null, clientName: log.clientId - ? clientMap.get(log.clientId)?.name ?? null + ? (clientMap.get(log.clientId)?.name ?? null) : null, clientNiceId: log.clientId - ? clientMap.get(log.clientId)?.niceId ?? null + ? (clientMap.get(log.clientId)?.niceId ?? null) : null, clientType: log.clientId - ? clientMap.get(log.clientId)?.type ?? null + ? (clientMap.get(log.clientId)?.type ?? null) : null, - userEmail: log.userId - ? userMap.get(log.userId)?.email ?? null - : null + userEmail: log.userId ? (userMap.get(log.userId)?.email ?? null) : null })); } @@ -521,4 +508,4 @@ export async function queryConnectionAuditLogs( createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred") ); } -} \ No newline at end of file +} diff --git a/server/private/routers/newt/handleConnectionLogMessage.ts b/server/private/routers/newt/handleConnectionLogMessage.ts index 6355eb783..cf2ba2daa 100644 --- a/server/private/routers/newt/handleConnectionLogMessage.ts +++ b/server/private/routers/newt/handleConnectionLogMessage.ts @@ -11,7 +11,7 @@ * This file is not licensed under the AGPLv3. */ -import { db } from "@server/db"; +import { clientSitesAssociationsCache, db } from "@server/db"; import { MessageHandler } from "@server/routers/ws"; import { sites, Newt, clients, orgs } from "@server/db"; import { and, eq, inArray } from "drizzle-orm"; @@ -146,7 +146,11 @@ export const handleConnectionLogMessage: MessageHandler = async (context) => { // each unique sourceAddr + the org's CIDR suffix and do a targeted IN query. const ipToClient = new Map< string, - { clientId: number; userId: string | null } + { + clientId: number; + userId: string | null; + clientEndpoint: string | null; + } >(); if (cidrSuffix) { @@ -172,9 +176,21 @@ export const handleConnectionLogMessage: MessageHandler = async (context) => { .select({ clientId: clients.clientId, userId: clients.userId, - subnet: clients.subnet + subnet: clients.subnet, + clientEndpoint: clientSitesAssociationsCache.endpoint }) .from(clients) + .leftJoin( + // this should be one to one + clientSitesAssociationsCache, + and( + eq( + clients.clientId, + clientSitesAssociationsCache.clientId + ), + eq(clientSitesAssociationsCache.siteId, newt.siteId) + ) + ) .where( and( eq(clients.orgId, orgId), @@ -189,7 +205,8 @@ export const handleConnectionLogMessage: MessageHandler = async (context) => { ); ipToClient.set(ip, { clientId: c.clientId, - userId: c.userId + userId: c.userId, + clientEndpoint: c.clientEndpoint }); } } @@ -234,6 +251,7 @@ export const handleConnectionLogMessage: MessageHandler = async (context) => { orgId, siteId: newt.siteId, clientId: clientInfo?.clientId ?? null, + clientEndpoint: clientInfo?.clientEndpoint ?? null, userId: clientInfo?.userId ?? null, sourceAddr: session.sourceAddr, destAddr: session.destAddr, diff --git a/server/routers/auditLogs/types.ts b/server/routers/auditLogs/types.ts index 972eebfe3..b8168ef1e 100644 --- a/server/routers/auditLogs/types.ts +++ b/server/routers/auditLogs/types.ts @@ -100,6 +100,7 @@ export type QueryConnectionAuditLogResponse = { orgId: string | null; siteId: number | null; clientId: number | null; + clientEndpoint: string | null; userId: string | null; sourceAddr: string; destAddr: string; diff --git a/src/app/[orgId]/settings/logs/connection/page.tsx b/src/app/[orgId]/settings/logs/connection/page.tsx index 0fc8f95b7..c2a630332 100644 --- a/src/app/[orgId]/settings/logs/connection/page.tsx +++ b/src/app/[orgId]/settings/logs/connection/page.tsx @@ -645,6 +645,12 @@ export default function ConnectionLogsPage() { )} */} +
+ Client Endpoint:{" "} + + {row.clientEndpoint ?? "-"} + +
Site: {row.siteName ?? "-"} {row.siteNiceId && (