iflow-mcp-m507_ai-soc-agent 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- iflow_mcp_m507_ai_soc_agent-1.0.0.dist-info/METADATA +410 -0
- iflow_mcp_m507_ai_soc_agent-1.0.0.dist-info/RECORD +85 -0
- iflow_mcp_m507_ai_soc_agent-1.0.0.dist-info/WHEEL +5 -0
- iflow_mcp_m507_ai_soc_agent-1.0.0.dist-info/entry_points.txt +2 -0
- iflow_mcp_m507_ai_soc_agent-1.0.0.dist-info/licenses/LICENSE +21 -0
- iflow_mcp_m507_ai_soc_agent-1.0.0.dist-info/top_level.txt +1 -0
- src/__init__.py +8 -0
- src/ai_controller/README.md +139 -0
- src/ai_controller/__init__.py +12 -0
- src/ai_controller/agent_executor.py +596 -0
- src/ai_controller/cli/__init__.py +2 -0
- src/ai_controller/cli/main.py +243 -0
- src/ai_controller/session_manager.py +409 -0
- src/ai_controller/web/__init__.py +2 -0
- src/ai_controller/web/server.py +1181 -0
- src/ai_controller/web/static/css/README.md +102 -0
- src/api/__init__.py +13 -0
- src/api/case_management.py +271 -0
- src/api/edr.py +187 -0
- src/api/kb.py +136 -0
- src/api/siem.py +308 -0
- src/core/__init__.py +10 -0
- src/core/config.py +242 -0
- src/core/config_storage.py +684 -0
- src/core/dto.py +50 -0
- src/core/errors.py +36 -0
- src/core/logging.py +128 -0
- src/integrations/__init__.py +8 -0
- src/integrations/case_management/__init__.py +5 -0
- src/integrations/case_management/iris/__init__.py +11 -0
- src/integrations/case_management/iris/iris_client.py +885 -0
- src/integrations/case_management/iris/iris_http.py +274 -0
- src/integrations/case_management/iris/iris_mapper.py +263 -0
- src/integrations/case_management/iris/iris_models.py +128 -0
- src/integrations/case_management/thehive/__init__.py +8 -0
- src/integrations/case_management/thehive/thehive_client.py +193 -0
- src/integrations/case_management/thehive/thehive_http.py +147 -0
- src/integrations/case_management/thehive/thehive_mapper.py +190 -0
- src/integrations/case_management/thehive/thehive_models.py +125 -0
- src/integrations/cti/__init__.py +6 -0
- src/integrations/cti/local_tip/__init__.py +10 -0
- src/integrations/cti/local_tip/local_tip_client.py +90 -0
- src/integrations/cti/local_tip/local_tip_http.py +110 -0
- src/integrations/cti/opencti/__init__.py +10 -0
- src/integrations/cti/opencti/opencti_client.py +101 -0
- src/integrations/cti/opencti/opencti_http.py +418 -0
- src/integrations/edr/__init__.py +6 -0
- src/integrations/edr/elastic_defend/__init__.py +6 -0
- src/integrations/edr/elastic_defend/elastic_defend_client.py +351 -0
- src/integrations/edr/elastic_defend/elastic_defend_http.py +162 -0
- src/integrations/eng/__init__.py +10 -0
- src/integrations/eng/clickup/__init__.py +8 -0
- src/integrations/eng/clickup/clickup_client.py +513 -0
- src/integrations/eng/clickup/clickup_http.py +156 -0
- src/integrations/eng/github/__init__.py +8 -0
- src/integrations/eng/github/github_client.py +169 -0
- src/integrations/eng/github/github_http.py +158 -0
- src/integrations/eng/trello/__init__.py +8 -0
- src/integrations/eng/trello/trello_client.py +207 -0
- src/integrations/eng/trello/trello_http.py +162 -0
- src/integrations/kb/__init__.py +12 -0
- src/integrations/kb/fs_kb_client.py +313 -0
- src/integrations/siem/__init__.py +6 -0
- src/integrations/siem/elastic/__init__.py +6 -0
- src/integrations/siem/elastic/elastic_client.py +3319 -0
- src/integrations/siem/elastic/elastic_http.py +165 -0
- src/mcp/README.md +183 -0
- src/mcp/TOOLS.md +2827 -0
- src/mcp/__init__.py +13 -0
- src/mcp/__main__.py +18 -0
- src/mcp/agent_profiles.py +408 -0
- src/mcp/flow_agent_profiles.py +424 -0
- src/mcp/mcp_server.py +4086 -0
- src/mcp/rules_engine.py +487 -0
- src/mcp/runbook_manager.py +264 -0
- src/orchestrator/__init__.py +11 -0
- src/orchestrator/incident_workflow.py +244 -0
- src/orchestrator/tools_case.py +1085 -0
- src/orchestrator/tools_cti.py +359 -0
- src/orchestrator/tools_edr.py +315 -0
- src/orchestrator/tools_eng.py +378 -0
- src/orchestrator/tools_kb.py +156 -0
- src/orchestrator/tools_siem.py +1709 -0
- src/web/__init__.py +8 -0
- src/web/config_server.py +511 -0
src/api/siem.py
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Generic SIEM API for SamiGPT.
|
|
3
|
+
|
|
4
|
+
This module defines vendor-neutral DTOs and the ``SIEMClient`` interface
|
|
5
|
+
that orchestrator code and LLM tools will use for searching security events
|
|
6
|
+
and retrieving reports about files, IPs, and related entities.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from typing import Any, Dict, List, Optional, Protocol
|
|
15
|
+
|
|
16
|
+
from ..core.dto import BaseDTO
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Severity(str, Enum):
|
|
20
|
+
"""
|
|
21
|
+
Generic severity levels for SIEM alerts/events.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
LOW = "low"
|
|
25
|
+
MEDIUM = "medium"
|
|
26
|
+
HIGH = "high"
|
|
27
|
+
CRITICAL = "critical"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AlertStatus(str, Enum):
|
|
31
|
+
"""
|
|
32
|
+
Generic status for SIEM alerts.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
OPEN = "open"
|
|
36
|
+
IN_PROGRESS = "in_progress"
|
|
37
|
+
CLOSED = "closed"
|
|
38
|
+
SUPPRESSED = "suppressed"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class SourceType(str, Enum):
|
|
42
|
+
"""
|
|
43
|
+
High-level source type for events.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
ENDPOINT = "endpoint"
|
|
47
|
+
NETWORK = "network"
|
|
48
|
+
AUTH = "auth"
|
|
49
|
+
CLOUD = "cloud"
|
|
50
|
+
OTHER = "other"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class SiemEvent(BaseDTO):
|
|
55
|
+
"""
|
|
56
|
+
Generic SIEM event.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
id: str
|
|
60
|
+
timestamp: datetime
|
|
61
|
+
source_type: SourceType
|
|
62
|
+
message: str
|
|
63
|
+
host: Optional[str] = None
|
|
64
|
+
username: Optional[str] = None
|
|
65
|
+
ip: Optional[str] = None
|
|
66
|
+
process_name: Optional[str] = None
|
|
67
|
+
file_hash: Optional[str] = None
|
|
68
|
+
raw: Optional[dict] = None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass
|
|
72
|
+
class SiemAlert(BaseDTO):
|
|
73
|
+
"""
|
|
74
|
+
Generic SIEM alert.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
id: str
|
|
78
|
+
created_at: datetime
|
|
79
|
+
severity: Severity
|
|
80
|
+
status: AlertStatus
|
|
81
|
+
title: str
|
|
82
|
+
description: Optional[str] = None
|
|
83
|
+
related_entities: Optional[List[str]] = None
|
|
84
|
+
raw: Optional[dict] = None
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class QueryResult(BaseDTO):
|
|
89
|
+
"""
|
|
90
|
+
Container for results of a security event search.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
query: str
|
|
94
|
+
events: List[SiemEvent]
|
|
95
|
+
total_count: int
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@dataclass
|
|
99
|
+
class FileReport(BaseDTO):
|
|
100
|
+
"""
|
|
101
|
+
Aggregated report about a file (by hash).
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
file_hash: str
|
|
105
|
+
first_seen: Optional[datetime] = None
|
|
106
|
+
last_seen: Optional[datetime] = None
|
|
107
|
+
detection_count: int = 0
|
|
108
|
+
affected_hosts: Optional[List[str]] = None
|
|
109
|
+
raw: Optional[dict] = None
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@dataclass
|
|
113
|
+
class FileBehaviorSummary(BaseDTO):
|
|
114
|
+
"""
|
|
115
|
+
High-level behavior summary for a file.
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
file_hash: str
|
|
119
|
+
process_trees: Optional[List[dict]] = None
|
|
120
|
+
network_activity: Optional[List[dict]] = None
|
|
121
|
+
persistence_mechanisms: Optional[List[str]] = None
|
|
122
|
+
notes: Optional[str] = None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@dataclass
|
|
126
|
+
class IpAddressReport(BaseDTO):
|
|
127
|
+
"""
|
|
128
|
+
Aggregated report for an IP address.
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
ip: str
|
|
132
|
+
reputation: Optional[str] = None
|
|
133
|
+
geo: Optional[dict] = None
|
|
134
|
+
related_alerts: Optional[List[str]] = None
|
|
135
|
+
raw: Optional[dict] = None
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@dataclass
|
|
139
|
+
class RelatedEntities(BaseDTO):
|
|
140
|
+
"""
|
|
141
|
+
Entities related to a specific indicator (e.g. file hash).
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
indicator: str
|
|
145
|
+
hosts: Optional[List[str]] = None
|
|
146
|
+
users: Optional[List[str]] = None
|
|
147
|
+
processes: Optional[List[str]] = None
|
|
148
|
+
alerts: Optional[List[str]] = None
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class SIEMClient(Protocol):
|
|
152
|
+
"""
|
|
153
|
+
Vendor-neutral interface for SIEM operations.
|
|
154
|
+
|
|
155
|
+
This interface is designed to support the skills described in the README:
|
|
156
|
+
- search_security_events
|
|
157
|
+
- get_file_report
|
|
158
|
+
- get_file_behavior_summary
|
|
159
|
+
- get_entities_related_to_file
|
|
160
|
+
- get_ip_address_report
|
|
161
|
+
- search_user_activity
|
|
162
|
+
- pivot_on_indicator
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
def search_security_events(
|
|
166
|
+
self,
|
|
167
|
+
query: str,
|
|
168
|
+
limit: int = 100,
|
|
169
|
+
) -> QueryResult:
|
|
170
|
+
"""
|
|
171
|
+
Search security events/logs across environments using a vendor-specific
|
|
172
|
+
query language or filter, returning a normalized result.
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
...
|
|
176
|
+
|
|
177
|
+
def get_file_report(self, file_hash: str) -> FileReport:
|
|
178
|
+
...
|
|
179
|
+
|
|
180
|
+
def get_file_behavior_summary(self, file_hash: str) -> FileBehaviorSummary:
|
|
181
|
+
...
|
|
182
|
+
|
|
183
|
+
def get_entities_related_to_file(self, file_hash: str) -> RelatedEntities:
|
|
184
|
+
...
|
|
185
|
+
|
|
186
|
+
def get_ip_address_report(self, ip: str) -> IpAddressReport:
|
|
187
|
+
...
|
|
188
|
+
|
|
189
|
+
def search_user_activity(
|
|
190
|
+
self,
|
|
191
|
+
username: str,
|
|
192
|
+
limit: int = 100,
|
|
193
|
+
) -> QueryResult:
|
|
194
|
+
...
|
|
195
|
+
|
|
196
|
+
def pivot_on_indicator(
|
|
197
|
+
self,
|
|
198
|
+
indicator: str,
|
|
199
|
+
limit: int = 200,
|
|
200
|
+
) -> QueryResult:
|
|
201
|
+
"""
|
|
202
|
+
Given an IOC (hash, IP, domain, etc.), search for related events
|
|
203
|
+
and return them for further investigation.
|
|
204
|
+
"""
|
|
205
|
+
|
|
206
|
+
...
|
|
207
|
+
|
|
208
|
+
def search_kql_query(
|
|
209
|
+
self,
|
|
210
|
+
kql_query: str,
|
|
211
|
+
limit: int = 500,
|
|
212
|
+
hours_back: Optional[int] = None,
|
|
213
|
+
) -> QueryResult:
|
|
214
|
+
"""
|
|
215
|
+
Execute a KQL (Kusto Query Language) or advanced query for deeper investigations.
|
|
216
|
+
|
|
217
|
+
This method allows for complex queries that may include:
|
|
218
|
+
- Advanced filtering and aggregation
|
|
219
|
+
- Time-based analysis
|
|
220
|
+
- Cross-index searches
|
|
221
|
+
- Complex joins and correlations
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
kql_query: KQL query string or advanced query DSL
|
|
225
|
+
limit: Maximum number of events to return (default: 500)
|
|
226
|
+
hours_back: Optional time window in hours to limit the search
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
QueryResult containing matching events
|
|
230
|
+
"""
|
|
231
|
+
...
|
|
232
|
+
|
|
233
|
+
def get_siem_event_by_id(
|
|
234
|
+
self,
|
|
235
|
+
event_id: str,
|
|
236
|
+
) -> SiemEvent:
|
|
237
|
+
"""
|
|
238
|
+
Retrieve a specific security event by its ID.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
event_id: The unique identifier of the event to retrieve.
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
SiemEvent containing the event details.
|
|
245
|
+
|
|
246
|
+
Raises:
|
|
247
|
+
IntegrationError: If the event is not found or retrieval fails.
|
|
248
|
+
"""
|
|
249
|
+
...
|
|
250
|
+
|
|
251
|
+
def close_alert(
|
|
252
|
+
self,
|
|
253
|
+
alert_id: str,
|
|
254
|
+
reason: Optional[str] = None,
|
|
255
|
+
comment: Optional[str] = None,
|
|
256
|
+
) -> Dict[str, Any]:
|
|
257
|
+
"""
|
|
258
|
+
Close an alert in the SIEM, typically used for false positives.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
alert_id: The ID of the alert to close.
|
|
262
|
+
reason: Optional reason for closing (e.g., "false_positive", "benign_true_positive").
|
|
263
|
+
comment: Optional comment explaining why the alert is being closed.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
Dictionary with success status and alert details.
|
|
267
|
+
"""
|
|
268
|
+
...
|
|
269
|
+
|
|
270
|
+
def tag_alert(
|
|
271
|
+
self,
|
|
272
|
+
alert_id: str,
|
|
273
|
+
tag: str,
|
|
274
|
+
) -> Dict[str, Any]:
|
|
275
|
+
"""
|
|
276
|
+
Tag an alert with a classification tag (FP, TP, or NMI).
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
alert_id: The ID of the alert to tag.
|
|
280
|
+
tag: The tag to apply. Must be one of: "FP" (False Positive),
|
|
281
|
+
"TP" (True Positive), or "NMI" (Need More Investigation).
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
Dictionary with success status and alert details including updated tags.
|
|
285
|
+
"""
|
|
286
|
+
...
|
|
287
|
+
|
|
288
|
+
def add_alert_note(
|
|
289
|
+
self,
|
|
290
|
+
alert_id: str,
|
|
291
|
+
note: str,
|
|
292
|
+
) -> Dict[str, Any]:
|
|
293
|
+
"""
|
|
294
|
+
Add a note/comment to an alert in the SIEM.
|
|
295
|
+
|
|
296
|
+
This is used to document investigation findings, recommendations,
|
|
297
|
+
or other relevant information about the alert.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
alert_id: The ID of the alert to add a note to.
|
|
301
|
+
note: The note/comment text to add.
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
Dictionary with success status and alert details including the note.
|
|
305
|
+
"""
|
|
306
|
+
...
|
|
307
|
+
|
|
308
|
+
|
src/core/__init__.py
ADDED
src/core/config.py
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configuration models and loading logic for SamiGPT.
|
|
3
|
+
|
|
4
|
+
The goal of this module is to provide a single place where runtime
|
|
5
|
+
configuration (API URLs, auth tokens, timeouts, logging settings, etc.)
|
|
6
|
+
is defined and loaded from the environment.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
import os
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
from .errors import ConfigError
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class TheHiveConfig:
|
|
20
|
+
"""
|
|
21
|
+
Configuration for the TheHive case management integration.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
base_url: str
|
|
25
|
+
api_key: str
|
|
26
|
+
timeout_seconds: int = 30
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class IrisConfig:
|
|
31
|
+
"""
|
|
32
|
+
Configuration for the IRIS case management integration.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
base_url: str
|
|
36
|
+
api_key: str
|
|
37
|
+
timeout_seconds: int = 30
|
|
38
|
+
verify_ssl: bool = True
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class ElasticConfig:
|
|
43
|
+
"""
|
|
44
|
+
Configuration for Elastic (SIEM) integration.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
base_url: str
|
|
48
|
+
api_key: Optional[str] = None
|
|
49
|
+
username: Optional[str] = None
|
|
50
|
+
password: Optional[str] = None
|
|
51
|
+
timeout_seconds: int = 30
|
|
52
|
+
verify_ssl: bool = True
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class EDRConfig:
|
|
57
|
+
"""
|
|
58
|
+
Configuration for EDR integration (generic, can be Velociraptor, CrowdStrike, Elastic Defend, etc.).
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
edr_type: str # e.g., "velociraptor", "crowdstrike", "elastic_defend"
|
|
62
|
+
base_url: str
|
|
63
|
+
api_key: str
|
|
64
|
+
timeout_seconds: int = 30
|
|
65
|
+
verify_ssl: bool = True
|
|
66
|
+
additional_params: Optional[dict] = None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass
|
|
70
|
+
class CTIConfig:
|
|
71
|
+
"""
|
|
72
|
+
Configuration for CTI (Cyber Threat Intelligence) integration.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
cti_type: str # e.g., "local_tip", "opencti"
|
|
76
|
+
base_url: str
|
|
77
|
+
api_key: Optional[str] = None # Required for OpenCTI, optional for local_tip
|
|
78
|
+
timeout_seconds: int = 30
|
|
79
|
+
verify_ssl: bool = True
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass
|
|
83
|
+
class TrelloConfig:
|
|
84
|
+
"""
|
|
85
|
+
Configuration for Trello integration.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
api_key: str
|
|
89
|
+
api_token: str
|
|
90
|
+
fine_tuning_board_id: str
|
|
91
|
+
engineering_board_id: str
|
|
92
|
+
timeout_seconds: int = 30
|
|
93
|
+
verify_ssl: bool = True
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@dataclass
|
|
97
|
+
class ClickUpConfig:
|
|
98
|
+
"""
|
|
99
|
+
Configuration for ClickUp integration.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
api_token: str
|
|
103
|
+
fine_tuning_list_id: str
|
|
104
|
+
engineering_list_id: str
|
|
105
|
+
space_id: Optional[str] = None # Optional space ID for workspace organization
|
|
106
|
+
timeout_seconds: int = 30
|
|
107
|
+
verify_ssl: bool = True
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass
|
|
111
|
+
class GitHubConfig:
|
|
112
|
+
"""
|
|
113
|
+
Configuration for GitHub integration.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
api_token: str
|
|
117
|
+
fine_tuning_project_id: str
|
|
118
|
+
engineering_project_id: str
|
|
119
|
+
timeout_seconds: int = 30
|
|
120
|
+
verify_ssl: bool = True
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@dataclass
|
|
124
|
+
class EngConfig:
|
|
125
|
+
"""
|
|
126
|
+
Configuration for Engineering integrations.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
trello: Optional[TrelloConfig] = None
|
|
130
|
+
clickup: Optional[ClickUpConfig] = None
|
|
131
|
+
github: Optional[GitHubConfig] = None
|
|
132
|
+
provider: str = "trello" # "trello", "clickup", or "github" - which provider to use
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@dataclass
|
|
136
|
+
class LoggingConfig:
|
|
137
|
+
"""
|
|
138
|
+
Logging-related configuration.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
log_dir: str = "logs"
|
|
142
|
+
log_level: str = "INFO"
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@dataclass
|
|
146
|
+
class WebConfig:
|
|
147
|
+
"""
|
|
148
|
+
Configuration for the web management interface.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
admin_secret: str # Secret/password for accessing the management interface
|
|
152
|
+
session_secret: Optional[str] = None # Secret for session signing (auto-generated if not provided)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@dataclass
|
|
156
|
+
class SamiConfig:
|
|
157
|
+
"""
|
|
158
|
+
Top-level configuration for SamiGPT.
|
|
159
|
+
|
|
160
|
+
Additional sections (for SIEM, EDR, etc.) can be added here later.
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
thehive: Optional[TheHiveConfig] = None
|
|
164
|
+
iris: Optional[IrisConfig] = None
|
|
165
|
+
elastic: Optional[ElasticConfig] = None
|
|
166
|
+
edr: Optional[EDRConfig] = None
|
|
167
|
+
cti: Optional[CTIConfig] = None
|
|
168
|
+
eng: Optional[EngConfig] = None
|
|
169
|
+
logging: Optional[LoggingConfig] = None
|
|
170
|
+
web: Optional[WebConfig] = None
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _require_env(name: str) -> str:
|
|
174
|
+
"""
|
|
175
|
+
Read a required environment variable or raise ConfigError if missing.
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
value = os.getenv(name)
|
|
179
|
+
if not value:
|
|
180
|
+
raise ConfigError(f"Required environment variable {name!r} is not set")
|
|
181
|
+
return value
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def load_config() -> SamiConfig:
|
|
185
|
+
"""
|
|
186
|
+
Load SamiGPT configuration from environment variables.
|
|
187
|
+
|
|
188
|
+
Environment variables:
|
|
189
|
+
SAMIGPT_THEHIVE_URL: Base URL for TheHive (required if TheHive is used).
|
|
190
|
+
SAMIGPT_THEHIVE_API_KEY: API key/token for TheHive.
|
|
191
|
+
SAMIGPT_THEHIVE_TIMEOUT_SECONDS: Request timeout for TheHive (default: 30).
|
|
192
|
+
|
|
193
|
+
SAMIGPT_LOG_DIR: Directory for log files (default: "logs").
|
|
194
|
+
SAMIGPT_LOG_LEVEL: Root log level (default: "INFO").
|
|
195
|
+
|
|
196
|
+
If TheHive variables are not set, the configuration will still be returned
|
|
197
|
+
with `thehive` set to None, allowing you to run without that integration.
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
# Logging config
|
|
201
|
+
log_dir = os.getenv("SAMIGPT_LOG_DIR", "logs")
|
|
202
|
+
log_level = os.getenv("SAMIGPT_LOG_LEVEL", "INFO")
|
|
203
|
+
logging_cfg = LoggingConfig(log_dir=log_dir, log_level=log_level)
|
|
204
|
+
|
|
205
|
+
# TheHive config (optional but recommended). If one of the key vars is set,
|
|
206
|
+
# we require the others to avoid a half-configured integration.
|
|
207
|
+
thehive_url = os.getenv("SAMIGPT_THEHIVE_URL")
|
|
208
|
+
thehive_api_key = os.getenv("SAMIGPT_THEHIVE_API_KEY")
|
|
209
|
+
thehive_timeout_raw = os.getenv("SAMIGPT_THEHIVE_TIMEOUT_SECONDS", "30")
|
|
210
|
+
|
|
211
|
+
thehive_cfg: Optional[TheHiveConfig]
|
|
212
|
+
if thehive_url or thehive_api_key:
|
|
213
|
+
# If any TheHive-related env var is set, treat TheHive as enabled
|
|
214
|
+
if not thehive_url:
|
|
215
|
+
raise ConfigError(
|
|
216
|
+
"SAMIGPT_THEHIVE_URL must be set when SAMIGPT_THEHIVE_API_KEY is provided"
|
|
217
|
+
)
|
|
218
|
+
if not thehive_api_key:
|
|
219
|
+
raise ConfigError(
|
|
220
|
+
"SAMIGPT_THEHIVE_API_KEY must be set when SAMIGPT_THEHIVE_URL is provided"
|
|
221
|
+
)
|
|
222
|
+
try:
|
|
223
|
+
timeout_seconds = int(thehive_timeout_raw)
|
|
224
|
+
except ValueError as exc:
|
|
225
|
+
raise ConfigError(
|
|
226
|
+
"SAMIGPT_THEHIVE_TIMEOUT_SECONDS must be an integer"
|
|
227
|
+
) from exc
|
|
228
|
+
|
|
229
|
+
thehive_cfg = TheHiveConfig(
|
|
230
|
+
base_url=thehive_url,
|
|
231
|
+
api_key=thehive_api_key,
|
|
232
|
+
timeout_seconds=timeout_seconds,
|
|
233
|
+
)
|
|
234
|
+
else:
|
|
235
|
+
thehive_cfg = None
|
|
236
|
+
|
|
237
|
+
return SamiConfig(
|
|
238
|
+
thehive=thehive_cfg,
|
|
239
|
+
logging=logging_cfg,
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
|