aiptx 2.0.2__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.

Potentially problematic release.


This version of aiptx might be problematic. Click here for more details.

Files changed (165) hide show
  1. aipt_v2/__init__.py +110 -0
  2. aipt_v2/__main__.py +24 -0
  3. aipt_v2/agents/AIPTxAgent/__init__.py +10 -0
  4. aipt_v2/agents/AIPTxAgent/aiptx_agent.py +211 -0
  5. aipt_v2/agents/__init__.py +24 -0
  6. aipt_v2/agents/base.py +520 -0
  7. aipt_v2/agents/ptt.py +406 -0
  8. aipt_v2/agents/state.py +168 -0
  9. aipt_v2/app.py +960 -0
  10. aipt_v2/browser/__init__.py +31 -0
  11. aipt_v2/browser/automation.py +458 -0
  12. aipt_v2/browser/crawler.py +453 -0
  13. aipt_v2/cli.py +321 -0
  14. aipt_v2/compliance/__init__.py +71 -0
  15. aipt_v2/compliance/compliance_report.py +449 -0
  16. aipt_v2/compliance/framework_mapper.py +424 -0
  17. aipt_v2/compliance/nist_mapping.py +345 -0
  18. aipt_v2/compliance/owasp_mapping.py +330 -0
  19. aipt_v2/compliance/pci_mapping.py +297 -0
  20. aipt_v2/config.py +288 -0
  21. aipt_v2/core/__init__.py +43 -0
  22. aipt_v2/core/agent.py +630 -0
  23. aipt_v2/core/llm.py +395 -0
  24. aipt_v2/core/memory.py +305 -0
  25. aipt_v2/core/ptt.py +329 -0
  26. aipt_v2/database/__init__.py +14 -0
  27. aipt_v2/database/models.py +232 -0
  28. aipt_v2/database/repository.py +384 -0
  29. aipt_v2/docker/__init__.py +23 -0
  30. aipt_v2/docker/builder.py +260 -0
  31. aipt_v2/docker/manager.py +222 -0
  32. aipt_v2/docker/sandbox.py +371 -0
  33. aipt_v2/evasion/__init__.py +58 -0
  34. aipt_v2/evasion/request_obfuscator.py +272 -0
  35. aipt_v2/evasion/tls_fingerprint.py +285 -0
  36. aipt_v2/evasion/ua_rotator.py +301 -0
  37. aipt_v2/evasion/waf_bypass.py +439 -0
  38. aipt_v2/execution/__init__.py +23 -0
  39. aipt_v2/execution/executor.py +302 -0
  40. aipt_v2/execution/parser.py +544 -0
  41. aipt_v2/execution/terminal.py +337 -0
  42. aipt_v2/health.py +437 -0
  43. aipt_v2/intelligence/__init__.py +85 -0
  44. aipt_v2/intelligence/auth.py +520 -0
  45. aipt_v2/intelligence/chaining.py +775 -0
  46. aipt_v2/intelligence/cve_aipt.py +334 -0
  47. aipt_v2/intelligence/cve_info.py +1111 -0
  48. aipt_v2/intelligence/rag.py +239 -0
  49. aipt_v2/intelligence/scope.py +442 -0
  50. aipt_v2/intelligence/searchers/__init__.py +5 -0
  51. aipt_v2/intelligence/searchers/exploitdb_searcher.py +523 -0
  52. aipt_v2/intelligence/searchers/github_searcher.py +467 -0
  53. aipt_v2/intelligence/searchers/google_searcher.py +281 -0
  54. aipt_v2/intelligence/tools.json +443 -0
  55. aipt_v2/intelligence/triage.py +670 -0
  56. aipt_v2/interface/__init__.py +5 -0
  57. aipt_v2/interface/cli.py +230 -0
  58. aipt_v2/interface/main.py +501 -0
  59. aipt_v2/interface/tui.py +1276 -0
  60. aipt_v2/interface/utils.py +583 -0
  61. aipt_v2/llm/__init__.py +39 -0
  62. aipt_v2/llm/config.py +26 -0
  63. aipt_v2/llm/llm.py +514 -0
  64. aipt_v2/llm/memory.py +214 -0
  65. aipt_v2/llm/request_queue.py +89 -0
  66. aipt_v2/llm/utils.py +89 -0
  67. aipt_v2/models/__init__.py +15 -0
  68. aipt_v2/models/findings.py +295 -0
  69. aipt_v2/models/phase_result.py +224 -0
  70. aipt_v2/models/scan_config.py +207 -0
  71. aipt_v2/monitoring/grafana/dashboards/aipt-dashboard.json +355 -0
  72. aipt_v2/monitoring/grafana/dashboards/default.yml +17 -0
  73. aipt_v2/monitoring/grafana/datasources/prometheus.yml +17 -0
  74. aipt_v2/monitoring/prometheus.yml +60 -0
  75. aipt_v2/orchestration/__init__.py +52 -0
  76. aipt_v2/orchestration/pipeline.py +398 -0
  77. aipt_v2/orchestration/progress.py +300 -0
  78. aipt_v2/orchestration/scheduler.py +296 -0
  79. aipt_v2/orchestrator.py +2284 -0
  80. aipt_v2/payloads/__init__.py +27 -0
  81. aipt_v2/payloads/cmdi.py +150 -0
  82. aipt_v2/payloads/sqli.py +263 -0
  83. aipt_v2/payloads/ssrf.py +204 -0
  84. aipt_v2/payloads/templates.py +222 -0
  85. aipt_v2/payloads/traversal.py +166 -0
  86. aipt_v2/payloads/xss.py +204 -0
  87. aipt_v2/prompts/__init__.py +60 -0
  88. aipt_v2/proxy/__init__.py +29 -0
  89. aipt_v2/proxy/history.py +352 -0
  90. aipt_v2/proxy/interceptor.py +452 -0
  91. aipt_v2/recon/__init__.py +44 -0
  92. aipt_v2/recon/dns.py +241 -0
  93. aipt_v2/recon/osint.py +367 -0
  94. aipt_v2/recon/subdomain.py +372 -0
  95. aipt_v2/recon/tech_detect.py +311 -0
  96. aipt_v2/reports/__init__.py +17 -0
  97. aipt_v2/reports/generator.py +313 -0
  98. aipt_v2/reports/html_report.py +378 -0
  99. aipt_v2/runtime/__init__.py +44 -0
  100. aipt_v2/runtime/base.py +30 -0
  101. aipt_v2/runtime/docker.py +401 -0
  102. aipt_v2/runtime/local.py +346 -0
  103. aipt_v2/runtime/tool_server.py +205 -0
  104. aipt_v2/scanners/__init__.py +28 -0
  105. aipt_v2/scanners/base.py +273 -0
  106. aipt_v2/scanners/nikto.py +244 -0
  107. aipt_v2/scanners/nmap.py +402 -0
  108. aipt_v2/scanners/nuclei.py +273 -0
  109. aipt_v2/scanners/web.py +454 -0
  110. aipt_v2/scripts/security_audit.py +366 -0
  111. aipt_v2/telemetry/__init__.py +7 -0
  112. aipt_v2/telemetry/tracer.py +347 -0
  113. aipt_v2/terminal/__init__.py +28 -0
  114. aipt_v2/terminal/executor.py +400 -0
  115. aipt_v2/terminal/sandbox.py +350 -0
  116. aipt_v2/tools/__init__.py +44 -0
  117. aipt_v2/tools/active_directory/__init__.py +78 -0
  118. aipt_v2/tools/active_directory/ad_config.py +238 -0
  119. aipt_v2/tools/active_directory/bloodhound_wrapper.py +447 -0
  120. aipt_v2/tools/active_directory/kerberos_attacks.py +430 -0
  121. aipt_v2/tools/active_directory/ldap_enum.py +533 -0
  122. aipt_v2/tools/active_directory/smb_attacks.py +505 -0
  123. aipt_v2/tools/agents_graph/__init__.py +19 -0
  124. aipt_v2/tools/agents_graph/agents_graph_actions.py +69 -0
  125. aipt_v2/tools/api_security/__init__.py +76 -0
  126. aipt_v2/tools/api_security/api_discovery.py +608 -0
  127. aipt_v2/tools/api_security/graphql_scanner.py +622 -0
  128. aipt_v2/tools/api_security/jwt_analyzer.py +577 -0
  129. aipt_v2/tools/api_security/openapi_fuzzer.py +761 -0
  130. aipt_v2/tools/browser/__init__.py +5 -0
  131. aipt_v2/tools/browser/browser_actions.py +238 -0
  132. aipt_v2/tools/browser/browser_instance.py +535 -0
  133. aipt_v2/tools/browser/tab_manager.py +344 -0
  134. aipt_v2/tools/cloud/__init__.py +70 -0
  135. aipt_v2/tools/cloud/cloud_config.py +273 -0
  136. aipt_v2/tools/cloud/cloud_scanner.py +639 -0
  137. aipt_v2/tools/cloud/prowler_tool.py +571 -0
  138. aipt_v2/tools/cloud/scoutsuite_tool.py +359 -0
  139. aipt_v2/tools/executor.py +307 -0
  140. aipt_v2/tools/parser.py +408 -0
  141. aipt_v2/tools/proxy/__init__.py +5 -0
  142. aipt_v2/tools/proxy/proxy_actions.py +103 -0
  143. aipt_v2/tools/proxy/proxy_manager.py +789 -0
  144. aipt_v2/tools/registry.py +196 -0
  145. aipt_v2/tools/scanners/__init__.py +343 -0
  146. aipt_v2/tools/scanners/acunetix_tool.py +712 -0
  147. aipt_v2/tools/scanners/burp_tool.py +631 -0
  148. aipt_v2/tools/scanners/config.py +156 -0
  149. aipt_v2/tools/scanners/nessus_tool.py +588 -0
  150. aipt_v2/tools/scanners/zap_tool.py +612 -0
  151. aipt_v2/tools/terminal/__init__.py +5 -0
  152. aipt_v2/tools/terminal/terminal_actions.py +37 -0
  153. aipt_v2/tools/terminal/terminal_manager.py +153 -0
  154. aipt_v2/tools/terminal/terminal_session.py +449 -0
  155. aipt_v2/tools/tool_processing.py +108 -0
  156. aipt_v2/utils/__init__.py +17 -0
  157. aipt_v2/utils/logging.py +201 -0
  158. aipt_v2/utils/model_manager.py +187 -0
  159. aipt_v2/utils/searchers/__init__.py +269 -0
  160. aiptx-2.0.2.dist-info/METADATA +324 -0
  161. aiptx-2.0.2.dist-info/RECORD +165 -0
  162. aiptx-2.0.2.dist-info/WHEEL +5 -0
  163. aiptx-2.0.2.dist-info/entry_points.txt +7 -0
  164. aiptx-2.0.2.dist-info/licenses/LICENSE +21 -0
  165. aiptx-2.0.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,571 @@
