Automatitzar l'informe setmanal del SOC amb Python
L'informe setmanal eren tres hores de copiar i enganxar. En automatitzar-lo amb Python, els problemes de veritat van ser la paginació, les zones horàries i les fallades en silenci.
- python
- automatizacion
- soc
- reporting
- buenas-practicas
Hi ha una tasca que apareix a tots els SOC: l'informe periòdic. Quantes alertes, de quin tipus, quantes tancades, quina tendència. Triga hores, surt quasi idèntic cada vegada i ningú no l'enyora quan desapareix. És el candidat perfecte per automatitzar.
Ho vaig muntar en Python. El codi va ser el fàcil. El que va costar va ser tota la resta.
Separar les tres fases
El primer intent va ser un script que consultava, calculava i escrivia el document alhora. Va funcionar una setmana i es va tornar impossible de tocar. Refet en tres parts independents:
- Extreure. Parlar amb l'API i desar la resposta crua, sense interpretar res.
- Normalitzar. Passar aquesta resposta a una estructura pròpia, estable, que no canviï encara que canviï l'API.
- Renderitzar. Convertir aquesta estructura en el document final.
L'avantatge apareix a la primera incidència. Si l'informe surt estrany, se sap en quina fase mirar sense rellegir l'script sencer. I si el fabricant canvia un camp, només es toca la fase de normalitzar.
La paginació, que sempre mossega
L'error clàssic, i el vaig cometre: demanar les dades, rebre una llista amb bona pinta i donar-la per completa. Quasi cap API retorna tot d'un cop. Sol haver-hi un topall per pàgina i un cursor per continuar.
El pitjor d'aquesta fallada és que no trenca res. No hi ha excepció ni traça. Simplement l'informe diu 200 alertes on n'hi va haver 1.400, i el número sembla perfectament plausible. Va estar malament dues setmanes abans que algú ho notés.
Des de llavors, qualsevol consulta que pugui retornar més d'un element passa per una funció que esgota el cursor, i el resultat es contrasta amb el total que declara la mateixa API. Si no quadren, l'script s'atura.
Zones horàries
L'API respon en UTC. L'informe es llegeix en hora peninsular. Entre una cosa i l'altra hi ha una o dues hores segons l'època de l'any, i això desplaça el tall de la setmana.
El símptoma és subtil: les alertes del diumenge a la nit cauen a la setmana equivocada. Els totals del mes quadren, els setmanals no, i costa veure per què.
La regla que segueixo ara és simple i no l'he tornat a trencar: tot es maneja en UTC i amb dates conscients de zona horària fins a l'últim moment. La conversió a hora local passa només en escriure el text, mai en un càlcul.
Que falli en alt, no en silenci
Un script programat que falla sense avisar és pitjor que no tenir-lo, perquè l'absència d'informe s'interpreta com una setmana tranquil·la. El que vaig aprendre a cobrir:
- Reintents amb espera creixent davant de límits de peticions, en lloc de martellejar l'API.
- Idempotència. Executar-lo dues vegades ha de produir el mateix informe, no duplicar res.
- Un avís explícit en fallar, amb la fase que s'ha trencat. Un traceback en un log que ningú llegeix no és un avís.
- Comprovacions de coherència: si el total de la setmana és zero, quasi segur que el trencat és l'script i no la realitat.
Què no vaig automatitzar
L'anàlisi. L'script reuneix les dades, calcula les xifres i deixa el document muntat. La lectura de per què han pujat les deteccions d'un tipus concret, o si una caiguda és bona notícia o un sensor caigut, continua fent-la una persona.
Automatitzar la recollida retorna les hores que se n'anaven a copiar i enganxar. Automatitzar la conclusió produeix informes que ningú no es creu, i amb raó.
Aquell generador setmanal va créixer amb el temps fins a convertir-se en alguna cosa més completa: un sistema que també enriqueix cada CVE contra NVD, CISA KEV i EPSS abans de posar-lo a l'informe. El vaig publicar en obert: el codi és a GitHub.