-
Notifications
You must be signed in to change notification settings - Fork 0
Home
🇬🇧 English first · 🇪🇸 Español más abajo.
Two Python scripts, 115 lines between them: one writes 5.000 synthetic log lines, the other reads them back and summarises them into an incident report. The exercise is the parsing and the reporting — it does not detect anything, and this wiki says so rather than implying otherwise.
Repo: mindset-code/project-security-log-analysis
- Arquitectura del SIEM — the two scripts, the real log format and the flow
- Reglas de deteccion — why there are no detection rules, and what the report actually counts
generate_logs.py picks an event at random from five, with fixed weights. log_analysis.py reads the file back and counts how many times each label appeared.
That means the classification is written by the generator and read by the analyser. BRUTE_FORCE_ATTEMPT is not a conclusion the analyser reaches — it is a string the generator already put in the line. There is no threshold, no time window, no correlation between events and no comparison against a baseline. The line
**Intentos de Fuerza Bruta Detectados:** 246
is a count of a field, not a detection.
This is worth stating plainly because it is the difference between a log-parsing exercise — which this is, and does correctly — and a SIEM, which it is not.
One line, space-separated, with the event in square brackets:
2026-01-05 02:50:25 192.168.1.83 [LOGIN_SUCCESS] User admin logged in successfully.
2026-01-05 02:50:31 192.168.1.185 [LOGIN_FAILED] User admin failed to log in.
Five event types exist, and no others:
| Event | Weight in the generator | Count in the committed file | Share |
|---|---|---|---|
LOGIN_SUCCESS |
0.60 | 3.057 | 61,1 % |
LOGIN_FAILED |
0.20 | 969 | 19,4 % |
ACCESS_DENIED |
0.10 | 478 | 9,6 % |
PORT_SCAN_DETECTED |
0.05 | 250 | 5,0 % |
BRUTE_FORCE_ATTEMPT |
0.05 | 246 | 4,9 % |
The observed shares track the weights closely, which is what you would expect from 5.000 independent draws and is itself the clearest evidence that nothing in this data is an attack.
flowchart LR
A["generate_logs.py<br/>5.000 lines, 5 events by weight"] --> B["security_logs.txt<br/>426 KB, committed"]
B --> C["log_analysis.py<br/>1 regex + Counter"]
C --> D["security_analysis_report.md<br/>4 tables"]
python generate_logs.py # writes security_logs.txt
python log_analysis.py # writes security_analysis_report.mdStandard library only: re, random, collections.Counter, datetime. No dependencies, no configuration, no arguments.
Both the log file and the report are committed, so every number on this wiki can be checked without running anything.
The vocabulary — event triage, indicators, incident write-up — follows the Security Operations domain of the ISC2 Certified in Cybersecurity (CC). What the code exercises from that domain is the last part: turning a pile of events into a document somebody can read. The monitoring and the identification of indicators are not implemented, and Reglas de deteccion explains exactly what would have to be added.
Dos scripts de Python, 115 líneas entre los dos: uno escribe 5.000 líneas de log sintéticas y el otro las vuelve a leer y las resume en un informe de incidentes. El ejercicio está en el parseo y en la redacción del informe — no detecta nada, y esta wiki lo dice en vez de dejar entender otra cosa.
Repo: mindset-code/project-security-log-analysis
- Arquitectura del SIEM — los dos scripts, el formato real del log y el flujo
- Reglas de deteccion — por qué no hay reglas de detección y qué cuenta de verdad el informe
generate_logs.py elige un evento al azar entre cinco, con pesos fijos. log_analysis.py vuelve a leer el fichero y cuenta cuántas veces apareció cada etiqueta.
Es decir: la clasificación la escribe el generador y la lee el analizador. BRUTE_FORCE_ATTEMPT no es una conclusión a la que llegue el analizador — es una cadena que el generador ya había puesto en la línea. No hay umbral, ni ventana temporal, ni correlación entre eventos, ni comparación contra una línea base. La línea
**Intentos de Fuerza Bruta Detectados:** 246
es el recuento de un campo, no una detección.
Merece la pena decirlo sin rodeos, porque ahí está la diferencia entre un ejercicio de parseo de logs —que es lo que esto es, y lo hace bien— y un SIEM, que no lo es.
Una línea, separada por espacios, con el evento entre corchetes:
2026-01-05 02:50:25 192.168.1.83 [LOGIN_SUCCESS] User admin logged in successfully.
2026-01-05 02:50:31 192.168.1.185 [LOGIN_FAILED] User admin failed to log in.
Existen cinco tipos de evento, y ninguno más:
| Evento | Peso en el generador | Recuento en el fichero commiteado | Porcentaje |
|---|---|---|---|
LOGIN_SUCCESS |
0,60 | 3.057 | 61,1 % |
LOGIN_FAILED |
0,20 | 969 | 19,4 % |
ACCESS_DENIED |
0,10 | 478 | 9,6 % |
PORT_SCAN_DETECTED |
0,05 | 250 | 5,0 % |
BRUTE_FORCE_ATTEMPT |
0,05 | 246 | 4,9 % |
Los porcentajes observados siguen de cerca a los pesos, que es lo que cabe esperar de 5.000 tiradas independientes y es en sí mismo la prueba más clara de que en estos datos no hay ningún ataque.
Ver el diagrama de arriba: el generador escribe security_logs.txt, el analizador lo lee con una expresión regular y un Counter, y de ahí sale security_analysis_report.md con cuatro tablas.
python generate_logs.py # escribe security_logs.txt
python log_analysis.py # escribe security_analysis_report.mdSolo biblioteca estándar: re, random, collections.Counter y datetime. Sin dependencias, sin configuración y sin argumentos.
Tanto el fichero de logs como el informe están commiteados, así que todos los números de esta wiki se pueden comprobar sin ejecutar nada.
El vocabulario —triaje de eventos, indicadores, redacción del incidente— sigue el dominio Security Operations de la certificación ISC2 Certified in Cybersecurity (CC). De ese dominio, lo que el código ejercita es la última parte: convertir un montón de eventos en un documento que alguien pueda leer. La monitorización y la identificación de indicadores no están implementadas, y Reglas de deteccion explica exactamente qué habría que añadir.