proxilion 0.0.1__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.
- proxilion/__init__.py +136 -0
- proxilion/audit/__init__.py +133 -0
- proxilion/audit/base_exporters.py +527 -0
- proxilion/audit/compliance/__init__.py +130 -0
- proxilion/audit/compliance/base.py +457 -0
- proxilion/audit/compliance/eu_ai_act.py +603 -0
- proxilion/audit/compliance/iso27001.py +544 -0
- proxilion/audit/compliance/soc2.py +491 -0
- proxilion/audit/events.py +493 -0
- proxilion/audit/explainability.py +1173 -0
- proxilion/audit/exporters/__init__.py +58 -0
- proxilion/audit/exporters/aws_s3.py +636 -0
- proxilion/audit/exporters/azure_storage.py +608 -0
- proxilion/audit/exporters/cloud_base.py +468 -0
- proxilion/audit/exporters/gcp_storage.py +570 -0
- proxilion/audit/exporters/multi_exporter.py +498 -0
- proxilion/audit/hash_chain.py +652 -0
- proxilion/audit/logger.py +543 -0
- proxilion/caching/__init__.py +49 -0
- proxilion/caching/tool_cache.py +633 -0
- proxilion/context/__init__.py +73 -0
- proxilion/context/context_window.py +556 -0
- proxilion/context/message_history.py +505 -0
- proxilion/context/session.py +735 -0
- proxilion/contrib/__init__.py +51 -0
- proxilion/contrib/anthropic.py +609 -0
- proxilion/contrib/google.py +1012 -0
- proxilion/contrib/langchain.py +641 -0
- proxilion/contrib/mcp.py +893 -0
- proxilion/contrib/openai.py +646 -0
- proxilion/core.py +3058 -0
- proxilion/decorators.py +966 -0
- proxilion/engines/__init__.py +287 -0
- proxilion/engines/base.py +266 -0
- proxilion/engines/casbin_engine.py +412 -0
- proxilion/engines/opa_engine.py +493 -0
- proxilion/engines/simple.py +437 -0
- proxilion/exceptions.py +887 -0
- proxilion/guards/__init__.py +54 -0
- proxilion/guards/input_guard.py +522 -0
- proxilion/guards/output_guard.py +634 -0
- proxilion/observability/__init__.py +198 -0
- proxilion/observability/cost_tracker.py +866 -0
- proxilion/observability/hooks.py +683 -0
- proxilion/observability/metrics.py +798 -0
- proxilion/observability/session_cost_tracker.py +1063 -0
- proxilion/policies/__init__.py +67 -0
- proxilion/policies/base.py +304 -0
- proxilion/policies/builtin.py +486 -0
- proxilion/policies/registry.py +376 -0
- proxilion/providers/__init__.py +201 -0
- proxilion/providers/adapter.py +468 -0
- proxilion/providers/anthropic_adapter.py +330 -0
- proxilion/providers/gemini_adapter.py +391 -0
- proxilion/providers/openai_adapter.py +294 -0
- proxilion/py.typed +0 -0
- proxilion/resilience/__init__.py +81 -0
- proxilion/resilience/degradation.py +615 -0
- proxilion/resilience/fallback.py +555 -0
- proxilion/resilience/retry.py +554 -0
- proxilion/scheduling/__init__.py +57 -0
- proxilion/scheduling/priority_queue.py +419 -0
- proxilion/scheduling/scheduler.py +459 -0
- proxilion/security/__init__.py +244 -0
- proxilion/security/agent_trust.py +968 -0
- proxilion/security/behavioral_drift.py +794 -0
- proxilion/security/cascade_protection.py +869 -0
- proxilion/security/circuit_breaker.py +428 -0
- proxilion/security/cost_limiter.py +690 -0
- proxilion/security/idor_protection.py +460 -0
- proxilion/security/intent_capsule.py +849 -0
- proxilion/security/intent_validator.py +495 -0
- proxilion/security/memory_integrity.py +767 -0
- proxilion/security/rate_limiter.py +509 -0
- proxilion/security/scope_enforcer.py +680 -0
- proxilion/security/sequence_validator.py +636 -0
- proxilion/security/trust_boundaries.py +784 -0
- proxilion/streaming/__init__.py +70 -0
- proxilion/streaming/detector.py +761 -0
- proxilion/streaming/transformer.py +674 -0
- proxilion/timeouts/__init__.py +55 -0
- proxilion/timeouts/decorators.py +477 -0
- proxilion/timeouts/manager.py +545 -0
- proxilion/tools/__init__.py +69 -0
- proxilion/tools/decorators.py +493 -0
- proxilion/tools/registry.py +732 -0
- proxilion/types.py +339 -0
- proxilion/validation/__init__.py +93 -0
- proxilion/validation/pydantic_schema.py +351 -0
- proxilion/validation/schema.py +651 -0
- proxilion-0.0.1.dist-info/METADATA +872 -0
- proxilion-0.0.1.dist-info/RECORD +94 -0
- proxilion-0.0.1.dist-info/WHEEL +4 -0
- proxilion-0.0.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ISO 27001 compliance exporter.
|
|
3
|
+
|
|
4
|
+
Provides audit log export formats for ISO 27001 compliance,
|
|
5
|
+
mapping to Annex A controls including:
|
|
6
|
+
- A.9: Access Control
|
|
7
|
+
- A.12: Operations Security
|
|
8
|
+
- A.16: Information Security Incident Management
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
>>> from proxilion.audit import InMemoryAuditLogger
|
|
12
|
+
>>> from proxilion.audit.compliance import ISO27001Exporter
|
|
13
|
+
>>> from datetime import datetime, timedelta, timezone
|
|
14
|
+
>>>
|
|
15
|
+
>>> logger = InMemoryAuditLogger()
|
|
16
|
+
>>> # ... log events ...
|
|
17
|
+
>>>
|
|
18
|
+
>>> exporter = ISO27001Exporter(
|
|
19
|
+
... logger,
|
|
20
|
+
... organization="Acme Corp",
|
|
21
|
+
... system_name="Enterprise API",
|
|
22
|
+
... responsible_party="ISMS Manager",
|
|
23
|
+
... )
|
|
24
|
+
>>>
|
|
25
|
+
>>> end = datetime.now(timezone.utc)
|
|
26
|
+
>>> start = end - timedelta(days=365)
|
|
27
|
+
>>>
|
|
28
|
+
>>> # Export access control evidence (A.9)
|
|
29
|
+
>>> access = exporter.export_access_control_a9(start, end)
|
|
30
|
+
>>>
|
|
31
|
+
>>> # Generate full ISO 27001 report
|
|
32
|
+
>>> report = exporter.generate_report(start, end)
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
from __future__ import annotations
|
|
36
|
+
|
|
37
|
+
from dataclasses import dataclass, field
|
|
38
|
+
from datetime import datetime, timezone # noqa: F401 (timezone used in docstring)
|
|
39
|
+
from typing import Any
|
|
40
|
+
|
|
41
|
+
from proxilion.audit.compliance.base import (
|
|
42
|
+
BaseComplianceExporter,
|
|
43
|
+
ComplianceEvidence,
|
|
44
|
+
ComplianceFramework,
|
|
45
|
+
ComplianceReport,
|
|
46
|
+
)
|
|
47
|
+
from proxilion.audit.events import EventType
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class AccessControlA9Evidence:
|
|
52
|
+
"""
|
|
53
|
+
Evidence for A.9 - Access Control.
|
|
54
|
+
|
|
55
|
+
Covers:
|
|
56
|
+
- A.9.1: Business requirements of access control
|
|
57
|
+
- A.9.2: User access management
|
|
58
|
+
- A.9.4: System and application access control
|
|
59
|
+
"""
|
|
60
|
+
user_access_events: list[dict[str, Any]] = field(default_factory=list)
|
|
61
|
+
access_denied_events: list[dict[str, Any]] = field(default_factory=list)
|
|
62
|
+
privileged_access_events: list[dict[str, Any]] = field(default_factory=list)
|
|
63
|
+
unique_users: int = 0
|
|
64
|
+
unique_resources: int = 0
|
|
65
|
+
role_distribution: dict[str, int] = field(default_factory=dict)
|
|
66
|
+
|
|
67
|
+
def to_dict(self) -> dict[str, Any]:
|
|
68
|
+
"""Convert to dictionary."""
|
|
69
|
+
total = len(self.user_access_events)
|
|
70
|
+
denied = len(self.access_denied_events)
|
|
71
|
+
return {
|
|
72
|
+
"user_access_events": self.user_access_events,
|
|
73
|
+
"access_denied_events": self.access_denied_events,
|
|
74
|
+
"privileged_access_events": self.privileged_access_events,
|
|
75
|
+
"summary": {
|
|
76
|
+
"total_access_events": total,
|
|
77
|
+
"access_denied": denied,
|
|
78
|
+
"privileged_access": len(self.privileged_access_events),
|
|
79
|
+
"unique_users": self.unique_users,
|
|
80
|
+
"unique_resources": self.unique_resources,
|
|
81
|
+
"denial_rate": denied / total if total > 0 else 0.0,
|
|
82
|
+
"role_distribution": self.role_distribution,
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class OperationsSecurityA12Evidence:
|
|
89
|
+
"""
|
|
90
|
+
Evidence for A.12 - Operations Security.
|
|
91
|
+
|
|
92
|
+
Covers:
|
|
93
|
+
- A.12.1: Operational procedures and responsibilities
|
|
94
|
+
- A.12.4: Logging and monitoring
|
|
95
|
+
- A.12.6: Technical vulnerability management
|
|
96
|
+
"""
|
|
97
|
+
operational_events: list[dict[str, Any]] = field(default_factory=list)
|
|
98
|
+
logging_events: list[dict[str, Any]] = field(default_factory=list)
|
|
99
|
+
vulnerability_events: list[dict[str, Any]] = field(default_factory=list)
|
|
100
|
+
monitoring_active: bool = True
|
|
101
|
+
|
|
102
|
+
def to_dict(self) -> dict[str, Any]:
|
|
103
|
+
"""Convert to dictionary."""
|
|
104
|
+
return {
|
|
105
|
+
"operational_events": self.operational_events,
|
|
106
|
+
"logging_events": self.logging_events,
|
|
107
|
+
"vulnerability_events": self.vulnerability_events,
|
|
108
|
+
"summary": {
|
|
109
|
+
"total_operations": len(self.operational_events),
|
|
110
|
+
"logging_events": len(self.logging_events),
|
|
111
|
+
"vulnerabilities_detected": len(self.vulnerability_events),
|
|
112
|
+
"monitoring_status": "Active" if self.monitoring_active else "Inactive",
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@dataclass
|
|
118
|
+
class IncidentManagementA16Evidence:
|
|
119
|
+
"""
|
|
120
|
+
Evidence for A.16 - Information Security Incident Management.
|
|
121
|
+
|
|
122
|
+
Covers:
|
|
123
|
+
- A.16.1: Management of security incidents
|
|
124
|
+
"""
|
|
125
|
+
security_incidents: list[dict[str, Any]] = field(default_factory=list)
|
|
126
|
+
incident_responses: list[dict[str, Any]] = field(default_factory=list)
|
|
127
|
+
incident_by_severity: dict[str, int] = field(default_factory=dict)
|
|
128
|
+
|
|
129
|
+
def to_dict(self) -> dict[str, Any]:
|
|
130
|
+
"""Convert to dictionary."""
|
|
131
|
+
return {
|
|
132
|
+
"security_incidents": self.security_incidents,
|
|
133
|
+
"incident_responses": self.incident_responses,
|
|
134
|
+
"summary": {
|
|
135
|
+
"total_incidents": len(self.security_incidents),
|
|
136
|
+
"incidents_responded": len(self.incident_responses),
|
|
137
|
+
"response_rate": (
|
|
138
|
+
len(self.incident_responses) / len(self.security_incidents)
|
|
139
|
+
if self.security_incidents else 1.0
|
|
140
|
+
),
|
|
141
|
+
"by_severity": self.incident_by_severity,
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class ISO27001Exporter(BaseComplianceExporter):
|
|
147
|
+
"""
|
|
148
|
+
Export audit logs for ISO 27001 evidence.
|
|
149
|
+
|
|
150
|
+
Maps to Annex A controls:
|
|
151
|
+
- A.9: Access control
|
|
152
|
+
- A.12: Operations security
|
|
153
|
+
- A.16: Incident management
|
|
154
|
+
|
|
155
|
+
ISO 27001 is an international standard for information security
|
|
156
|
+
management systems (ISMS). This exporter produces evidence
|
|
157
|
+
for key controls related to access, operations, and incidents.
|
|
158
|
+
|
|
159
|
+
Example:
|
|
160
|
+
>>> exporter = ISO27001Exporter(
|
|
161
|
+
... logger,
|
|
162
|
+
... organization="Acme Corp",
|
|
163
|
+
... system_name="Core Platform",
|
|
164
|
+
... responsible_party="isms@acme.com",
|
|
165
|
+
... )
|
|
166
|
+
>>>
|
|
167
|
+
>>> # Export A.9 Access Control evidence
|
|
168
|
+
>>> access = exporter.export_access_control_a9(start, end)
|
|
169
|
+
>>>
|
|
170
|
+
>>> # Export A.12 Operations Security evidence
|
|
171
|
+
>>> ops = exporter.export_operations_security_a12(start, end)
|
|
172
|
+
>>>
|
|
173
|
+
>>> # Export A.16 Incident Management evidence
|
|
174
|
+
>>> incidents = exporter.export_incident_management_a16(start, end)
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def framework(self) -> ComplianceFramework:
|
|
179
|
+
"""Get the compliance framework."""
|
|
180
|
+
return ComplianceFramework.ISO27001
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def framework_version(self) -> str:
|
|
184
|
+
"""Get the framework version."""
|
|
185
|
+
return "2022" # ISO 27001:2022
|
|
186
|
+
|
|
187
|
+
def export_access_control_a9(
|
|
188
|
+
self,
|
|
189
|
+
start: datetime,
|
|
190
|
+
end: datetime,
|
|
191
|
+
) -> AccessControlA9Evidence:
|
|
192
|
+
"""
|
|
193
|
+
Export A.9 - Access Control evidence.
|
|
194
|
+
|
|
195
|
+
A.9 covers:
|
|
196
|
+
- A.9.1.1: Access control policy
|
|
197
|
+
- A.9.2.1: User registration and de-registration
|
|
198
|
+
- A.9.2.2: User access provisioning
|
|
199
|
+
- A.9.2.3: Management of privileged access rights
|
|
200
|
+
- A.9.4.1: Information access restriction
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
start: Start of the reporting period.
|
|
204
|
+
end: End of the reporting period.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
AccessControlA9Evidence with categorized events.
|
|
208
|
+
"""
|
|
209
|
+
events = self.filter_by_date_range(start, end)
|
|
210
|
+
evidence = AccessControlA9Evidence()
|
|
211
|
+
|
|
212
|
+
users = set()
|
|
213
|
+
resources = set()
|
|
214
|
+
role_counts: dict[str, int] = {}
|
|
215
|
+
|
|
216
|
+
for event in events:
|
|
217
|
+
event_dict = self.event_to_evidence_dict(event)
|
|
218
|
+
users.add(event.data.user_id)
|
|
219
|
+
resources.add(event.data.tool_name)
|
|
220
|
+
|
|
221
|
+
# Count roles
|
|
222
|
+
for role in event.data.user_roles:
|
|
223
|
+
role_counts[role] = role_counts.get(role, 0) + 1
|
|
224
|
+
|
|
225
|
+
# All authorization events are access control evidence
|
|
226
|
+
if event.data.event_type in [
|
|
227
|
+
EventType.AUTHORIZATION_GRANTED,
|
|
228
|
+
EventType.AUTHORIZATION_DENIED,
|
|
229
|
+
EventType.AUTHORIZATION_REQUEST,
|
|
230
|
+
]:
|
|
231
|
+
evidence.user_access_events.append({
|
|
232
|
+
**event_dict,
|
|
233
|
+
"control": "A.9.4.1",
|
|
234
|
+
"access_type": "granted" if event.data.authorization_allowed else "denied",
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
# Denied access events
|
|
238
|
+
if event.data.event_type == EventType.AUTHORIZATION_DENIED:
|
|
239
|
+
evidence.access_denied_events.append({
|
|
240
|
+
**event_dict,
|
|
241
|
+
"control": "A.9.4.1",
|
|
242
|
+
"denial_reason": event.data.authorization_reason,
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
# Privileged access (admin roles or high-risk tools)
|
|
246
|
+
is_admin = "admin" in event.data.user_roles
|
|
247
|
+
is_high_risk = event.data.authorization_metadata.get("risk_level") == "high"
|
|
248
|
+
if is_admin or is_high_risk:
|
|
249
|
+
evidence.privileged_access_events.append({
|
|
250
|
+
**event_dict,
|
|
251
|
+
"control": "A.9.2.3",
|
|
252
|
+
"privilege_type": "admin" if is_admin else "high_risk_tool",
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
evidence.unique_users = len(users)
|
|
256
|
+
evidence.unique_resources = len(resources)
|
|
257
|
+
evidence.role_distribution = role_counts
|
|
258
|
+
|
|
259
|
+
return evidence
|
|
260
|
+
|
|
261
|
+
def export_operations_security_a12(
|
|
262
|
+
self,
|
|
263
|
+
start: datetime,
|
|
264
|
+
end: datetime,
|
|
265
|
+
) -> OperationsSecurityA12Evidence:
|
|
266
|
+
"""
|
|
267
|
+
Export A.12 - Operations Security evidence.
|
|
268
|
+
|
|
269
|
+
A.12 covers:
|
|
270
|
+
- A.12.1.1: Documented operating procedures
|
|
271
|
+
- A.12.4.1: Event logging
|
|
272
|
+
- A.12.4.3: Administrator and operator logs
|
|
273
|
+
- A.12.6.1: Management of technical vulnerabilities
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
start: Start of the reporting period.
|
|
277
|
+
end: End of the reporting period.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
OperationsSecurityA12Evidence with categorized events.
|
|
281
|
+
"""
|
|
282
|
+
events = self.filter_by_date_range(start, end)
|
|
283
|
+
evidence = OperationsSecurityA12Evidence()
|
|
284
|
+
|
|
285
|
+
for event in events:
|
|
286
|
+
event_dict = self.event_to_evidence_dict(event)
|
|
287
|
+
|
|
288
|
+
# All events demonstrate logging (A.12.4.1)
|
|
289
|
+
evidence.logging_events.append({
|
|
290
|
+
**event_dict,
|
|
291
|
+
"control": "A.12.4.1",
|
|
292
|
+
"log_type": "authorization",
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
# Operational events (successful executions)
|
|
296
|
+
if event.data.event_type in [
|
|
297
|
+
EventType.TOOL_EXECUTION_SUCCESS,
|
|
298
|
+
EventType.AUTHORIZATION_GRANTED,
|
|
299
|
+
]:
|
|
300
|
+
evidence.operational_events.append({
|
|
301
|
+
**event_dict,
|
|
302
|
+
"control": "A.12.1.1",
|
|
303
|
+
"operation_status": "success",
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
# Vulnerability-related events
|
|
307
|
+
if event.data.event_type in [
|
|
308
|
+
EventType.IDOR_VIOLATION,
|
|
309
|
+
EventType.SCHEMA_VALIDATION_FAILURE,
|
|
310
|
+
]:
|
|
311
|
+
evidence.vulnerability_events.append({
|
|
312
|
+
**event_dict,
|
|
313
|
+
"control": "A.12.6.1",
|
|
314
|
+
"vulnerability_type": event.data.event_type.value,
|
|
315
|
+
"mitigation": "Request blocked by security control",
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
return evidence
|
|
319
|
+
|
|
320
|
+
def export_incident_management_a16(
|
|
321
|
+
self,
|
|
322
|
+
start: datetime,
|
|
323
|
+
end: datetime,
|
|
324
|
+
) -> IncidentManagementA16Evidence:
|
|
325
|
+
"""
|
|
326
|
+
Export A.16 - Incident Management evidence.
|
|
327
|
+
|
|
328
|
+
A.16 covers:
|
|
329
|
+
- A.16.1.1: Responsibilities and procedures
|
|
330
|
+
- A.16.1.2: Reporting information security events
|
|
331
|
+
- A.16.1.4: Assessment of and decision on security events
|
|
332
|
+
- A.16.1.5: Response to security incidents
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
start: Start of the reporting period.
|
|
336
|
+
end: End of the reporting period.
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
IncidentManagementA16Evidence with categorized events.
|
|
340
|
+
"""
|
|
341
|
+
events = self.filter_by_date_range(start, end)
|
|
342
|
+
evidence = IncidentManagementA16Evidence()
|
|
343
|
+
|
|
344
|
+
severity_counts: dict[str, int] = {
|
|
345
|
+
"low": 0,
|
|
346
|
+
"medium": 0,
|
|
347
|
+
"high": 0,
|
|
348
|
+
"critical": 0,
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
for event in events:
|
|
352
|
+
event_dict = self.event_to_evidence_dict(event)
|
|
353
|
+
|
|
354
|
+
# Security incidents
|
|
355
|
+
if event.data.event_type in [
|
|
356
|
+
EventType.RATE_LIMIT_EXCEEDED,
|
|
357
|
+
EventType.CIRCUIT_BREAKER_OPEN,
|
|
358
|
+
EventType.IDOR_VIOLATION,
|
|
359
|
+
EventType.SCHEMA_VALIDATION_FAILURE,
|
|
360
|
+
]:
|
|
361
|
+
# Determine severity
|
|
362
|
+
if event.data.event_type == EventType.IDOR_VIOLATION:
|
|
363
|
+
severity = "critical"
|
|
364
|
+
elif event.data.event_type == EventType.CIRCUIT_BREAKER_OPEN:
|
|
365
|
+
severity = "high"
|
|
366
|
+
elif event.data.event_type == EventType.SCHEMA_VALIDATION_FAILURE:
|
|
367
|
+
severity = "medium"
|
|
368
|
+
else:
|
|
369
|
+
severity = "low"
|
|
370
|
+
|
|
371
|
+
severity_counts[severity] += 1
|
|
372
|
+
|
|
373
|
+
incident = {
|
|
374
|
+
**event_dict,
|
|
375
|
+
"control": "A.16.1.2",
|
|
376
|
+
"incident_type": event.data.event_type.value,
|
|
377
|
+
"severity": severity,
|
|
378
|
+
"reported_at": event.timestamp.isoformat(),
|
|
379
|
+
}
|
|
380
|
+
evidence.security_incidents.append(incident)
|
|
381
|
+
|
|
382
|
+
# All detected incidents have automated response
|
|
383
|
+
evidence.incident_responses.append({
|
|
384
|
+
**incident,
|
|
385
|
+
"control": "A.16.1.5",
|
|
386
|
+
"response_type": "automated_block",
|
|
387
|
+
"response_time_ms": 0, # Immediate
|
|
388
|
+
"resolution": "Request blocked by security control",
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
# Authorization denials are also security events
|
|
392
|
+
if event.data.event_type == EventType.AUTHORIZATION_DENIED:
|
|
393
|
+
severity_counts["low"] += 1
|
|
394
|
+
evidence.security_incidents.append({
|
|
395
|
+
**event_dict,
|
|
396
|
+
"control": "A.16.1.2",
|
|
397
|
+
"incident_type": "access_denied",
|
|
398
|
+
"severity": "low",
|
|
399
|
+
"reported_at": event.timestamp.isoformat(),
|
|
400
|
+
})
|
|
401
|
+
evidence.incident_responses.append({
|
|
402
|
+
**event_dict,
|
|
403
|
+
"control": "A.16.1.5",
|
|
404
|
+
"response_type": "access_blocked",
|
|
405
|
+
"response_time_ms": 0,
|
|
406
|
+
"resolution": event.data.authorization_reason,
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
evidence.incident_by_severity = severity_counts
|
|
410
|
+
|
|
411
|
+
return evidence
|
|
412
|
+
|
|
413
|
+
def generate_report(
|
|
414
|
+
self,
|
|
415
|
+
start: datetime,
|
|
416
|
+
end: datetime,
|
|
417
|
+
) -> ComplianceReport:
|
|
418
|
+
"""
|
|
419
|
+
Generate a complete ISO 27001 compliance report.
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
start: Start of the reporting period.
|
|
423
|
+
end: End of the reporting period.
|
|
424
|
+
|
|
425
|
+
Returns:
|
|
426
|
+
Complete compliance report.
|
|
427
|
+
"""
|
|
428
|
+
metadata = self.create_metadata(start, end)
|
|
429
|
+
evidence_list = []
|
|
430
|
+
recommendations = []
|
|
431
|
+
|
|
432
|
+
# A.9: Access Control
|
|
433
|
+
access = self.export_access_control_a9(start, end)
|
|
434
|
+
access_data = access.to_dict()
|
|
435
|
+
|
|
436
|
+
a9_evidence = ComplianceEvidence(
|
|
437
|
+
control_id="A.9",
|
|
438
|
+
control_name="Access Control",
|
|
439
|
+
evidence_type="access_logs",
|
|
440
|
+
description=(
|
|
441
|
+
"Evidence of access control implementation covering user access "
|
|
442
|
+
"management (A.9.2), system and application access control (A.9.4), "
|
|
443
|
+
"and management of privileged access rights (A.9.2.3)."
|
|
444
|
+
),
|
|
445
|
+
events=access.user_access_events[:50],
|
|
446
|
+
summary=access_data["summary"],
|
|
447
|
+
compliant=len(access.user_access_events) > 0,
|
|
448
|
+
notes=(
|
|
449
|
+
f"Monitoring {access.unique_users} users across "
|
|
450
|
+
f"{access.unique_resources} resources. "
|
|
451
|
+
f"{len(access.privileged_access_events)} privileged access events tracked."
|
|
452
|
+
),
|
|
453
|
+
)
|
|
454
|
+
evidence_list.append(a9_evidence)
|
|
455
|
+
|
|
456
|
+
if access_data["summary"]["denial_rate"] > 0.3:
|
|
457
|
+
recommendations.append(
|
|
458
|
+
"High access denial rate detected. Review access policies and user permissions."
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
# A.12: Operations Security
|
|
462
|
+
ops = self.export_operations_security_a12(start, end)
|
|
463
|
+
ops_data = ops.to_dict()
|
|
464
|
+
|
|
465
|
+
a12_evidence = ComplianceEvidence(
|
|
466
|
+
control_id="A.12",
|
|
467
|
+
control_name="Operations Security",
|
|
468
|
+
evidence_type="operational_logs",
|
|
469
|
+
description=(
|
|
470
|
+
"Evidence of operations security including event logging (A.12.4.1), "
|
|
471
|
+
"operational procedures (A.12.1.1), and technical vulnerability "
|
|
472
|
+
"management (A.12.6.1)."
|
|
473
|
+
),
|
|
474
|
+
events=ops.logging_events[:50],
|
|
475
|
+
summary=ops_data["summary"],
|
|
476
|
+
compliant=ops.monitoring_active,
|
|
477
|
+
notes=(
|
|
478
|
+
f"Logging is active with {len(ops.logging_events)} events recorded. "
|
|
479
|
+
f"{len(ops.vulnerability_events)} potential vulnerabilities detected and mitigated."
|
|
480
|
+
),
|
|
481
|
+
)
|
|
482
|
+
evidence_list.append(a12_evidence)
|
|
483
|
+
|
|
484
|
+
if len(ops.vulnerability_events) > 10:
|
|
485
|
+
recommendations.append(
|
|
486
|
+
"Multiple vulnerability events detected. Conduct a security review "
|
|
487
|
+
"and consider additional input validation controls."
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
# A.16: Incident Management
|
|
491
|
+
incidents = self.export_incident_management_a16(start, end)
|
|
492
|
+
incidents_data = incidents.to_dict()
|
|
493
|
+
|
|
494
|
+
a16_evidence = ComplianceEvidence(
|
|
495
|
+
control_id="A.16",
|
|
496
|
+
control_name="Information Security Incident Management",
|
|
497
|
+
evidence_type="incident_logs",
|
|
498
|
+
description=(
|
|
499
|
+
"Evidence of incident management including security event reporting "
|
|
500
|
+
"(A.16.1.2) and incident response (A.16.1.5)."
|
|
501
|
+
),
|
|
502
|
+
events=incidents.security_incidents[:50],
|
|
503
|
+
summary=incidents_data["summary"],
|
|
504
|
+
compliant=incidents_data["summary"]["response_rate"] >= 0.95,
|
|
505
|
+
notes=(
|
|
506
|
+
f"{len(incidents.security_incidents)} security events detected. "
|
|
507
|
+
f"Response rate: {incidents_data['summary']['response_rate']:.1%}. "
|
|
508
|
+
f"By severity: {incidents.incident_by_severity}"
|
|
509
|
+
),
|
|
510
|
+
)
|
|
511
|
+
evidence_list.append(a16_evidence)
|
|
512
|
+
|
|
513
|
+
if incidents.incident_by_severity.get("critical", 0) > 0:
|
|
514
|
+
recommendations.append(
|
|
515
|
+
f"Critical incidents detected ({incidents.incident_by_severity['critical']}). "
|
|
516
|
+
"Review root causes and implement preventive controls."
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
# Overall summary
|
|
520
|
+
all_events = self.filter_by_date_range(start, end)
|
|
521
|
+
stats = self.compute_summary_stats(all_events)
|
|
522
|
+
|
|
523
|
+
summary = {
|
|
524
|
+
"reporting_period": f"{start.date()} to {end.date()}",
|
|
525
|
+
"framework_version": "ISO 27001:2022",
|
|
526
|
+
"total_events_analyzed": stats["total_events"],
|
|
527
|
+
"unique_users": stats["unique_users"],
|
|
528
|
+
"unique_resources": stats["unique_tools"],
|
|
529
|
+
"controls_assessed": 3,
|
|
530
|
+
"controls_compliant": sum(1 for e in evidence_list if e.compliant),
|
|
531
|
+
"security_incidents": len(incidents.security_incidents),
|
|
532
|
+
"incident_response_rate": f"{incidents_data['summary']['response_rate']:.1%}",
|
|
533
|
+
"privileged_access_events": len(access.privileged_access_events),
|
|
534
|
+
"overall_status": (
|
|
535
|
+
"Compliant" if all(e.compliant for e in evidence_list) else "Review Required"
|
|
536
|
+
),
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return ComplianceReport(
|
|
540
|
+
metadata=metadata,
|
|
541
|
+
evidence=evidence_list,
|
|
542
|
+
summary=summary,
|
|
543
|
+
recommendations=recommendations,
|
|
544
|
+
)
|