Build interactive access topology map
All checks were successful
OfficeCom Sentinel Client / validate-client (push) Successful in 23s
OfficeCom Sentinel Client / build-client-windows (push) Successful in 48s

This commit is contained in:
OfficeCom Codex
2026-07-30 01:37:50 +02:00
parent c65001aa17
commit 0207d84775
5 changed files with 121 additions and 8 deletions

View File

@@ -5,7 +5,7 @@ import os
from datetime import datetime, timezone
import psycopg
from flask import Flask, abort, redirect, render_template, request, url_for
from flask import Flask, abort, jsonify, redirect, render_template, request, url_for
app = Flask(__name__)
@@ -245,8 +245,7 @@ def organization(organization_id):
)
@app.get("/network")
def network():
def load_network_flows():
with db_connection() as connection, connection.cursor() as cursor:
cursor.execute(
"""
@@ -286,13 +285,52 @@ def network():
max_count = max([entry["count"] for entry in flow_rows] or [1])
source_count = len({entry["source_ip"] for entry in flow_rows})
target_count = len({entry["machine_name"] for entry in flow_rows})
return flow_rows, max_count, source_count, target_count
@app.get("/network")
def network():
flows, _, source_count, target_count = load_network_flows()
return render_template(
"network.html",
flows=flow_rows,
max_count=max_count,
source_count=source_count,
target_count=target_count,
total_events=sum(entry["count"] for entry in flow_rows),
total_events=sum(entry["count"] for entry in flows),
path_count=len(flows),
)
@app.get("/api/network")
def network_api():
flows, max_count, source_count, target_count = load_network_flows()
nodes = {}
edges = []
for index, flow in enumerate(flows):
source_id = f"source:{flow['source_ip']}"
target_id = f"target:{flow['machine_name']}"
nodes[source_id] = {"data": {"id": source_id, "label": flow["source_ip"], "kind": "source"}}
nodes[target_id] = {"data": {"id": target_id, "label": flow["machine_name"], "kind": "target"}}
edges.append(
{
"data": {
"id": f"flow:{index}",
"source": source_id,
"target": target_id,
"count": flow["count"],
"account": flow["account"],
"event_type": flow["target"],
"last_seen": str(flow["last_seen"] or "-"),
"machine_name": flow["machine_name"],
}
}
)
return jsonify(
{
"elements": {"nodes": list(nodes.values()), "edges": edges},
"max_count": max_count,
"source_count": source_count,
"target_count": target_count,
}
)