diff --git a/backend/routes/incidents.py b/backend/routes/incidents.py index a2203aa..2058a21 100644 --- a/backend/routes/incidents.py +++ b/backend/routes/incidents.py @@ -29,15 +29,27 @@ async def get_incident_clusters( # Note: src_ip est en IPv6, les IPv4 sont stockés comme ::ffff:x.x.x.x # toIPv4() convertit les IPv4-mapped, IPv4NumToString() retourne l'IPv4 en notation x.x.x.x cluster_query = """ - WITH subnet_groups AS ( + WITH cleaned_ips AS ( + SELECT + replaceRegexpAll(toString(src_ip), '^::ffff:', '') AS clean_ip, + detected_at, + ja4, + country_code, + asn_number, + threat_level, + anomaly_score + FROM ml_detected_anomalies + WHERE detected_at >= now() - INTERVAL %(hours)s HOUR + ), + subnet_groups AS ( SELECT concat( - splitByChar('.', IPv4NumToString(toIPv4(src_ip)))[1], '.', - splitByChar('.', IPv4NumToString(toIPv4(src_ip)))[2], '.', - splitByChar('.', IPv4NumToString(toIPv4(src_ip)))[3], '.0/24' + splitByChar('.', clean_ip)[1], '.', + splitByChar('.', clean_ip)[2], '.', + splitByChar('.', clean_ip)[3], '.0/24' ) AS subnet, count() AS total_detections, - uniq(src_ip) AS unique_ips, + uniq(clean_ip) AS unique_ips, min(detected_at) AS first_seen, max(detected_at) AS last_seen, argMax(ja4, detected_at) AS ja4, @@ -45,10 +57,8 @@ async def get_incident_clusters( argMax(asn_number, detected_at) AS asn_number, argMax(threat_level, detected_at) AS threat_level, avg(anomaly_score) AS avg_score, - any(IPv4NumToString(toIPv4(src_ip))) AS sample_ip - FROM ml_detected_anomalies - WHERE detected_at >= now() - INTERVAL %(hours)s HOUR - AND isIPv4MappedIPv6(src_ip) -- Filtre uniquement les IPv4 + argMax(clean_ip, detected_at) AS sample_ip + FROM cleaned_ips GROUP BY subnet HAVING total_detections >= 2 )