import logging from datetime import datetime, timezone from pymisp import PyMISP, PyMISPError from sqlalchemy.exc import IntegrityError from sqlalchemy import select import config from db_setup import ModificadosEv class MISPProcessor: def __init__(self): self.misp = PyMISP(config.MISP_CONFIG["misp_url"], config.MISP_CONFIG["misp_authkey"], ssl=False) def search_events(self, published=True): events_data = self.misp.search_index(publish_timestamp=config.RANGO_DIAS, published=published ) parsed = [] for e in events_data: eid = e.get("id") uuid = e.get("uuid") c = e.get("attribute_count", 0) # o len(ev["Attribute"]) si quieres parsed.append({"id": eid, "uuid": uuid, "attribute_count": str(c)}) return parsed def fix_correlation(self, session, event_id, event_uuid, event_attribute_count): # Para publicar publica = False stmt = select(ModificadosEv).where(ModificadosEv.evento_uuid == event_uuid, ModificadosEv.attribute_count >= int(event_attribute_count)) existe = session.scalars(stmt).first() if existe: logging.info(f"[OMITIDO] {event_uuid} ya en DB.") return try: count = int(event_attribute_count) except: logging.error(f"[ERROR] count inválido: {event_attribute_count}") return if count > config.MAX_ATTRS: logging.info(f"[OMITIDO] {event_id} excede {config.MAX_ATTRS}.") return resp = self.misp.direct_call("attributes/restSearch", {"eventid": event_id}) if "Attribute" not in resp: logging.error(f"[ERROR] Sin Attribute en {event_id}") return for a in resp["Attribute"]: t = a["type"] if t in config.NO_CORRELATIVOS: if not a["disable_correlation"]: self.misp.direct_call(f"attributes/edit/{a['id']}", {"to_ids": "0","disable_correlation": True}) publica = True if config.NO_CORRELATIVOS_EXCLUSION: try: ex_resp = self.misp.direct_call("correlation_exclusions/add", { "value": a["value"], "type": a["type"], "enabled": True }) if "CorrelationExclusion" not in ex_resp and ex_resp.get("errors"): logging.warning(f"Exclusión error: {ex_resp.get('errors')}") except PyMISPError as e: logging.error(f"PyMISPError excl: {e}") else: if a["to_ids"]: self.misp.direct_call(f"attributes/edit/{a['id']}", {"to_ids": "0"}) publica = True elif t in config.IDS_CORRELATIVOS: if not a["to_ids"]: self.misp.direct_call(f"attributes/edit/{a['id']}", {"to_ids": "1", "disable_correlation": False}) publica = True else: if a["disable_correlation"]: self.misp.direct_call(f"attributes/edit/{a['id']}", {"disable_correlation": False}) publica = True new_ev = ModificadosEv(evento_uuid=event_uuid, publicado_fecha=datetime.now(), attribute_count=int(event_attribute_count)) session.add(new_ev) try: session.commit() logging.info(f"[PROCESADO] {event_id} => {event_uuid}") except IntegrityError: session.rollback() logging.warning(f"[WARNING] Duplicado {event_uuid}") # Si pasa flag if publica: try: publish_resp = self.misp.publish(int(event_id), alert=False) logging.info(f"[PUBLICADO] Evento {event_id} => {publish_resp}") except PyMISPError as e: logging.error(f"[ERROR PUBLICAR] {event_id}: {e}") except Exception as ex: logging.error(f"[ERROR PUBLICAR] {event_id}: {ex}")