diff --git a/app/routers/audit_full.py b/app/routers/audit_full.py index df8e657..afbfc27 100644 --- a/app/routers/audit_full.py +++ b/app/routers/audit_full.py @@ -157,12 +157,86 @@ async def audit_full_flow_map(request: Request, db=Depends(get_db)): if not user: return RedirectResponse(url="/login") - flows = get_flow_map(db) + domain_filter = request.query_params.get("domain", "") + server_filter = request.query_params.get("server", "").strip() + + # Domaines + zones pour le dropdown + all_domains = db.execute(text( + "SELECT code, name, 'domain' as type FROM domains ORDER BY name" + )).fetchall() + all_zones = db.execute(text( + "SELECT name as code, name, 'zone' as type FROM zones ORDER BY name" + )).fetchall() + + # Serveurs audites pour l'autocompletion + audited_servers = db.execute(text(""" + SELECT DISTINCT hostname FROM server_audit_full WHERE status = 'ok' ORDER BY hostname + """)).fetchall() + + if server_filter: + # Flux pour un serveur specifique (IN + OUT) + flows = db.execute(text(""" + SELECT source_hostname, source_ip, dest_ip, dest_port, + dest_hostname, process_name, direction, state, + COUNT(*) as cnt + FROM network_flow_map nfm + JOIN server_audit_full saf ON nfm.audit_id = saf.id + WHERE saf.id IN ( + SELECT DISTINCT ON (hostname) id FROM server_audit_full + WHERE status = 'ok' ORDER BY hostname, audit_date DESC + ) + AND (nfm.source_hostname = :srv OR nfm.dest_hostname = :srv) + AND nfm.source_hostname != nfm.dest_hostname + AND nfm.dest_hostname IS NOT NULL + GROUP BY source_hostname, source_ip, dest_ip, dest_port, + dest_hostname, process_name, direction, state + ORDER BY source_hostname + """), {"srv": server_filter}).fetchall() + elif domain_filter: + # Flux pour un domaine ou une zone + # D'abord chercher comme zone + hostnames = [r.hostname for r in db.execute(text(""" + SELECT s.hostname FROM servers s + JOIN zones z ON s.zone_id = z.id WHERE z.name = :name + """), {"name": domain_filter}).fetchall()] + if not hostnames: + # Sinon comme domaine + hostnames = [r.hostname for r in db.execute(text(""" + SELECT s.hostname FROM servers s + JOIN domain_environments de ON s.domain_env_id = de.id + JOIN domains d ON de.domain_id = d.id WHERE d.code = :dc + """), {"dc": domain_filter}).fetchall()] + if hostnames: + flows = db.execute(text(""" + SELECT source_hostname, source_ip, dest_ip, dest_port, + dest_hostname, process_name, direction, state, + COUNT(*) as cnt + FROM network_flow_map nfm + JOIN server_audit_full saf ON nfm.audit_id = saf.id + WHERE saf.id IN ( + SELECT DISTINCT ON (hostname) id FROM server_audit_full + WHERE status = 'ok' ORDER BY hostname, audit_date DESC + ) + AND (nfm.source_hostname = ANY(:hosts) OR nfm.dest_hostname = ANY(:hosts)) + AND nfm.source_hostname != COALESCE(nfm.dest_hostname, '') + AND nfm.dest_hostname IS NOT NULL + GROUP BY source_hostname, source_ip, dest_ip, dest_port, + dest_hostname, process_name, direction, state + ORDER BY source_hostname + """), {"hosts": hostnames}).fetchall() + else: + flows = [] + else: + flows = get_flow_map(db) + app_map = get_app_map(db) ctx = base_context(request, db, user) ctx.update({ "app_name": APP_NAME, "flows": flows, "app_map": app_map, + "all_domains": all_domains, "all_zones": all_zones, + "audited_servers": audited_servers, + "domain_filter": domain_filter, "server_filter": server_filter, }) return templates.TemplateResponse("audit_full_flowmap.html", ctx) diff --git a/app/templates/audit_full_flowmap.html b/app/templates/audit_full_flowmap.html index c4ceef2..d3e0783 100644 --- a/app/templates/audit_full_flowmap.html +++ b/app/templates/audit_full_flowmap.html @@ -4,14 +4,35 @@ < Retour