vvillarreal-cfee commited on
Commit
9ac0306
·
verified ·
1 Parent(s): 41f9f93

feat: First functional Crew

Browse files
Files changed (2) hide show
  1. .gitignore +2 -1
  2. src/app.py +80 -86
.gitignore CHANGED
@@ -1 +1,2 @@
1
- Pipfile.lock
 
 
1
+ Pipfile.lock
2
+ .env
src/app.py CHANGED
@@ -1,8 +1,5 @@
1
- import os
2
-
3
  import streamlit as st
4
- from google import genai
5
- from crewai import Agent, Task, Crew, Process
6
 
7
  # --- Interfaz de Usuario con Streamlit ---
8
  st.set_page_config(
@@ -14,6 +11,28 @@ st.set_page_config(
14
  if 'gemini_api_key' not in st.session_state:
15
  st.session_state['gemini_api_key'] = ''
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
  st.title("📄 Generador IA de Informes Post-Mortem")
19
 
@@ -21,73 +40,9 @@ st.title("📄 Generador IA de Informes Post-Mortem")
21
  # --- Sidebar para la configuración de la API Key ---
22
  with st.sidebar:
23
  st.header("⚙️ Instrucciones")
24
-
25
- # Campo de entrada para la API Key
26
- st.session_state['gemini_api_key'] = st.text_input(
27
- "1. 🔑 Ingresa tu API Key de Gemini",
28
- type="password",
29
- value=st.session_state['gemini_api_key']
30
- )
31
-
32
- if st.session_state['gemini_api_key']:
33
- st.success("API Key cargada. ¡Puedes generar el informe!")
34
- else:
35
- st.warning("🚨 Por favor, ingresa tu API Key de Gemini.")
36
-
37
- st.write("2. 📄 Completa el formulario con los detalles de la incidencia (o pega el texto RAW y deja que la IA extraiga los campos)")
38
- st.write("3. 🚀 Presiona el botón y la IA generará un informe técnico estructurado post-mortem de tu incidente.")
39
-
40
-
41
- # --- Función para generar el Post-Mortem ---
42
- def generar_post_mortem(api_key, tipo_alerta, sistema, fecha_hora, impacto, acciones):
43
- """
44
- Construye el prompt, inicializa el cliente con la API Key y genera el informe.
45
- """
46
- MODEL_NAME = "gemini-2.5-flash"
47
-
48
- # 1. Inicializar el cliente con la clave ingresada
49
- try:
50
- client = genai.Client(api_key=api_key)
51
- except Exception as e:
52
- return f"🚨 Error al inicializar el cliente de Gemini: {e}"
53
-
54
- # 2. Definir la instrucción (System Instruction)
55
- system_instruction = (
56
- "Eres un especialista Incident Response en Ciberseguridad. Tu tarea es generar un informe "
57
- "Post-Mortem conciso y profesional de incidentes de ciberseguridad, estructurado con las secciones: "
58
- "'Resumen Ejecutivo', 'Qué Sucedió (Timeline)', 'Análisis de Causa Raíz', "
59
- "'Impacto del Negocio' y 'Acciones Realizadas'. "
60
- "Usa Markdown (##) para los encabezados y un tono técnico y formal. "
61
- "No añadas introducciones ni conclusiones fuera del formato solicitado."
62
- )
63
 
64
- # 3. Construir el contenido del prompt
65
- prompt_content = f"""
66
- Genera un informe Post-Mortem usando la siguiente información de la incidencia:
67
- - **Tipo de Alerta/Problema Principal**: {tipo_alerta}
68
- - **Sistema Afectado**: {sistema}
69
- - **Fecha y Hora de Inicio**: {fecha_hora}
70
-
71
- ## Detalles para el Informe Post-Mortem:
72
- {impacto}
73
-
74
- ## Acciones realizadas:
75
- {acciones}
76
- """
77
-
78
- try:
79
- # Llamar a la API de Gemini
80
- response = client.models.generate_content(
81
- model=MODEL_NAME,
82
- contents=prompt_content,
83
- config=genai.types.GenerateContentConfig(
84
- system_instruction=system_instruction
85
- )
86
- )
87
- return response.text
88
- except Exception as e:
89
- # Muestra errores comunes de autenticación si la clave es incorrecta
90
- return f"🚨 Error al generar el informe con Gemini (posible API Key inválida o límite excedido): {e}"
91
 
92
 
93
  # --- Formulario de entrada de datos principal ---
@@ -110,7 +65,7 @@ with st.form("post_mortem_form"):
110
  )
111
 
112
  impacto_detalle = st.text_area(
113
- "Impacto del Negocio y Observaciones",
114
  placeholder="Ej: Latencia elevada afectó al 20% de los usuarios.",
115
  height=150,
116
  )
@@ -126,32 +81,71 @@ with st.form("post_mortem_form"):
126
 
127
  # --- Lógica de procesamiento ---
128
  if submitted:
129
- api_key = st.session_state.get('gemini_api_key')
130
-
131
- if not api_key:
132
- st.error("❌ Por favor, ingresa tu API Key de Gemini en el panel lateral (sidebar) antes de continuar.")
133
 
134
- elif not all([tipo_alerta, sistema_afectado, fecha_hora, impacto_detalle, acciones_tomadas]):
135
  st.error("❌ Por favor, completa todos los campos del formulario para generar el informe.")
136
 
137
  else:
138
- with st.spinner("⏳ Generando informe técnico con Google Gemini..."):
139
- informe = generar_post_mortem(
140
- api_key,
141
- tipo_alerta,
142
- sistema_afectado,
143
- fecha_hora,
144
- impacto_detalle,
145
- acciones_tomadas
 
 
 
 
 
146
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
  # Mostrar el resultado
149
  st.divider()
150
  st.success("✅ Informe Post-Mortem Generado")
151
- st.markdown(informe)
 
152
  st.download_button(
153
  label="Descargar Informe (.md)",
154
- data=informe,
155
  file_name="post_mortem_incidencia.md",
156
  mime="text/markdown",
157
  on_click="ignore"
 
 
 
1
  import streamlit as st
2
+ from crewai import Agent, Task, Crew, Process, LLM
 
3
 
4
  # --- Interfaz de Usuario con Streamlit ---
5
  st.set_page_config(
 
11
  if 'gemini_api_key' not in st.session_state:
12
  st.session_state['gemini_api_key'] = ''
13
 
14
+ llm = LLM(
15
+ model="gemini/gemini-2.0-flash",
16
+ temperature=0.3
17
+ )
18
+
19
+ threat_hunter_agent = Agent(
20
+ role="Security Threat Hunter",
21
+ goal="Rapidly identify, extract, and analyze key Indicators of Compromise (IOCs) from initial security alerts to provide structured and actionable intelligence.",
22
+ backstory="Highly specialized in threat intelligence, capable of parsing raw incident data, identifying patterns, and performing virtual lookups on security intelligence databases (like VirusTotal, IPInfo, etc.). Your output must be a concise, structured summary.",
23
+ verbose=True,
24
+ allow_delegation=False,
25
+ llm=llm,
26
+ )
27
+
28
+ reporter_agent = Agent(
29
+ role="Incident Response Document Specialist",
30
+ goal="Generate a formal, professional, and comprehensive Incident Response Report based on the initial alert and the technical intelligence provided by the Threat Hunter.",
31
+ backstory="An expert in cybersecurity documentation, focusing on clarity, structure, and adherence to industry-standard reporting formats. You transform raw data into polished, readable documents suitable for management and technical teams.",
32
+ verbose=True,
33
+ llm=llm,
34
+ )
35
+
36
 
37
  st.title("📄 Generador IA de Informes Post-Mortem")
38
 
 
40
  # --- Sidebar para la configuración de la API Key ---
41
  with st.sidebar:
42
  st.header("⚙️ Instrucciones")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
+ st.write("1. 📄 Completa el formulario con los detalles de la incidencia (o pega el texto RAW y deja que la IA extraiga los campos)")
45
+ st.write("2. 🚀 Presiona el botón y la IA generará un informe técnico estructurado post-mortem de tu incidente.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
 
48
  # --- Formulario de entrada de datos principal ---
 
65
  )
66
 
67
  impacto_detalle = st.text_area(
68
+ "Detalles del incidente e Impacto",
69
  placeholder="Ej: Latencia elevada afectó al 20% de los usuarios.",
70
  height=150,
71
  )
 
81
 
82
  # --- Lógica de procesamiento ---
83
  if submitted:
 
 
 
 
84
 
85
+ if not all([tipo_alerta, sistema_afectado, fecha_hora, impacto_detalle, acciones_tomadas]):
86
  st.error("❌ Por favor, completa todos los campos del formulario para generar el informe.")
87
 
88
  else:
89
+ with st.spinner("⏳ Generando informe técnico..."):
90
+ task_ioc_extraction = Task(
91
+ description=f"""
92
+ Input: Initial raw incident alert details
93
+ {impacto_detalle}
94
+ Process:
95
+ 1. Extract 10 observable Indicators of Compromise (IOCs) including IPs, domains, file hashes (SHA256, MD5), and URLs from the input.
96
+ 2. For each extracted IOC, simulate querying external intelligence services (like VirusTotal, IPInfo, etc.).
97
+ 3. Synthesize the findings into a clear, structured intelligence summary.
98
+ Output Requirements: The output MUST be a JSON-like or clearly delimited text block, detailing each IOC, its type, and a summary of the associated risk/reputation found (e.g., "Malicious/Known C2," "Clean," "High Reputation," "Related to Phishing Campaign X"). This summary is the ONLY content that should be passed to the next agent.
99
+ """,
100
+ expected_output="A structured summary of technical findings including IPs, hashes, and domains, and their corresponding threat intelligence status, ready for the final report.",
101
+ agent=threat_hunter_agent,
102
  )
103
+
104
+ task_report_drafting = Task(
105
+ description=f"""
106
+ Input:
107
+ 1. The original user input:
108
+ - **Tipo de Alerta**: {tipo_alerta}
109
+ - **Sistema Afectado**: {sistema_afectado}
110
+ - **Fecha y Hora**: {fecha_hora}
111
+ - **Detalles del Incidente**: {impacto_detalle}
112
+ - **Acciones Tomadas (Mitigación Inmediata)**: {acciones_tomadas}
113
+ 2. The structured technical intelligence summary provided by the Threat Hunter.
114
+
115
+ Process: Draft a complete, professional Incident Response Report.
116
+
117
+ Output Requirements: The report MUST be formatted in Markdown and include the following mandatory sections:
118
+ 1. Executive Summary (A brief, high-level overview).
119
+ 2. Initial Incident Details (Source, Time, Initial Observation).
120
+ 3. Technical Analysis & Indicators of Compromise (IOCs) (A detailed section incorporating ALL findings from the Threat Hunter agent information context).
121
+ 4. Impact Assessment (Potential or confirmed impact on systems/data).
122
+ 5. Mitigation or remediation steps taken (if any).
123
+
124
+ The entire final output must be this Markdown report.
125
+ """,
126
+ expected_output="A complete Incident Response Report in Spanish language. Formatted as markdown without '```'",
127
+ agent=reporter_agent,
128
+ markdown=True,
129
+ context=[task_ioc_extraction] # Esta tarea espera el resultado de la anterior
130
+ )
131
+
132
+ incident_crew = Crew(
133
+ agents=[threat_hunter_agent, reporter_agent],
134
+ tasks=[task_ioc_extraction, task_report_drafting],
135
+ process=Process.sequential, # Ejecución secuencial: Threat Hunter -> Reporter
136
+ verbose=True # Nivel de detalle de la ejecución
137
+ )
138
+
139
+ final_report = incident_crew.kickoff()
140
 
141
  # Mostrar el resultado
142
  st.divider()
143
  st.success("✅ Informe Post-Mortem Generado")
144
+ st.code(incident_crew.usage_metrics)
145
+ st.markdown(final_report)
146
  st.download_button(
147
  label="Descargar Informe (.md)",
148
+ data=final_report.raw,
149
  file_name="post_mortem_incidencia.md",
150
  mime="text/markdown",
151
  on_click="ignore"