Files
mass-scan2/app/utils/models.py
2025-10-21 21:00:48 -05:00

94 lines
2.5 KiB
Python

from __future__ import annotations
from dataclasses import dataclass, field, asdict
from typing import Dict, List, Set, Optional, Any
from ipaddress import ip_address
@dataclass
class PortFinding:
"""
A single discovered port on a host.
protocol: 'tcp' or 'udp'
state: 'open', 'closed', 'filtered', 'open|filtered', etc.
service: optional nmap-reported service name (e.g., 'ssh', 'http')
"""
port: int
protocol: str
state: str
service: Optional[str] = None
@dataclass
class HostResult:
"""
Results for a single host.
address: IP address (e.g., '192.0.2.10')
host: primary hostname if reported by nmap (may be None)
ports: list of PortFinding instances for this host
"""
address: str
host: Optional[str] = None
ports: List[PortFinding] = field(default_factory=list)
@dataclass
class HostReport:
"""
Delta result for a single host.
"""
ip: str
unexpected_tcp: List[int]
missing_tcp: List[int]
unexpected_udp: List[int]
missing_udp: List[int]
def has_issues(self) -> bool:
"""
Returns True if any delta list is non-empty.
"""
if self.unexpected_tcp:
return True
if self.missing_tcp:
return True
if self.unexpected_udp:
return True
if self.missing_udp:
return True
return False
def to_dict(self) -> Dict[str, Any]:
"""
Convert to a plain dict for JSON/Jinja contexts.
"""
return asdict(self)
@dataclass
class GroupedReports:
"""
Final, template-friendly structure:
- issues: list of HostReport with any deltas (sorted by IP)
- expected: list of HostReport with no deltas (sorted by IP)
- by_ip: mapping for random access if needed
"""
issues: List[HostReport]
expected: List[HostReport]
by_ip: Dict[str, HostReport]
def to_context(self) -> Dict[str, Any]:
"""
Produce plain-dict context for Jinja render() if you prefer dicts.
"""
issues_dicts: List[Dict[str, Any]] = []
for hr in self.issues:
issues_dicts.append(hr.to_dict())
expected_dicts: List[Dict[str, Any]] = []
for hr in self.expected:
expected_dicts.append(hr.to_dict())
by_ip_dict: Dict[str, Dict[str, Any]] = {}
for ip, hr in self.by_ip.items():
by_ip_dict[ip] = hr.to_dict()
return {
"issues": issues_dicts,
"expected": expected_dicts,
"by_ip": by_ip_dict,
}