Mark a finding as resolved
(self, finding_id: str, reason: str = "no_longer_detected")
| 391 | self.logger.error(f"Error confirming finding: {e}") |
| 392 | |
| 393 | def resolve_finding(self, finding_id: str, reason: str = "no_longer_detected"): |
| 394 | """Mark a finding as resolved""" |
| 395 | try: |
| 396 | network_id = self.get_current_network_id() |
| 397 | if not network_id: |
| 398 | self.logger.error("No network ID available for resolution") |
| 399 | return |
| 400 | |
| 401 | resolved = False |
| 402 | |
| 403 | # Check and move vulnerability |
| 404 | if network_id in self.active_vulnerabilities: |
| 405 | if finding_id in self.active_vulnerabilities[network_id]: |
| 406 | vuln_data = self.active_vulnerabilities[network_id].pop(finding_id) |
| 407 | vuln_data['status'] = 'resolved' |
| 408 | vuln_data['resolved'] = datetime.now().isoformat() |
| 409 | vuln_data['resolution_reason'] = reason |
| 410 | |
| 411 | if network_id not in self.resolved_vulnerabilities: |
| 412 | self.resolved_vulnerabilities[network_id] = {} |
| 413 | self.resolved_vulnerabilities[network_id][finding_id] = vuln_data |
| 414 | resolved = True |
| 415 | |
| 416 | # Check and move credential |
| 417 | if network_id in self.active_credentials and not resolved: |
| 418 | if finding_id in self.active_credentials[network_id]: |
| 419 | cred_data = self.active_credentials[network_id].pop(finding_id) |
| 420 | cred_data['status'] = 'resolved' |
| 421 | cred_data['resolved'] = datetime.now().isoformat() |
| 422 | cred_data['resolution_reason'] = reason |
| 423 | |
| 424 | if network_id not in self.resolved_credentials: |
| 425 | self.resolved_credentials[network_id] = {} |
| 426 | self.resolved_credentials[network_id][finding_id] = cred_data |
| 427 | resolved = True |
| 428 | |
| 429 | if resolved: |
| 430 | self.update_network_profile(network_id) |
| 431 | self.save_intelligence_data() |
| 432 | self.logger.info(f"Resolved finding: {finding_id} - {reason}") |
| 433 | else: |
| 434 | self.logger.warning(f"Finding not found for resolution: {finding_id}") |
| 435 | |
| 436 | except Exception as e: |
| 437 | self.logger.error(f"Error resolving finding: {e}") |
| 438 | |
| 439 | def get_active_findings_for_dashboard(self) -> Dict: |
| 440 | """Get active findings for current network (dashboard view) |
no test coverage detected