mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-22 08:45:24 +00:00
Add client endpoint to network log
This commit is contained in:
@@ -332,6 +332,7 @@ export const connectionAuditLog = pgTable(
|
|||||||
clientId: integer("clientId").references(() => clients.clientId, {
|
clientId: integer("clientId").references(() => clients.clientId, {
|
||||||
onDelete: "cascade"
|
onDelete: "cascade"
|
||||||
}),
|
}),
|
||||||
|
clientEndpoint: text("clientEndpoint"),
|
||||||
userId: text("userId").references(() => users.userId, {
|
userId: text("userId").references(() => users.userId, {
|
||||||
onDelete: "cascade"
|
onDelete: "cascade"
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -332,6 +332,7 @@ export const connectionAuditLog = sqliteTable(
|
|||||||
clientId: integer("clientId").references(() => clients.clientId, {
|
clientId: integer("clientId").references(() => clients.clientId, {
|
||||||
onDelete: "cascade"
|
onDelete: "cascade"
|
||||||
}),
|
}),
|
||||||
|
clientEndpoint: text("clientEndpoint"),
|
||||||
userId: text("userId").references(() => users.userId, {
|
userId: text("userId").references(() => users.userId, {
|
||||||
onDelete: "cascade"
|
onDelete: "cascade"
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export interface ConnectionLogRecord {
|
|||||||
orgId: string;
|
orgId: string;
|
||||||
siteId: number;
|
siteId: number;
|
||||||
clientId: number | null;
|
clientId: number | null;
|
||||||
|
clientEndpoint: string | null;
|
||||||
userId: string | null;
|
userId: string | null;
|
||||||
sourceAddr: string;
|
sourceAddr: string;
|
||||||
destAddr: string;
|
destAddr: string;
|
||||||
|
|||||||
@@ -124,15 +124,11 @@ function getWhere(data: Q) {
|
|||||||
data.clientId
|
data.clientId
|
||||||
? eq(connectionAuditLog.clientId, data.clientId)
|
? eq(connectionAuditLog.clientId, data.clientId)
|
||||||
: undefined,
|
: undefined,
|
||||||
data.siteId
|
data.siteId ? eq(connectionAuditLog.siteId, data.siteId) : undefined,
|
||||||
? eq(connectionAuditLog.siteId, data.siteId)
|
|
||||||
: undefined,
|
|
||||||
data.siteResourceId
|
data.siteResourceId
|
||||||
? eq(connectionAuditLog.siteResourceId, data.siteResourceId)
|
? eq(connectionAuditLog.siteResourceId, data.siteResourceId)
|
||||||
: undefined,
|
: undefined,
|
||||||
data.userId
|
data.userId ? eq(connectionAuditLog.userId, data.userId) : undefined
|
||||||
? eq(connectionAuditLog.userId, data.userId)
|
|
||||||
: undefined
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +140,7 @@ export function queryConnection(data: Q) {
|
|||||||
orgId: connectionAuditLog.orgId,
|
orgId: connectionAuditLog.orgId,
|
||||||
siteId: connectionAuditLog.siteId,
|
siteId: connectionAuditLog.siteId,
|
||||||
clientId: connectionAuditLog.clientId,
|
clientId: connectionAuditLog.clientId,
|
||||||
|
clientEndpoint: connectionAuditLog.clientEndpoint,
|
||||||
userId: connectionAuditLog.userId,
|
userId: connectionAuditLog.userId,
|
||||||
sourceAddr: connectionAuditLog.sourceAddr,
|
sourceAddr: connectionAuditLog.sourceAddr,
|
||||||
destAddr: connectionAuditLog.destAddr,
|
destAddr: connectionAuditLog.destAddr,
|
||||||
@@ -203,10 +200,7 @@ async function enrichWithDetails(
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Fetch resource details from main database
|
// Fetch resource details from main database
|
||||||
const resourceMap = new Map<
|
const resourceMap = new Map<number, { name: string; niceId: string }>();
|
||||||
number,
|
|
||||||
{ name: string; niceId: string }
|
|
||||||
>();
|
|
||||||
if (siteResourceIds.length > 0) {
|
if (siteResourceIds.length > 0) {
|
||||||
const resourceDetails = await primaryDb
|
const resourceDetails = await primaryDb
|
||||||
.select({
|
.select({
|
||||||
@@ -268,10 +262,7 @@ async function enrichWithDetails(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fetch user details from main database
|
// Fetch user details from main database
|
||||||
const userMap = new Map<
|
const userMap = new Map<string, { email: string | null }>();
|
||||||
string,
|
|
||||||
{ email: string | null }
|
|
||||||
>();
|
|
||||||
if (userIds.length > 0) {
|
if (userIds.length > 0) {
|
||||||
const userDetails = await primaryDb
|
const userDetails = await primaryDb
|
||||||
.select({
|
.select({
|
||||||
@@ -290,29 +281,25 @@ async function enrichWithDetails(
|
|||||||
return logs.map((log) => ({
|
return logs.map((log) => ({
|
||||||
...log,
|
...log,
|
||||||
resourceName: log.siteResourceId
|
resourceName: log.siteResourceId
|
||||||
? resourceMap.get(log.siteResourceId)?.name ?? null
|
? (resourceMap.get(log.siteResourceId)?.name ?? null)
|
||||||
: null,
|
: null,
|
||||||
resourceNiceId: log.siteResourceId
|
resourceNiceId: log.siteResourceId
|
||||||
? resourceMap.get(log.siteResourceId)?.niceId ?? null
|
? (resourceMap.get(log.siteResourceId)?.niceId ?? null)
|
||||||
: null,
|
|
||||||
siteName: log.siteId
|
|
||||||
? siteMap.get(log.siteId)?.name ?? null
|
|
||||||
: null,
|
: null,
|
||||||
|
siteName: log.siteId ? (siteMap.get(log.siteId)?.name ?? null) : null,
|
||||||
siteNiceId: log.siteId
|
siteNiceId: log.siteId
|
||||||
? siteMap.get(log.siteId)?.niceId ?? null
|
? (siteMap.get(log.siteId)?.niceId ?? null)
|
||||||
: null,
|
: null,
|
||||||
clientName: log.clientId
|
clientName: log.clientId
|
||||||
? clientMap.get(log.clientId)?.name ?? null
|
? (clientMap.get(log.clientId)?.name ?? null)
|
||||||
: null,
|
: null,
|
||||||
clientNiceId: log.clientId
|
clientNiceId: log.clientId
|
||||||
? clientMap.get(log.clientId)?.niceId ?? null
|
? (clientMap.get(log.clientId)?.niceId ?? null)
|
||||||
: null,
|
: null,
|
||||||
clientType: log.clientId
|
clientType: log.clientId
|
||||||
? clientMap.get(log.clientId)?.type ?? null
|
? (clientMap.get(log.clientId)?.type ?? null)
|
||||||
: null,
|
: null,
|
||||||
userEmail: log.userId
|
userEmail: log.userId ? (userMap.get(log.userId)?.email ?? null) : null
|
||||||
? userMap.get(log.userId)?.email ?? null
|
|
||||||
: null
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,4 +508,4 @@ export async function queryConnectionAuditLogs(
|
|||||||
createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred")
|
createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
* This file is not licensed under the AGPLv3.
|
* 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 { MessageHandler } from "@server/routers/ws";
|
||||||
import { sites, Newt, clients, orgs } from "@server/db";
|
import { sites, Newt, clients, orgs } from "@server/db";
|
||||||
import { and, eq, inArray } from "drizzle-orm";
|
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.
|
// each unique sourceAddr + the org's CIDR suffix and do a targeted IN query.
|
||||||
const ipToClient = new Map<
|
const ipToClient = new Map<
|
||||||
string,
|
string,
|
||||||
{ clientId: number; userId: string | null }
|
{
|
||||||
|
clientId: number;
|
||||||
|
userId: string | null;
|
||||||
|
clientEndpoint: string | null;
|
||||||
|
}
|
||||||
>();
|
>();
|
||||||
|
|
||||||
if (cidrSuffix) {
|
if (cidrSuffix) {
|
||||||
@@ -172,9 +176,21 @@ export const handleConnectionLogMessage: MessageHandler = async (context) => {
|
|||||||
.select({
|
.select({
|
||||||
clientId: clients.clientId,
|
clientId: clients.clientId,
|
||||||
userId: clients.userId,
|
userId: clients.userId,
|
||||||
subnet: clients.subnet
|
subnet: clients.subnet,
|
||||||
|
clientEndpoint: clientSitesAssociationsCache.endpoint
|
||||||
})
|
})
|
||||||
.from(clients)
|
.from(clients)
|
||||||
|
.leftJoin(
|
||||||
|
// this should be one to one
|
||||||
|
clientSitesAssociationsCache,
|
||||||
|
and(
|
||||||
|
eq(
|
||||||
|
clients.clientId,
|
||||||
|
clientSitesAssociationsCache.clientId
|
||||||
|
),
|
||||||
|
eq(clientSitesAssociationsCache.siteId, newt.siteId)
|
||||||
|
)
|
||||||
|
)
|
||||||
.where(
|
.where(
|
||||||
and(
|
and(
|
||||||
eq(clients.orgId, orgId),
|
eq(clients.orgId, orgId),
|
||||||
@@ -189,7 +205,8 @@ export const handleConnectionLogMessage: MessageHandler = async (context) => {
|
|||||||
);
|
);
|
||||||
ipToClient.set(ip, {
|
ipToClient.set(ip, {
|
||||||
clientId: c.clientId,
|
clientId: c.clientId,
|
||||||
userId: c.userId
|
userId: c.userId,
|
||||||
|
clientEndpoint: c.clientEndpoint
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,6 +251,7 @@ export const handleConnectionLogMessage: MessageHandler = async (context) => {
|
|||||||
orgId,
|
orgId,
|
||||||
siteId: newt.siteId,
|
siteId: newt.siteId,
|
||||||
clientId: clientInfo?.clientId ?? null,
|
clientId: clientInfo?.clientId ?? null,
|
||||||
|
clientEndpoint: clientInfo?.clientEndpoint ?? null,
|
||||||
userId: clientInfo?.userId ?? null,
|
userId: clientInfo?.userId ?? null,
|
||||||
sourceAddr: session.sourceAddr,
|
sourceAddr: session.sourceAddr,
|
||||||
destAddr: session.destAddr,
|
destAddr: session.destAddr,
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ export type QueryConnectionAuditLogResponse = {
|
|||||||
orgId: string | null;
|
orgId: string | null;
|
||||||
siteId: number | null;
|
siteId: number | null;
|
||||||
clientId: number | null;
|
clientId: number | null;
|
||||||
|
clientEndpoint: string | null;
|
||||||
userId: string | null;
|
userId: string | null;
|
||||||
sourceAddr: string;
|
sourceAddr: string;
|
||||||
destAddr: string;
|
destAddr: string;
|
||||||
|
|||||||
@@ -645,6 +645,12 @@ export default function ConnectionLogsPage() {
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>*/}
|
</div>*/}
|
||||||
|
<div>
|
||||||
|
<strong>Client Endpoint:</strong>{" "}
|
||||||
|
<span className="font-mono">
|
||||||
|
{row.clientEndpoint ?? "-"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<strong>Site:</strong> {row.siteName ?? "-"}
|
<strong>Site:</strong> {row.siteName ?? "-"}
|
||||||
{row.siteNiceId && (
|
{row.siteNiceId && (
|
||||||
|
|||||||
Reference in New Issue
Block a user