""" Endpoints pour la détection de la rotation de fingerprints JA4 et des menaces persistantes """ from fastapi import APIRouter, HTTPException, Query from ..database import db router = APIRouter(prefix="/api/rotation", tags=["rotation"]) @router.get("/ja4-rotators") async def get_ja4_rotators(limit: int = Query(50, ge=1, le=500)): """IPs qui effectuent le plus de rotation de fingerprints JA4.""" try: sql = """ SELECT replaceRegexpAll(toString(src_ip), '^::ffff:', '') AS ip, distinct_ja4_count, total_hits FROM mabase_prod.view_host_ip_ja4_rotation ORDER BY distinct_ja4_count DESC LIMIT %(limit)s """ result = db.query(sql, {"limit": limit}) items = [] for row in result.result_rows: distinct = int(row[1]) items.append({ "ip": str(row[0]), "distinct_ja4_count":distinct, "total_hits": int(row[2]), "evasion_score": min(100, distinct * 15), }) return {"items": items, "total": len(items)} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/persistent-threats") async def get_persistent_threats(limit: int = Query(100, ge=1, le=1000)): """Menaces persistantes triées par score de persistance.""" try: sql = """ SELECT replaceRegexpAll(toString(src_ip), '^::ffff:', '') AS ip, recurrence, worst_score, worst_threat_level, first_seen, last_seen FROM mabase_prod.view_ip_recurrence ORDER BY (least(100, recurrence * 20 + worst_score * 50)) DESC LIMIT %(limit)s """ result = db.query(sql, {"limit": limit}) items = [] for row in result.result_rows: recurrence = int(row[1]) worst_score = float(row[2] or 0) items.append({ "ip": str(row[0]), "recurrence": recurrence, "worst_score": worst_score, "worst_threat_level":str(row[3] or ""), "first_seen": str(row[4]), "last_seen": str(row[5]), "persistence_score": min(100, recurrence * 20 + worst_score * 50), }) return {"items": items, "total": len(items)} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/ip/{ip}/ja4-history") async def get_ip_ja4_history(ip: str): """Historique des JA4 utilisés par une IP donnée.""" try: sql = """ SELECT ja4, sum(hits) AS hits, min(window_start) AS first_seen, max(window_start) AS last_seen FROM mabase_prod.agg_host_ip_ja4_1h WHERE replaceRegexpAll(toString(src_ip), '^::ffff:', '') = %(ip)s GROUP BY ja4 ORDER BY hits DESC """ result = db.query(sql, {"ip": ip}) items = [ { "ja4": str(row[0]), "hits": int(row[1]), "first_seen":str(row[2]), "last_seen": str(row[3]), } for row in result.result_rows ] return {"ip": ip, "ja4_history": items, "total": len(items)} except Exception as e: raise HTTPException(status_code=500, detail=str(e))