1
+ """
2
+ Prowler Integration - AWS Security Best Practices Auditing
3
+
4
+ Prowler is an open-source security tool to perform AWS, GCP, and Azure
5
+ security best practices assessments, audits, incident response,
6
+ continuous monitoring, hardening and forensics readiness.
7
+
8
+ Supports:
9
+ - CIS AWS Foundations Benchmark
10
+ - PCI-DSS
11
+ - HIPAA
12
+ - GDPR
13
+ - AWS Well-Architected Framework
14
+ - 300+ security checks
15
+
16
+ Usage:
17
+ from aipt_v2.tools.cloud import run_prowler
18
+
19
+ findings = await run_prowler(profile="production", compliance=["cis", "pci"])
20
+ """
21
+
22
+ import asyncio
23
+ import json
24
+ import csv
25
+ import os
26
+ from dataclasses import dataclass, field
27
+ from datetime import datetime, timezone
28
+ from pathlib import Path
29
+ from typing import List, Dict, Any, Optional
30
+
31
+ from aipt_v2.tools.cloud.cloud_config import CloudConfig, get_cloud_config
32
+
33
+
34
+ @dataclass
35
+ class ProwlerConfig:
36
+ """Prowler configuration."""
37
+ provider: str = "aws" # aws, azure, gcp
38
+
39
+ # AWS options
40
+ aws_profile: str = "default"
41
+ aws_regions: List[str] = field(default_factory=list) # Empty = all
42
+
43
+ # Compliance frameworks
44
+ compliance: List[str] = field(default_factory=list) # cis, pci, hipaa, gdpr
45
+
46
+ # Scanning options
47
+ checks: List[str] = field(default_factory=list) # Specific checks to run
48
+ services: List[str] = field(default_factory=list) # Specific services
49
+ severity: List[str] = field(default_factory=lambda: ["critical", "high", "medium", "low"])
50
+
51
+ # Output options
52
+ output_dir: str = "./prowler_results"
53
+ output_formats: List[str] = field(default_factory=lambda: ["json", "html"])
54
+
55
+ # Performance
56
+ parallel: bool = True
57
+ shodan_api_key: str = "" # Optional Shodan integration
58
+
59
+
60
+ @dataclass
61
+ class ProwlerFinding:
62
+ """Individual Prowler finding."""
63
+ check_id: str
64
+ check_title: str
65
+ service: str
66
+ severity: str
67
+ status: str # PASS, FAIL, INFO, WARNING
68
+ region: str
69
+ resource_id: str
70
+ resource_arn: str
71
+ description: str
72
+ risk: str
73
+ remediation: str
74
+ compliance: List[str] = field(default_factory=list)
75
+ timestamp: str = ""
76
+
77
+
78
+ @dataclass
79
+ class ProwlerResult:
80
+ """Result of a Prowler scan."""
81
+ provider: str
82
+ status: str
83
+ started_at: str
84
+ finished_at: str
85
+ duration: float
86
+ total_checks: int
87
+ passed: int
88
+ failed: int
89
+ warnings: int
90
+ findings: List[ProwlerFinding]
91
+ report_path: str
92
+ summary: Dict[str, int]
93
+ metadata: Dict[str, Any] = field(default_factory=dict)
94
+
95
+
96
+ class ProwlerTool:
97
+ """
98
+ Prowler wrapper for AWS/Azure/GCP security auditing.
99
+
100
+ Provides a Python interface to the Prowler CLI tool
101
+ for automated cloud security assessments against
102
+ compliance frameworks.
103
+ """
104
+
105
+ def __init__(self, config: Optional[ProwlerConfig] = None):
106
+ """
107
+ Initialize Prowler tool.
108
+
109
+ Args:
110
+ config: Prowler configuration
111
+ """
112
+ self.config = config or ProwlerConfig()
113
+ self.output_dir = Path(self.config.output_dir)
114
+ self.output_dir.mkdir(parents=True, exist_ok=True)
115
+ self._installed = None
116
+ self._version = None
117
+
118
+ async def check_installed(self) -> bool:
119
+ """Check if Prowler is installed."""
120
+ if self._installed is not None:
121
+ return self._installed
122
+
123
+ try:
124
+ process = await asyncio.create_subprocess_shell(
125
+ "prowler --version",
126
+ stdout=asyncio.subprocess.PIPE,
127
+ stderr=asyncio.subprocess.PIPE
128
+ )
129
+ stdout, _ = await process.communicate()
130
+ self._installed = process.returncode == 0
131
+ if self._installed:
132
+ self._version = stdout.decode().strip()
133
+ except Exception:
134
+ self._installed = False
135
+
136
+ return self._installed
137
+
138
+ async def get_version(self) -> str:
139
+ """Get Prowler version."""
140
+ if not await self.check_installed():
141
+ return "Not installed"
142
+ return self._version or "Unknown"
143
+
144
+ def _build_command(self) -> str:
145
+ """Build Prowler command from configuration."""
146
+ cmd_parts = ["prowler", self.config.provider]
147
+
148
+ # Add provider-specific options
149
+ if self.config.provider == "aws":
150
+ if self.config.aws_profile:
151
+ cmd_parts.extend(["--profile", self.config.aws_profile])
152
+ if self.config.aws_regions:
153
+ cmd_parts.extend(["--filter-region", ",".join(self.config.aws_regions)])
154
+
155
+ # Add compliance frameworks
156
+ if self.config.compliance:
157
+ for framework in self.config.compliance:
158
+ cmd_parts.extend(["--compliance", framework])
159
+
160
+ # Add specific checks
161
+ if self.config.checks:
162
+ cmd_parts.extend(["--checks", ",".join(self.config.checks)])
163
+
164
+ # Add service filtering
165
+ if self.config.services:
166
+ cmd_parts.extend(["--services", ",".join(self.config.services)])
167
+
168
+ # Add severity filtering
169
+ if self.config.severity:
170
+ cmd_parts.extend(["--severity", ",".join(self.config.severity)])
171
+
172
+ # Add output options
173
+ cmd_parts.extend(["--output-directory", str(self.output_dir)])
174
+
175
+ if self.config.output_formats:
176
+ cmd_parts.extend(["--output-formats", ",".join(self.config.output_formats)])
177
+
178
+ # Add Shodan integration if configured
179
+ if self.config.shodan_api_key:
180
+ cmd_parts.extend(["--shodan", self.config.shodan_api_key])
181
+
182
+ # Quiet mode for cleaner output
183
+ cmd_parts.append("--no-banner")
184
+
185
+ return " ".join(cmd_parts)
186
+
187
+ async def scan(self, timeout: int = 3600) -> ProwlerResult:
188
+ """
189
+ Run Prowler scan.
190
+
191
+ Args:
192
+ timeout: Scan timeout in seconds
193
+
194
+ Returns:
195
+ ProwlerResult with findings summary
196
+ """
197
+ if not await self.check_installed():
198
+ raise RuntimeError("Prowler is not installed. Install with: pip install prowler")
199
+
200
+ started_at = datetime.now(timezone.utc).isoformat()
201
+ start_time = asyncio.get_event_loop().time()
202
+
203
+ cmd = self._build_command()
204
+ print(f"[*] Running: {cmd}")
205
+
206
+ # Set up environment
207
+ env = os.environ.copy()
208
+
209
+ process = await asyncio.create_subprocess_shell(
210
+ cmd,
211
+ stdout=asyncio.subprocess.PIPE,
212
+ stderr=asyncio.subprocess.PIPE,
213
+ env=env
214
+ )
215
+
216
+ try:
217
+ stdout, stderr = await asyncio.wait_for(
218
+ process.communicate(),
219
+ timeout=timeout
220
+ )
221
+ except asyncio.TimeoutError:
222
+ process.kill()
223
+ raise TimeoutError(f"Prowler scan timed out after {timeout}s")
224
+
225
+ finished_at = datetime.now(timezone.utc).isoformat()
226
+ duration = asyncio.get_event_loop().time() - start_time
227
+
228
+ # Parse results
229
+ findings = self._parse_findings()
230
+ report_path = self._find_latest_report()
231
+
232
+ # Calculate summary
233
+ total_checks = len(findings)
234
+ passed = sum(1 for f in findings if f.status == "PASS")
235
+ failed = sum(1 for f in findings if f.status == "FAIL")
236
+ warnings = sum(1 for f in findings if f.status in ["WARNING", "INFO"])
237
+
238
+ summary = {
239
+ "critical": sum(1 for f in findings if f.severity == "critical" and f.status == "FAIL"),
240
+ "high": sum(1 for f in findings if f.severity == "high" and f.status == "FAIL"),
241
+ "medium": sum(1 for f in findings if f.severity == "medium" and f.status == "FAIL"),
242
+ "low": sum(1 for f in findings if f.severity == "low" and f.status == "FAIL"),
243
+ }
244
+
245
+ status = "completed" if process.returncode == 0 else "failed"
246
+
247
+ return ProwlerResult(
248
+ provider=self.config.provider,
249
+ status=status,
250
+ started_at=started_at,
251
+ finished_at=finished_at,
252
+ duration=duration,
253
+ total_checks=total_checks,
254
+ passed=passed,
255
+ failed=failed,
256
+ warnings=warnings,
257
+ findings=findings,
258
+ report_path=str(report_path) if report_path else "",
259
+ summary=summary,
260
+ metadata={
261
+ "command": cmd,
262
+ "return_code": process.returncode,
263
+ "version": self._version,
264
+ "stderr": stderr.decode() if process.returncode != 0 else ""
265
+ }
266
+ )
267
+
268
+ def _find_latest_report(self) -> Optional[Path]:
269
+ """Find the latest Prowler output file."""
270
+ # Prowler creates timestamped directories
271
+ if not self.output_dir.exists():
272
+ return None
273
+
274
+ # Look for JSON output files
275
+ json_files = list(self.output_dir.glob("**/prowler-output*.json"))
276
+ if json_files:
277
+ return max(json_files, key=lambda f: f.stat().st_mtime)
278
+
279
+ # Try CSV files
280
+ csv_files = list(self.output_dir.glob("**/prowler-output*.csv"))
281
+ if csv_files:
282
+ return max(csv_files, key=lambda f: f.stat().st_mtime)
283
+
284
+ # Try HTML files
285
+ html_files = list(self.output_dir.glob("**/prowler-output*.html"))
286
+ if html_files:
287
+ return max(html_files, key=lambda f: f.stat().st_mtime)
288
+
289
+ return None
290
+
291
+ def _parse_findings(self) -> List[ProwlerFinding]:
292
+ """Parse findings from Prowler output."""
293
+ findings = []
294
+
295
+ # Try JSON first (preferred)
296
+ json_files = list(self.output_dir.glob("**/prowler-output*.json"))
297
+ if json_files:
298
+ latest_json = max(json_files, key=lambda f: f.stat().st_mtime)
299
+ findings.extend(self._parse_json_findings(latest_json))
300
+
301
+ # Fall back to CSV if no JSON
302
+ if not findings:
303
+ csv_files = list(self.output_dir.glob("**/prowler-output*.csv"))
304
+ if csv_files:
305
+ latest_csv = max(csv_files, key=lambda f: f.stat().st_mtime)
306
+ findings.extend(self._parse_csv_findings(latest_csv))
307
+
308
+ return findings
309
+
310
+ def _parse_json_findings(self, json_file: Path) -> List[ProwlerFinding]:
311
+ """Parse findings from JSON output."""
312
+ findings = []
313
+
314
+ try:
315
+ with open(json_file, 'r') as f:
316
+ # Prowler JSON can be JSONL (one JSON per line) or array
317
+ content = f.read().strip()
318
+
319
+ if content.startswith('['):
320
+ # JSON array
321
+ data = json.loads(content)
322
+ else:
323
+ # JSONL format
324
+ data = []
325
+ for line in content.split('\n'):
326
+ if line.strip():
327
+ data.append(json.loads(line))
328
+
329
+ for item in data:
330
+ finding = ProwlerFinding(
331
+ check_id=item.get("CheckID", item.get("check_id", "")),
332
+ check_title=item.get("CheckTitle", item.get("check_title", "")),
333
+ service=item.get("ServiceName", item.get("service", "")),
334
+ severity=item.get("Severity", item.get("severity", "")).lower(),
335
+ status=item.get("Status", item.get("status", "")).upper(),
336
+ region=item.get("Region", item.get("region", "")),
337
+ resource_id=item.get("ResourceId", item.get("resource_id", "")),
338
+ resource_arn=item.get("ResourceArn", item.get("resource_arn", "")),
339
+ description=item.get("StatusExtended", item.get("description", "")),
340
+ risk=item.get("Risk", item.get("risk", "")),
341
+ remediation=item.get("Remediation", {}).get("Recommendation", {}).get("Text", ""),
342
+ compliance=item.get("Compliance", []),
343
+ timestamp=item.get("Timestamp", item.get("timestamp", ""))
344
+ )
345
+ findings.append(finding)
346
+
347
+ except Exception as e:
348
+ print(f"[!] Error parsing Prowler JSON: {e}")
349
+
350
+ return findings
351
+
352
+ def _parse_csv_findings(self, csv_file: Path) -> List[ProwlerFinding]:
353
+ """Parse findings from CSV output."""
354
+ findings = []
355
+
356
+ try:
357
+ with open(csv_file, 'r', newline='') as f:
358
+ reader = csv.DictReader(f)
359
+ for row in reader:
360
+ finding = ProwlerFinding(
361
+ check_id=row.get("CHECK_ID", row.get("check_id", "")),
362
+ check_title=row.get("CHECK_TITLE", row.get("check_title", "")),
363
+ service=row.get("SERVICE_NAME", row.get("service", "")),
364
+ severity=row.get("SEVERITY", row.get("severity", "")).lower(),
365
+ status=row.get("STATUS", row.get("status", "")).upper(),
366
+ region=row.get("REGION", row.get("region", "")),
367
+ resource_id=row.get("RESOURCE_ID", row.get("resource_id", "")),
368
+ resource_arn=row.get("RESOURCE_ARN", row.get("resource_arn", "")),
369
+ description=row.get("STATUS_EXTENDED", row.get("description", "")),
370
+ risk=row.get("RISK", row.get("risk", "")),
371
+ remediation=row.get("REMEDIATION", row.get("remediation", "")),
372
+ compliance=[],
373
+ timestamp=row.get("TIMESTAMP", row.get("timestamp", ""))
374
+ )
375
+ findings.append(finding)
376
+
377
+ except Exception as e:
378
+ print(f"[!] Error parsing Prowler CSV: {e}")
379
+
380
+ return findings
381
+
382
+ def get_failed_findings(self) -> List[ProwlerFinding]:
383
+ """Get only failed findings from the latest scan."""
384
+ all_findings = self._parse_findings()
385
+ return [f for f in all_findings if f.status == "FAIL"]
386
+
387
+ def get_findings_by_severity(self, severity: str) -> List[ProwlerFinding]:
388
+ """Get findings filtered by severity."""
389
+ all_findings = self._parse_findings()
390
+ return [f for f in all_findings if f.severity.lower() == severity.lower()]
391
+
392
+ def get_findings_by_service(self, service: str) -> List[ProwlerFinding]:
393
+ """Get findings filtered by AWS service."""
394
+ all_findings = self._parse_findings()
395
+ return [f for f in all_findings if service.lower() in f.service.lower()]
396
+
397
+ def get_compliance_summary(self) -> Dict[str, Dict[str, int]]:
398
+ """Get compliance framework summary."""
399
+ findings = self._parse_findings()
400
+ compliance_summary = {}
401
+
402
+ for finding in findings:
403
+ for framework in finding.compliance:
404
+ if framework not in compliance_summary:
405
+ compliance_summary[framework] = {"passed": 0, "failed": 0}
406
+
407
+ if finding.status == "PASS":
408
+ compliance_summary[framework]["passed"] += 1
409
+ elif finding.status == "FAIL":
410
+ compliance_summary[framework]["failed"] += 1
411
+
412
+ return compliance_summary
413
+
414
+
415
+ async def list_available_checks(provider: str = "aws") -> List[Dict[str, str]]:
416
+ """
417
+ List all available Prowler checks for a provider.
418
+
419
+ Args:
420
+ provider: Cloud provider (aws, azure, gcp)
421
+
422
+ Returns:
423
+ List of check definitions
424
+ """
425
+ try:
426
+ process = await asyncio.create_subprocess_shell(
427
+ f"prowler {provider} --list-checks --no-banner",
428
+ stdout=asyncio.subprocess.PIPE,
429
+ stderr=asyncio.subprocess.PIPE
430
+ )
431
+ stdout, _ = await process.communicate()
432
+
433
+ checks = []
434
+ for line in stdout.decode().split('\n'):
435
+ if line.strip() and not line.startswith(('-', '=')):
436
+ parts = line.split(' - ', 1)
437
+ if len(parts) == 2:
438
+ checks.append({
439
+ "id": parts[0].strip(),
440
+ "title": parts[1].strip()
441
+ })
442
+
443
+ return checks
444
+ except Exception as e:
445
+ print(f"[!] Error listing checks: {e}")
446
+ return []
447
+
448
+
449
+ async def list_compliance_frameworks(provider: str = "aws") -> List[str]:
450
+ """
451
+ List available compliance frameworks.
452
+
453
+ Args:
454
+ provider: Cloud provider
455
+
456
+ Returns:
457
+ List of framework names
458
+ """
459
+ try:
460
+ process = await asyncio.create_subprocess_shell(
461
+ f"prowler {provider} --list-compliance --no-banner",
462
+ stdout=asyncio.subprocess.PIPE,
463
+ stderr=asyncio.subprocess.PIPE
464
+ )
465
+ stdout, _ = await process.communicate()
466
+
467
+ frameworks = []
468
+ for line in stdout.decode().split('\n'):
469
+ line = line.strip()
470
+ if line and not line.startswith(('-', '=', 'Available')):
471
+ frameworks.append(line)
472
+
473
+ return frameworks
474
+ except Exception:
475
+ # Return default frameworks if listing fails
476
+ return [
477
+ "cis_1.4_aws",
478
+ "cis_1.5_aws",
479
+ "cis_2.0_aws",
480
+ "pci_3.2.1_aws",
481
+ "hipaa_aws",
482
+ "gdpr_aws",
483
+ "aws_well_architected_framework",
484
+ "nist_800_53_revision_5_aws"
485
+ ]
486
+
487
+
488
+ # Convenience function
489
+ async def run_prowler(
490
+ profile: Optional[str] = None,
491
+ regions: Optional[List[str]] = None,
492
+ compliance: Optional[List[str]] = None,
493
+ services: Optional[List[str]] = None,
494
+ severity: Optional[List[str]] = None,
495
+ output_dir: str = "./prowler_results",
496
+ timeout: int = 3600
497
+ ) -> ProwlerResult:
498
+ """
499
+ Run Prowler AWS security scan.
500
+
501
+ Args:
502
+ profile: AWS profile name
503
+ regions: Specific regions to scan
504
+ compliance: Compliance frameworks to check (cis, pci, hipaa, gdpr)
505
+ services: Specific AWS services to scan
506
+ severity: Severity levels to include
507
+ output_dir: Output directory for reports
508
+ timeout: Scan timeout in seconds
509
+
510
+ Returns:
511
+ ProwlerResult
512
+ """
513
+ config = ProwlerConfig(
514
+ provider="aws",
515
+ aws_profile=profile or "default",
516
+ aws_regions=regions or [],
517
+ compliance=compliance or [],
518
+ services=services or [],
519
+ severity=severity or ["critical", "high", "medium", "low"],
520
+ output_dir=output_dir
521
+ )
522
+
523
+ tool = ProwlerTool(config)
524
+ return await tool.scan(timeout=timeout)
525
+
526
+
527
+ # Quick check functions
528
+ async def quick_iam_check(profile: str = "default") -> ProwlerResult:
529
+ """Quick IAM security check."""
530
+ config = ProwlerConfig(
531
+ aws_profile=profile,
532
+ services=["iam"],
533
+ severity=["critical", "high"]
534
+ )
535
+ tool = ProwlerTool(config)
536
+ return await tool.scan(timeout=600)
537
+
538
+
539
+ async def quick_s3_check(profile: str = "default") -> ProwlerResult:
540
+ """Quick S3 security check."""
541
+ config = ProwlerConfig(
542
+ aws_profile=profile,
543
+ services=["s3"],
544
+ severity=["critical", "high"]
545
+ )
546
+ tool = ProwlerTool(config)
547
+ return await tool.scan(timeout=600)
548
+
549
+
550
+ async def quick_network_check(profile: str = "default") -> ProwlerResult:
551
+ """Quick network/VPC security check."""
552
+ config = ProwlerConfig(
553
+ aws_profile=profile,
554
+ services=["ec2", "vpc"],
555
+ severity=["critical", "high"]
556
+ )
557
+ tool = ProwlerTool(config)
558
+ return await tool.scan(timeout=900)
559
+
560
+
561
+ async def compliance_scan(
562
+ profile: str = "default",
563
+ framework: str = "cis_2.0_aws"
564
+ ) -> ProwlerResult:
565
+ """Run compliance-focused scan."""
566
+ config = ProwlerConfig(
567
+ aws_profile=profile,
568
+ compliance=[framework]
569
+ )
570
+ tool = ProwlerTool(config)
571
+ return await tool.scan(timeout=3600)