aiptx 2.0.7__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.
- aipt_v2/__init__.py +110 -0
- aipt_v2/__main__.py +24 -0
- aipt_v2/agents/AIPTxAgent/__init__.py +10 -0
- aipt_v2/agents/AIPTxAgent/aiptx_agent.py +211 -0
- aipt_v2/agents/__init__.py +46 -0
- aipt_v2/agents/base.py +520 -0
- aipt_v2/agents/exploit_agent.py +688 -0
- aipt_v2/agents/ptt.py +406 -0
- aipt_v2/agents/state.py +168 -0
- aipt_v2/app.py +957 -0
- aipt_v2/browser/__init__.py +31 -0
- aipt_v2/browser/automation.py +458 -0
- aipt_v2/browser/crawler.py +453 -0
- aipt_v2/cli.py +2933 -0
- aipt_v2/compliance/__init__.py +71 -0
- aipt_v2/compliance/compliance_report.py +449 -0
- aipt_v2/compliance/framework_mapper.py +424 -0
- aipt_v2/compliance/nist_mapping.py +345 -0
- aipt_v2/compliance/owasp_mapping.py +330 -0
- aipt_v2/compliance/pci_mapping.py +297 -0
- aipt_v2/config.py +341 -0
- aipt_v2/core/__init__.py +43 -0
- aipt_v2/core/agent.py +630 -0
- aipt_v2/core/llm.py +395 -0
- aipt_v2/core/memory.py +305 -0
- aipt_v2/core/ptt.py +329 -0
- aipt_v2/database/__init__.py +14 -0
- aipt_v2/database/models.py +232 -0
- aipt_v2/database/repository.py +384 -0
- aipt_v2/docker/__init__.py +23 -0
- aipt_v2/docker/builder.py +260 -0
- aipt_v2/docker/manager.py +222 -0
- aipt_v2/docker/sandbox.py +371 -0
- aipt_v2/evasion/__init__.py +58 -0
- aipt_v2/evasion/request_obfuscator.py +272 -0
- aipt_v2/evasion/tls_fingerprint.py +285 -0
- aipt_v2/evasion/ua_rotator.py +301 -0
- aipt_v2/evasion/waf_bypass.py +439 -0
- aipt_v2/execution/__init__.py +23 -0
- aipt_v2/execution/executor.py +302 -0
- aipt_v2/execution/parser.py +544 -0
- aipt_v2/execution/terminal.py +337 -0
- aipt_v2/health.py +437 -0
- aipt_v2/intelligence/__init__.py +194 -0
- aipt_v2/intelligence/adaptation.py +474 -0
- aipt_v2/intelligence/auth.py +520 -0
- aipt_v2/intelligence/chaining.py +775 -0
- aipt_v2/intelligence/correlation.py +536 -0
- aipt_v2/intelligence/cve_aipt.py +334 -0
- aipt_v2/intelligence/cve_info.py +1111 -0
- aipt_v2/intelligence/knowledge_graph.py +590 -0
- aipt_v2/intelligence/learning.py +626 -0
- aipt_v2/intelligence/llm_analyzer.py +502 -0
- aipt_v2/intelligence/llm_tool_selector.py +518 -0
- aipt_v2/intelligence/payload_generator.py +562 -0
- aipt_v2/intelligence/rag.py +239 -0
- aipt_v2/intelligence/scope.py +442 -0
- aipt_v2/intelligence/searchers/__init__.py +5 -0
- aipt_v2/intelligence/searchers/exploitdb_searcher.py +523 -0
- aipt_v2/intelligence/searchers/github_searcher.py +467 -0
- aipt_v2/intelligence/searchers/google_searcher.py +281 -0
- aipt_v2/intelligence/tools.json +443 -0
- aipt_v2/intelligence/triage.py +670 -0
- aipt_v2/interactive_shell.py +559 -0
- aipt_v2/interface/__init__.py +5 -0
- aipt_v2/interface/cli.py +230 -0
- aipt_v2/interface/main.py +501 -0
- aipt_v2/interface/tui.py +1276 -0
- aipt_v2/interface/utils.py +583 -0
- aipt_v2/llm/__init__.py +39 -0
- aipt_v2/llm/config.py +26 -0
- aipt_v2/llm/llm.py +514 -0
- aipt_v2/llm/memory.py +214 -0
- aipt_v2/llm/request_queue.py +89 -0
- aipt_v2/llm/utils.py +89 -0
- aipt_v2/local_tool_installer.py +1467 -0
- aipt_v2/models/__init__.py +15 -0
- aipt_v2/models/findings.py +295 -0
- aipt_v2/models/phase_result.py +224 -0
- aipt_v2/models/scan_config.py +207 -0
- aipt_v2/monitoring/grafana/dashboards/aipt-dashboard.json +355 -0
- aipt_v2/monitoring/grafana/dashboards/default.yml +17 -0
- aipt_v2/monitoring/grafana/datasources/prometheus.yml +17 -0
- aipt_v2/monitoring/prometheus.yml +60 -0
- aipt_v2/orchestration/__init__.py +52 -0
- aipt_v2/orchestration/pipeline.py +398 -0
- aipt_v2/orchestration/progress.py +300 -0
- aipt_v2/orchestration/scheduler.py +296 -0
- aipt_v2/orchestrator.py +2427 -0
- aipt_v2/payloads/__init__.py +27 -0
- aipt_v2/payloads/cmdi.py +150 -0
- aipt_v2/payloads/sqli.py +263 -0
- aipt_v2/payloads/ssrf.py +204 -0
- aipt_v2/payloads/templates.py +222 -0
- aipt_v2/payloads/traversal.py +166 -0
- aipt_v2/payloads/xss.py +204 -0
- aipt_v2/prompts/__init__.py +60 -0
- aipt_v2/proxy/__init__.py +29 -0
- aipt_v2/proxy/history.py +352 -0
- aipt_v2/proxy/interceptor.py +452 -0
- aipt_v2/recon/__init__.py +44 -0
- aipt_v2/recon/dns.py +241 -0
- aipt_v2/recon/osint.py +367 -0
- aipt_v2/recon/subdomain.py +372 -0
- aipt_v2/recon/tech_detect.py +311 -0
- aipt_v2/reports/__init__.py +17 -0
- aipt_v2/reports/generator.py +313 -0
- aipt_v2/reports/html_report.py +378 -0
- aipt_v2/runtime/__init__.py +53 -0
- aipt_v2/runtime/base.py +30 -0
- aipt_v2/runtime/docker.py +401 -0
- aipt_v2/runtime/local.py +346 -0
- aipt_v2/runtime/tool_server.py +205 -0
- aipt_v2/runtime/vps.py +830 -0
- aipt_v2/scanners/__init__.py +28 -0
- aipt_v2/scanners/base.py +273 -0
- aipt_v2/scanners/nikto.py +244 -0
- aipt_v2/scanners/nmap.py +402 -0
- aipt_v2/scanners/nuclei.py +273 -0
- aipt_v2/scanners/web.py +454 -0
- aipt_v2/scripts/security_audit.py +366 -0
- aipt_v2/setup_wizard.py +941 -0
- aipt_v2/skills/__init__.py +80 -0
- aipt_v2/skills/agents/__init__.py +14 -0
- aipt_v2/skills/agents/api_tester.py +706 -0
- aipt_v2/skills/agents/base.py +477 -0
- aipt_v2/skills/agents/code_review.py +459 -0
- aipt_v2/skills/agents/security_agent.py +336 -0
- aipt_v2/skills/agents/web_pentest.py +818 -0
- aipt_v2/skills/prompts/__init__.py +647 -0
- aipt_v2/system_detector.py +539 -0
- aipt_v2/telemetry/__init__.py +7 -0
- aipt_v2/telemetry/tracer.py +347 -0
- aipt_v2/terminal/__init__.py +28 -0
- aipt_v2/terminal/executor.py +400 -0
- aipt_v2/terminal/sandbox.py +350 -0
- aipt_v2/tools/__init__.py +44 -0
- aipt_v2/tools/active_directory/__init__.py +78 -0
- aipt_v2/tools/active_directory/ad_config.py +238 -0
- aipt_v2/tools/active_directory/bloodhound_wrapper.py +447 -0
- aipt_v2/tools/active_directory/kerberos_attacks.py +430 -0
- aipt_v2/tools/active_directory/ldap_enum.py +533 -0
- aipt_v2/tools/active_directory/smb_attacks.py +505 -0
- aipt_v2/tools/agents_graph/__init__.py +19 -0
- aipt_v2/tools/agents_graph/agents_graph_actions.py +69 -0
- aipt_v2/tools/api_security/__init__.py +76 -0
- aipt_v2/tools/api_security/api_discovery.py +608 -0
- aipt_v2/tools/api_security/graphql_scanner.py +622 -0
- aipt_v2/tools/api_security/jwt_analyzer.py +577 -0
- aipt_v2/tools/api_security/openapi_fuzzer.py +761 -0
- aipt_v2/tools/browser/__init__.py +5 -0
- aipt_v2/tools/browser/browser_actions.py +238 -0
- aipt_v2/tools/browser/browser_instance.py +535 -0
- aipt_v2/tools/browser/tab_manager.py +344 -0
- aipt_v2/tools/cloud/__init__.py +70 -0
- aipt_v2/tools/cloud/cloud_config.py +273 -0
- aipt_v2/tools/cloud/cloud_scanner.py +639 -0
- aipt_v2/tools/cloud/prowler_tool.py +571 -0
- aipt_v2/tools/cloud/scoutsuite_tool.py +359 -0
- aipt_v2/tools/executor.py +307 -0
- aipt_v2/tools/parser.py +408 -0
- aipt_v2/tools/proxy/__init__.py +5 -0
- aipt_v2/tools/proxy/proxy_actions.py +103 -0
- aipt_v2/tools/proxy/proxy_manager.py +789 -0
- aipt_v2/tools/registry.py +196 -0
- aipt_v2/tools/scanners/__init__.py +343 -0
- aipt_v2/tools/scanners/acunetix_tool.py +712 -0
- aipt_v2/tools/scanners/burp_tool.py +631 -0
- aipt_v2/tools/scanners/config.py +156 -0
- aipt_v2/tools/scanners/nessus_tool.py +588 -0
- aipt_v2/tools/scanners/zap_tool.py +612 -0
- aipt_v2/tools/terminal/__init__.py +5 -0
- aipt_v2/tools/terminal/terminal_actions.py +37 -0
- aipt_v2/tools/terminal/terminal_manager.py +153 -0
- aipt_v2/tools/terminal/terminal_session.py +449 -0
- aipt_v2/tools/tool_processing.py +108 -0
- aipt_v2/utils/__init__.py +17 -0
- aipt_v2/utils/logging.py +202 -0
- aipt_v2/utils/model_manager.py +187 -0
- aipt_v2/utils/searchers/__init__.py +269 -0
- aipt_v2/verify_install.py +793 -0
- aiptx-2.0.7.dist-info/METADATA +345 -0
- aiptx-2.0.7.dist-info/RECORD +187 -0
- aiptx-2.0.7.dist-info/WHEEL +5 -0
- aiptx-2.0.7.dist-info/entry_points.txt +7 -0
- aiptx-2.0.7.dist-info/licenses/LICENSE +21 -0
- aiptx-2.0.7.dist-info/top_level.txt +1 -0
aipt_v2/health.py
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AIPT v2 Health Checks & Metrics Module
|
|
3
|
+
=======================================
|
|
4
|
+
|
|
5
|
+
Provides:
|
|
6
|
+
- /health - Basic liveness probe
|
|
7
|
+
- /health/live - Kubernetes liveness probe
|
|
8
|
+
- /health/ready - Kubernetes readiness probe (checks dependencies)
|
|
9
|
+
- /metrics - Prometheus-compatible metrics
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
from health import health_router
|
|
13
|
+
app.include_router(health_router)
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import time
|
|
18
|
+
import psutil
|
|
19
|
+
from datetime import datetime, timezone
|
|
20
|
+
from typing import Dict, Any, Optional
|
|
21
|
+
from functools import lru_cache
|
|
22
|
+
|
|
23
|
+
from fastapi import APIRouter, Response
|
|
24
|
+
from pydantic import BaseModel
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# =============================================================================
|
|
28
|
+
# Configuration
|
|
29
|
+
# =============================================================================
|
|
30
|
+
|
|
31
|
+
VERSION = os.getenv("AIPT_VERSION", "2.0.0")
|
|
32
|
+
ENVIRONMENT = os.getenv("AIPT_ENVIRONMENT", "development")
|
|
33
|
+
START_TIME = time.time()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# =============================================================================
|
|
37
|
+
# Pydantic Models
|
|
38
|
+
# =============================================================================
|
|
39
|
+
|
|
40
|
+
class HealthStatus(BaseModel):
|
|
41
|
+
"""Health check response model."""
|
|
42
|
+
status: str
|
|
43
|
+
version: str
|
|
44
|
+
timestamp: str
|
|
45
|
+
uptime_seconds: float
|
|
46
|
+
environment: str
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class ReadinessStatus(BaseModel):
|
|
50
|
+
"""Readiness check response model."""
|
|
51
|
+
status: str
|
|
52
|
+
version: str
|
|
53
|
+
timestamp: str
|
|
54
|
+
checks: Dict[str, Dict[str, Any]]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class ComponentCheck(BaseModel):
|
|
58
|
+
"""Individual component check result."""
|
|
59
|
+
status: str
|
|
60
|
+
latency_ms: Optional[float] = None
|
|
61
|
+
message: Optional[str] = None
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# =============================================================================
|
|
65
|
+
# Metrics Storage (Simple in-memory counters)
|
|
66
|
+
# =============================================================================
|
|
67
|
+
|
|
68
|
+
class MetricsCollector:
|
|
69
|
+
"""Simple metrics collector for Prometheus-style metrics."""
|
|
70
|
+
|
|
71
|
+
def __init__(self):
|
|
72
|
+
self.counters: Dict[str, int] = {}
|
|
73
|
+
self.gauges: Dict[str, float] = {}
|
|
74
|
+
self.histograms: Dict[str, list] = {}
|
|
75
|
+
|
|
76
|
+
# Initialize default metrics
|
|
77
|
+
self.counters["http_requests_total"] = 0
|
|
78
|
+
self.counters["scan_requests_total"] = 0
|
|
79
|
+
self.counters["tool_invocations_total"] = 0
|
|
80
|
+
self.counters["errors_total"] = 0
|
|
81
|
+
self.gauges["active_scans"] = 0
|
|
82
|
+
self.gauges["active_sessions"] = 0
|
|
83
|
+
|
|
84
|
+
def increment(self, name: str, value: int = 1, labels: Dict[str, str] = None):
|
|
85
|
+
"""Increment a counter."""
|
|
86
|
+
key = self._make_key(name, labels)
|
|
87
|
+
self.counters[key] = self.counters.get(key, 0) + value
|
|
88
|
+
|
|
89
|
+
def set_gauge(self, name: str, value: float, labels: Dict[str, str] = None):
|
|
90
|
+
"""Set a gauge value."""
|
|
91
|
+
key = self._make_key(name, labels)
|
|
92
|
+
self.gauges[key] = value
|
|
93
|
+
|
|
94
|
+
def observe(self, name: str, value: float, labels: Dict[str, str] = None):
|
|
95
|
+
"""Record a histogram observation."""
|
|
96
|
+
key = self._make_key(name, labels)
|
|
97
|
+
if key not in self.histograms:
|
|
98
|
+
self.histograms[key] = []
|
|
99
|
+
self.histograms[key].append(value)
|
|
100
|
+
|
|
101
|
+
def _make_key(self, name: str, labels: Dict[str, str] = None) -> str:
|
|
102
|
+
"""Create a metric key with labels."""
|
|
103
|
+
if not labels:
|
|
104
|
+
return name
|
|
105
|
+
label_str = ",".join(f'{k}="{v}"' for k, v in sorted(labels.items()))
|
|
106
|
+
return f"{name}{{{label_str}}}"
|
|
107
|
+
|
|
108
|
+
def to_prometheus(self) -> str:
|
|
109
|
+
"""Export metrics in Prometheus text format."""
|
|
110
|
+
lines = [
|
|
111
|
+
"# HELP aipt_http_requests_total Total HTTP requests",
|
|
112
|
+
"# TYPE aipt_http_requests_total counter",
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
# Export counters
|
|
116
|
+
for key, value in self.counters.items():
|
|
117
|
+
lines.append(f"aipt_{key} {value}")
|
|
118
|
+
|
|
119
|
+
lines.extend([
|
|
120
|
+
"",
|
|
121
|
+
"# HELP aipt_active_scans Number of active scans",
|
|
122
|
+
"# TYPE aipt_active_scans gauge",
|
|
123
|
+
])
|
|
124
|
+
|
|
125
|
+
# Export gauges
|
|
126
|
+
for key, value in self.gauges.items():
|
|
127
|
+
lines.append(f"aipt_{key} {value}")
|
|
128
|
+
|
|
129
|
+
# Add process metrics
|
|
130
|
+
try:
|
|
131
|
+
process = psutil.Process()
|
|
132
|
+
memory_info = process.memory_info()
|
|
133
|
+
|
|
134
|
+
lines.extend([
|
|
135
|
+
"",
|
|
136
|
+
"# HELP process_resident_memory_bytes Resident memory size in bytes",
|
|
137
|
+
"# TYPE process_resident_memory_bytes gauge",
|
|
138
|
+
f"process_resident_memory_bytes {memory_info.rss}",
|
|
139
|
+
"",
|
|
140
|
+
"# HELP process_virtual_memory_bytes Virtual memory size in bytes",
|
|
141
|
+
"# TYPE process_virtual_memory_bytes gauge",
|
|
142
|
+
f"process_virtual_memory_bytes {memory_info.vms}",
|
|
143
|
+
"",
|
|
144
|
+
"# HELP process_cpu_percent CPU percent usage",
|
|
145
|
+
"# TYPE process_cpu_percent gauge",
|
|
146
|
+
f"process_cpu_percent {process.cpu_percent()}",
|
|
147
|
+
"",
|
|
148
|
+
"# HELP process_open_fds Number of open file descriptors",
|
|
149
|
+
"# TYPE process_open_fds gauge",
|
|
150
|
+
f"process_open_fds {process.num_fds() if hasattr(process, 'num_fds') else 0}",
|
|
151
|
+
])
|
|
152
|
+
except Exception:
|
|
153
|
+
pass # Skip process metrics if unavailable
|
|
154
|
+
|
|
155
|
+
# Add uptime
|
|
156
|
+
lines.extend([
|
|
157
|
+
"",
|
|
158
|
+
"# HELP aipt_uptime_seconds Time since service started",
|
|
159
|
+
"# TYPE aipt_uptime_seconds gauge",
|
|
160
|
+
f"aipt_uptime_seconds {time.time() - START_TIME}",
|
|
161
|
+
])
|
|
162
|
+
|
|
163
|
+
return "\n".join(lines) + "\n"
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# Global metrics collector
|
|
167
|
+
metrics = MetricsCollector()
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
# =============================================================================
|
|
171
|
+
# Health Check Functions
|
|
172
|
+
# =============================================================================
|
|
173
|
+
|
|
174
|
+
def check_database() -> ComponentCheck:
|
|
175
|
+
"""Check database connectivity."""
|
|
176
|
+
start = time.time()
|
|
177
|
+
try:
|
|
178
|
+
# Try to import and use the repository
|
|
179
|
+
from database.repository import Repository
|
|
180
|
+
repo = Repository()
|
|
181
|
+
# Simple query to verify connection
|
|
182
|
+
repo.list_projects(status=None)
|
|
183
|
+
latency = (time.time() - start) * 1000
|
|
184
|
+
return ComponentCheck(status="healthy", latency_ms=round(latency, 2))
|
|
185
|
+
except Exception as e:
|
|
186
|
+
latency = (time.time() - start) * 1000
|
|
187
|
+
return ComponentCheck(
|
|
188
|
+
status="unhealthy",
|
|
189
|
+
latency_ms=round(latency, 2),
|
|
190
|
+
message=str(e)[:100]
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def check_redis() -> ComponentCheck:
|
|
195
|
+
"""Check Redis connectivity (if configured)."""
|
|
196
|
+
redis_url = os.getenv("REDIS_URL")
|
|
197
|
+
if not redis_url:
|
|
198
|
+
return ComponentCheck(status="skipped", message="REDIS_URL not configured")
|
|
199
|
+
|
|
200
|
+
start = time.time()
|
|
201
|
+
try:
|
|
202
|
+
import redis
|
|
203
|
+
client = redis.from_url(redis_url)
|
|
204
|
+
client.ping()
|
|
205
|
+
latency = (time.time() - start) * 1000
|
|
206
|
+
return ComponentCheck(status="healthy", latency_ms=round(latency, 2))
|
|
207
|
+
except ImportError:
|
|
208
|
+
return ComponentCheck(status="skipped", message="redis package not installed")
|
|
209
|
+
except Exception as e:
|
|
210
|
+
latency = (time.time() - start) * 1000
|
|
211
|
+
return ComponentCheck(
|
|
212
|
+
status="unhealthy",
|
|
213
|
+
latency_ms=round(latency, 2),
|
|
214
|
+
message=str(e)[:100]
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def check_llm_api() -> ComponentCheck:
|
|
219
|
+
"""Check LLM API key configuration."""
|
|
220
|
+
anthropic_key = os.getenv("ANTHROPIC_API_KEY")
|
|
221
|
+
openai_key = os.getenv("OPENAI_API_KEY")
|
|
222
|
+
llm_key = os.getenv("LLM_API_KEY")
|
|
223
|
+
|
|
224
|
+
if anthropic_key or openai_key or llm_key:
|
|
225
|
+
return ComponentCheck(status="healthy", message="API key configured")
|
|
226
|
+
return ComponentCheck(status="warning", message="No LLM API key configured")
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def check_disk_space() -> ComponentCheck:
|
|
230
|
+
"""Check available disk space."""
|
|
231
|
+
try:
|
|
232
|
+
disk = psutil.disk_usage("/")
|
|
233
|
+
free_percent = (disk.free / disk.total) * 100
|
|
234
|
+
|
|
235
|
+
if free_percent < 5:
|
|
236
|
+
return ComponentCheck(
|
|
237
|
+
status="unhealthy",
|
|
238
|
+
message=f"Low disk space: {free_percent:.1f}% free"
|
|
239
|
+
)
|
|
240
|
+
elif free_percent < 15:
|
|
241
|
+
return ComponentCheck(
|
|
242
|
+
status="warning",
|
|
243
|
+
message=f"Disk space warning: {free_percent:.1f}% free"
|
|
244
|
+
)
|
|
245
|
+
return ComponentCheck(
|
|
246
|
+
status="healthy",
|
|
247
|
+
message=f"{free_percent:.1f}% free"
|
|
248
|
+
)
|
|
249
|
+
except Exception as e:
|
|
250
|
+
return ComponentCheck(status="unknown", message=str(e)[:100])
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def check_memory() -> ComponentCheck:
|
|
254
|
+
"""Check memory usage."""
|
|
255
|
+
try:
|
|
256
|
+
memory = psutil.virtual_memory()
|
|
257
|
+
used_percent = memory.percent
|
|
258
|
+
|
|
259
|
+
if used_percent > 95:
|
|
260
|
+
return ComponentCheck(
|
|
261
|
+
status="unhealthy",
|
|
262
|
+
message=f"Critical memory usage: {used_percent:.1f}%"
|
|
263
|
+
)
|
|
264
|
+
elif used_percent > 85:
|
|
265
|
+
return ComponentCheck(
|
|
266
|
+
status="warning",
|
|
267
|
+
message=f"High memory usage: {used_percent:.1f}%"
|
|
268
|
+
)
|
|
269
|
+
return ComponentCheck(
|
|
270
|
+
status="healthy",
|
|
271
|
+
message=f"{used_percent:.1f}% used"
|
|
272
|
+
)
|
|
273
|
+
except Exception as e:
|
|
274
|
+
return ComponentCheck(status="unknown", message=str(e)[:100])
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
# =============================================================================
|
|
278
|
+
# Router
|
|
279
|
+
# =============================================================================
|
|
280
|
+
|
|
281
|
+
health_router = APIRouter(tags=["Health"])
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
@health_router.get("/health", response_model=HealthStatus)
|
|
285
|
+
async def health_check():
|
|
286
|
+
"""
|
|
287
|
+
Basic health check endpoint (liveness probe).
|
|
288
|
+
|
|
289
|
+
Returns HTTP 200 if the service is running.
|
|
290
|
+
Use /health/ready for dependency checks.
|
|
291
|
+
"""
|
|
292
|
+
metrics.increment("http_requests_total", labels={"endpoint": "health"})
|
|
293
|
+
|
|
294
|
+
return HealthStatus(
|
|
295
|
+
status="healthy",
|
|
296
|
+
version=VERSION,
|
|
297
|
+
timestamp=datetime.now(timezone.utc).isoformat() + "Z",
|
|
298
|
+
uptime_seconds=round(time.time() - START_TIME, 2),
|
|
299
|
+
environment=ENVIRONMENT,
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
@health_router.get("/health/live")
|
|
304
|
+
async def liveness_probe():
|
|
305
|
+
"""
|
|
306
|
+
Kubernetes liveness probe.
|
|
307
|
+
|
|
308
|
+
Returns HTTP 200 if the process is alive.
|
|
309
|
+
Kubernetes will restart the pod if this fails.
|
|
310
|
+
"""
|
|
311
|
+
return {"status": "alive"}
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
@health_router.get("/health/ready", response_model=ReadinessStatus)
|
|
315
|
+
async def readiness_probe():
|
|
316
|
+
"""
|
|
317
|
+
Kubernetes readiness probe.
|
|
318
|
+
|
|
319
|
+
Checks all dependencies and returns their status.
|
|
320
|
+
Returns HTTP 503 if any critical dependency is unhealthy.
|
|
321
|
+
"""
|
|
322
|
+
metrics.increment("http_requests_total", labels={"endpoint": "health_ready"})
|
|
323
|
+
|
|
324
|
+
checks = {
|
|
325
|
+
"database": check_database().model_dump(),
|
|
326
|
+
"redis": check_redis().model_dump(),
|
|
327
|
+
"llm_api": check_llm_api().model_dump(),
|
|
328
|
+
"disk": check_disk_space().model_dump(),
|
|
329
|
+
"memory": check_memory().model_dump(),
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
# Determine overall status
|
|
333
|
+
statuses = [c["status"] for c in checks.values()]
|
|
334
|
+
if "unhealthy" in statuses:
|
|
335
|
+
overall_status = "unhealthy"
|
|
336
|
+
elif "warning" in statuses:
|
|
337
|
+
overall_status = "degraded"
|
|
338
|
+
else:
|
|
339
|
+
overall_status = "healthy"
|
|
340
|
+
|
|
341
|
+
response = ReadinessStatus(
|
|
342
|
+
status=overall_status,
|
|
343
|
+
version=VERSION,
|
|
344
|
+
timestamp=datetime.now(timezone.utc).isoformat() + "Z",
|
|
345
|
+
checks=checks,
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
# Return 503 if unhealthy
|
|
349
|
+
if overall_status == "unhealthy":
|
|
350
|
+
from fastapi import HTTPException
|
|
351
|
+
raise HTTPException(status_code=503, detail=response.model_dump())
|
|
352
|
+
|
|
353
|
+
return response
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
@health_router.get("/metrics")
|
|
357
|
+
async def prometheus_metrics():
|
|
358
|
+
"""
|
|
359
|
+
Prometheus-compatible metrics endpoint.
|
|
360
|
+
|
|
361
|
+
Returns metrics in Prometheus text exposition format.
|
|
362
|
+
"""
|
|
363
|
+
content = metrics.to_prometheus()
|
|
364
|
+
return Response(
|
|
365
|
+
content=content,
|
|
366
|
+
media_type="text/plain; charset=utf-8"
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
@health_router.get("/health/info")
|
|
371
|
+
async def service_info():
|
|
372
|
+
"""
|
|
373
|
+
Detailed service information.
|
|
374
|
+
|
|
375
|
+
Returns version, build info, and configuration summary.
|
|
376
|
+
"""
|
|
377
|
+
return {
|
|
378
|
+
"service": "aipt-v2",
|
|
379
|
+
"version": VERSION,
|
|
380
|
+
"environment": ENVIRONMENT,
|
|
381
|
+
"python_version": os.popen("python --version 2>&1").read().strip(),
|
|
382
|
+
"uptime_seconds": round(time.time() - START_TIME, 2),
|
|
383
|
+
"config": {
|
|
384
|
+
"log_level": os.getenv("AIPT_LOG_LEVEL", "INFO"),
|
|
385
|
+
"cors_origins": os.getenv("AIPT_CORS_ORIGINS", "localhost"),
|
|
386
|
+
"database_configured": bool(os.getenv("DATABASE_URL")),
|
|
387
|
+
"redis_configured": bool(os.getenv("REDIS_URL")),
|
|
388
|
+
"llm_configured": bool(
|
|
389
|
+
os.getenv("ANTHROPIC_API_KEY") or
|
|
390
|
+
os.getenv("OPENAI_API_KEY") or
|
|
391
|
+
os.getenv("LLM_API_KEY")
|
|
392
|
+
),
|
|
393
|
+
},
|
|
394
|
+
"timestamp": datetime.now(timezone.utc).isoformat() + "Z",
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
# =============================================================================
|
|
399
|
+
# Utility Functions (for use in middleware)
|
|
400
|
+
# =============================================================================
|
|
401
|
+
|
|
402
|
+
def record_request(method: str, path: str, status_code: int, duration_ms: float):
|
|
403
|
+
"""Record an HTTP request for metrics."""
|
|
404
|
+
metrics.increment("http_requests_total", labels={
|
|
405
|
+
"method": method,
|
|
406
|
+
"path": path,
|
|
407
|
+
"status": str(status_code),
|
|
408
|
+
})
|
|
409
|
+
metrics.observe("http_request_duration_ms", duration_ms, labels={
|
|
410
|
+
"method": method,
|
|
411
|
+
"path": path,
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
def record_scan(scan_type: str):
|
|
416
|
+
"""Record a scan request."""
|
|
417
|
+
metrics.increment("scan_requests_total", labels={"type": scan_type})
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
def record_tool_invocation(tool_name: str):
|
|
421
|
+
"""Record a tool invocation."""
|
|
422
|
+
metrics.increment("tool_invocations_total", labels={"tool": tool_name})
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def record_error(error_type: str):
|
|
426
|
+
"""Record an error."""
|
|
427
|
+
metrics.increment("errors_total", labels={"type": error_type})
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def set_active_scans(count: int):
|
|
431
|
+
"""Set the number of active scans."""
|
|
432
|
+
metrics.set_gauge("active_scans", count)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def set_active_sessions(count: int):
|
|
436
|
+
"""Set the number of active sessions."""
|
|
437
|
+
metrics.set_gauge("active_sessions", count)
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AIPT Intelligence Module
|
|
3
|
+
|
|
4
|
+
Advanced analysis capabilities for penetration testing:
|
|
5
|
+
- CVE prioritization and RAG-based tool selection
|
|
6
|
+
- Vulnerability chaining (connect related findings into attack paths)
|
|
7
|
+
- AI-powered triage (prioritize findings by real-world impact)
|
|
8
|
+
- Scope enforcement (ensure testing stays within authorization)
|
|
9
|
+
- Authenticated scanning (test protected resources)
|
|
10
|
+
- LLM-powered tool selection and vulnerability analysis
|
|
11
|
+
- Feedback learning from exploitation attempts
|
|
12
|
+
- Adaptive payload generation
|
|
13
|
+
- Knowledge graph for findings
|
|
14
|
+
- Real-time adaptation to defenses
|
|
15
|
+
- Cross-target correlation
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from aipt_v2.intelligence.cve_aipt import CVEIntelligence, CVEInfo
|
|
19
|
+
from aipt_v2.intelligence.rag import ToolRAG, ToolMatch
|
|
20
|
+
|
|
21
|
+
# Vulnerability Chaining - Connect related findings into attack paths
|
|
22
|
+
from aipt_v2.intelligence.chaining import (
|
|
23
|
+
VulnerabilityChainer,
|
|
24
|
+
AttackChain,
|
|
25
|
+
ChainLink,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# AI-Powered Triage - Prioritize by real-world impact
|
|
29
|
+
from aipt_v2.intelligence.triage import (
|
|
30
|
+
AITriage,
|
|
31
|
+
TriageResult,
|
|
32
|
+
RiskAssessment,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Scope Enforcement - Stay within authorization
|
|
36
|
+
from aipt_v2.intelligence.scope import (
|
|
37
|
+
ScopeEnforcer,
|
|
38
|
+
ScopeConfig,
|
|
39
|
+
ScopeViolation,
|
|
40
|
+
ScopeDecision,
|
|
41
|
+
create_scope_from_target,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Authentication - Test protected resources
|
|
45
|
+
from aipt_v2.intelligence.auth import (
|
|
46
|
+
AuthenticationManager,
|
|
47
|
+
AuthCredentials,
|
|
48
|
+
AuthSession,
|
|
49
|
+
AuthMethod,
|
|
50
|
+
AuthenticationError,
|
|
51
|
+
create_bearer_auth,
|
|
52
|
+
create_basic_auth,
|
|
53
|
+
create_api_key_auth,
|
|
54
|
+
create_cookie_auth,
|
|
55
|
+
create_form_login_auth,
|
|
56
|
+
create_oauth2_auth,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# LLM-Powered Tool Selection
|
|
60
|
+
from aipt_v2.intelligence.llm_tool_selector import (
|
|
61
|
+
LLMToolSelector,
|
|
62
|
+
ToolSelection,
|
|
63
|
+
ToolSelectionResult,
|
|
64
|
+
AVAILABLE_TOOLS,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# LLM-Powered Vulnerability Analysis
|
|
68
|
+
from aipt_v2.intelligence.llm_analyzer import (
|
|
69
|
+
LLMVulnerabilityAnalyzer,
|
|
70
|
+
LLMAnalysisResult,
|
|
71
|
+
DiscoveredChain,
|
|
72
|
+
ImplicitVulnerability,
|
|
73
|
+
ExploitationAssessment,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Feedback Learning System
|
|
77
|
+
from aipt_v2.intelligence.learning import (
|
|
78
|
+
ExploitationLearner,
|
|
79
|
+
ExploitAttempt,
|
|
80
|
+
PayloadSuggestion,
|
|
81
|
+
TechniqueStats,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Adaptive Payload Generation
|
|
85
|
+
from aipt_v2.intelligence.payload_generator import (
|
|
86
|
+
AdaptivePayloadGenerator,
|
|
87
|
+
GeneratedPayload,
|
|
88
|
+
PayloadGenerationResult,
|
|
89
|
+
PAYLOAD_TEMPLATES,
|
|
90
|
+
WAF_BYPASS_TECHNIQUES,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Security Knowledge Graph
|
|
94
|
+
from aipt_v2.intelligence.knowledge_graph import (
|
|
95
|
+
SecurityKnowledgeGraph,
|
|
96
|
+
GraphNode,
|
|
97
|
+
GraphEdge,
|
|
98
|
+
AttackPath,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Real-Time Adaptation
|
|
102
|
+
from aipt_v2.intelligence.adaptation import (
|
|
103
|
+
RealTimeAdapter,
|
|
104
|
+
DefenseType,
|
|
105
|
+
AdaptationAction,
|
|
106
|
+
DefenseDetection,
|
|
107
|
+
AdaptationStrategy,
|
|
108
|
+
RequestResult,
|
|
109
|
+
AdaptationState,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Cross-Target Correlation
|
|
113
|
+
from aipt_v2.intelligence.correlation import (
|
|
114
|
+
CrossTargetAnalyzer,
|
|
115
|
+
TargetSummary,
|
|
116
|
+
CommonVulnerability,
|
|
117
|
+
SystemicIssue,
|
|
118
|
+
PortfolioReport,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
__all__ = [
|
|
122
|
+
# CVE Intelligence (existing)
|
|
123
|
+
"CVEIntelligence",
|
|
124
|
+
"CVEInfo",
|
|
125
|
+
"ToolRAG",
|
|
126
|
+
"ToolMatch",
|
|
127
|
+
# Vulnerability Chaining
|
|
128
|
+
"VulnerabilityChainer",
|
|
129
|
+
"AttackChain",
|
|
130
|
+
"ChainLink",
|
|
131
|
+
# AI Triage
|
|
132
|
+
"AITriage",
|
|
133
|
+
"TriageResult",
|
|
134
|
+
"RiskAssessment",
|
|
135
|
+
# Scope Enforcement
|
|
136
|
+
"ScopeEnforcer",
|
|
137
|
+
"ScopeConfig",
|
|
138
|
+
"ScopeViolation",
|
|
139
|
+
"ScopeDecision",
|
|
140
|
+
"create_scope_from_target",
|
|
141
|
+
# Authentication
|
|
142
|
+
"AuthenticationManager",
|
|
143
|
+
"AuthCredentials",
|
|
144
|
+
"AuthSession",
|
|
145
|
+
"AuthMethod",
|
|
146
|
+
"AuthenticationError",
|
|
147
|
+
"create_bearer_auth",
|
|
148
|
+
"create_basic_auth",
|
|
149
|
+
"create_api_key_auth",
|
|
150
|
+
"create_cookie_auth",
|
|
151
|
+
"create_form_login_auth",
|
|
152
|
+
"create_oauth2_auth",
|
|
153
|
+
# LLM Tool Selection
|
|
154
|
+
"LLMToolSelector",
|
|
155
|
+
"ToolSelection",
|
|
156
|
+
"ToolSelectionResult",
|
|
157
|
+
"AVAILABLE_TOOLS",
|
|
158
|
+
# LLM Vulnerability Analysis
|
|
159
|
+
"LLMVulnerabilityAnalyzer",
|
|
160
|
+
"LLMAnalysisResult",
|
|
161
|
+
"DiscoveredChain",
|
|
162
|
+
"ImplicitVulnerability",
|
|
163
|
+
"ExploitationAssessment",
|
|
164
|
+
# Feedback Learning
|
|
165
|
+
"ExploitationLearner",
|
|
166
|
+
"ExploitAttempt",
|
|
167
|
+
"PayloadSuggestion",
|
|
168
|
+
"TechniqueStats",
|
|
169
|
+
# Adaptive Payload Generation
|
|
170
|
+
"AdaptivePayloadGenerator",
|
|
171
|
+
"GeneratedPayload",
|
|
172
|
+
"PayloadGenerationResult",
|
|
173
|
+
"PAYLOAD_TEMPLATES",
|
|
174
|
+
"WAF_BYPASS_TECHNIQUES",
|
|
175
|
+
# Knowledge Graph
|
|
176
|
+
"SecurityKnowledgeGraph",
|
|
177
|
+
"GraphNode",
|
|
178
|
+
"GraphEdge",
|
|
179
|
+
"AttackPath",
|
|
180
|
+
# Real-Time Adaptation
|
|
181
|
+
"RealTimeAdapter",
|
|
182
|
+
"DefenseType",
|
|
183
|
+
"AdaptationAction",
|
|
184
|
+
"DefenseDetection",
|
|
185
|
+
"AdaptationStrategy",
|
|
186
|
+
"RequestResult",
|
|
187
|
+
"AdaptationState",
|
|
188
|
+
# Cross-Target Correlation
|
|
189
|
+
"CrossTargetAnalyzer",
|
|
190
|
+
"TargetSummary",
|
|
191
|
+
"CommonVulnerability",
|
|
192
|
+
"SystemicIssue",
|
|
193
|
+
"PortfolioReport",
|
|
194
|
+
]
|