mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-13 14:44:58 +03:00
291 lines
11 KiB
Python
291 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Ransomware Recovery Orchestration and Tracking Tool
|
|
|
|
Tracks recovery progress across multiple systems and phases:
|
|
- Recovery phase tracking with dependency management
|
|
- RTO compliance monitoring
|
|
- System validation checklists
|
|
- Recovery status reporting
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
from dataclasses import dataclass, field, asdict
|
|
from datetime import datetime, timedelta
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
|
|
@dataclass
|
|
class RecoverableSystem:
|
|
name: str
|
|
tier: int
|
|
system_type: str # dc, database, application, fileserver, web, other
|
|
dependencies: list = field(default_factory=list)
|
|
rto_hours: float = 24.0
|
|
status: str = "pending" # pending, restoring, validating, online, failed
|
|
backup_source: str = ""
|
|
backup_timestamp: Optional[str] = None
|
|
restore_start: Optional[str] = None
|
|
restore_end: Optional[str] = None
|
|
validation_checks: dict = field(default_factory=dict)
|
|
notes: str = ""
|
|
|
|
|
|
@dataclass
|
|
class RecoveryPlan:
|
|
incident_id: str
|
|
organization: str
|
|
recovery_start: str
|
|
compromise_date: str
|
|
systems: list = field(default_factory=list)
|
|
phases: dict = field(default_factory=dict)
|
|
overall_status: str = "in_progress"
|
|
|
|
|
|
class RecoveryOrchestrator:
|
|
"""Manages and tracks ransomware recovery across all systems."""
|
|
|
|
def __init__(self, incident_id: str, org_name: str, compromise_date: str):
|
|
self.plan = RecoveryPlan(
|
|
incident_id=incident_id,
|
|
organization=org_name,
|
|
recovery_start=datetime.now().isoformat(),
|
|
compromise_date=compromise_date,
|
|
)
|
|
|
|
def add_system(self, system: RecoverableSystem):
|
|
self.plan.systems.append(system)
|
|
|
|
def start_restore(self, system_name: str, backup_source: str):
|
|
for sys in self.plan.systems:
|
|
if sys.name == system_name:
|
|
# Check dependencies are online
|
|
for dep in sys.dependencies:
|
|
dep_sys = next((s for s in self.plan.systems if s.name == dep), None)
|
|
if dep_sys and dep_sys.status != "online":
|
|
raise ValueError(
|
|
f"Cannot restore {system_name}: dependency {dep} "
|
|
f"is {dep_sys.status}, must be 'online'"
|
|
)
|
|
sys.status = "restoring"
|
|
sys.backup_source = backup_source
|
|
sys.restore_start = datetime.now().isoformat()
|
|
return
|
|
raise ValueError(f"System not found: {system_name}")
|
|
|
|
def complete_restore(self, system_name: str):
|
|
for sys in self.plan.systems:
|
|
if sys.name == system_name:
|
|
sys.status = "validating"
|
|
sys.restore_end = datetime.now().isoformat()
|
|
return
|
|
raise ValueError(f"System not found: {system_name}")
|
|
|
|
def validate_system(self, system_name: str, checks: dict):
|
|
"""Record validation check results for a restored system."""
|
|
for sys in self.plan.systems:
|
|
if sys.name == system_name:
|
|
sys.validation_checks = checks
|
|
all_passed = all(checks.values())
|
|
sys.status = "online" if all_passed else "failed"
|
|
return all_passed
|
|
raise ValueError(f"System not found: {system_name}")
|
|
|
|
def check_rto_compliance(self) -> list:
|
|
"""Check which systems are at risk of exceeding their RTO."""
|
|
violations = []
|
|
recovery_start = datetime.fromisoformat(self.plan.recovery_start)
|
|
|
|
for sys in self.plan.systems:
|
|
rto_deadline = recovery_start + timedelta(hours=sys.rto_hours)
|
|
|
|
if sys.status in ("pending", "restoring", "validating"):
|
|
if datetime.now() > rto_deadline:
|
|
violations.append({
|
|
"system": sys.name,
|
|
"tier": sys.tier,
|
|
"rto_hours": sys.rto_hours,
|
|
"deadline": rto_deadline.isoformat(),
|
|
"status": sys.status,
|
|
"exceeded_by_hours": round(
|
|
(datetime.now() - rto_deadline).total_seconds() / 3600, 1
|
|
),
|
|
})
|
|
return violations
|
|
|
|
def get_recovery_progress(self) -> dict:
|
|
"""Calculate overall recovery progress."""
|
|
total = len(self.plan.systems)
|
|
if total == 0:
|
|
return {"progress": 0, "by_status": {}, "by_tier": {}}
|
|
|
|
by_status = {}
|
|
by_tier = {}
|
|
for sys in self.plan.systems:
|
|
by_status[sys.status] = by_status.get(sys.status, 0) + 1
|
|
tier_key = f"tier_{sys.tier}"
|
|
if tier_key not in by_tier:
|
|
by_tier[tier_key] = {"total": 0, "online": 0}
|
|
by_tier[tier_key]["total"] += 1
|
|
if sys.status == "online":
|
|
by_tier[tier_key]["online"] += 1
|
|
|
|
online = by_status.get("online", 0)
|
|
return {
|
|
"progress": round((online / total) * 100, 1),
|
|
"total_systems": total,
|
|
"by_status": by_status,
|
|
"by_tier": by_tier,
|
|
}
|
|
|
|
def get_next_recoverable(self) -> list:
|
|
"""Get list of systems ready for recovery (dependencies met)."""
|
|
ready = []
|
|
for sys in self.plan.systems:
|
|
if sys.status != "pending":
|
|
continue
|
|
deps_met = all(
|
|
next((s for s in self.plan.systems if s.name == dep), None) is not None
|
|
and next((s for s in self.plan.systems if s.name == dep)).status == "online"
|
|
for dep in sys.dependencies
|
|
)
|
|
if deps_met or not sys.dependencies:
|
|
ready.append(sys)
|
|
return sorted(ready, key=lambda s: s.tier)
|
|
|
|
def generate_report(self) -> str:
|
|
lines = []
|
|
lines.append("=" * 70)
|
|
lines.append("RANSOMWARE RECOVERY STATUS REPORT")
|
|
lines.append("=" * 70)
|
|
lines.append(f"Incident: {self.plan.incident_id}")
|
|
lines.append(f"Organization: {self.plan.organization}")
|
|
lines.append(f"Recovery Started: {self.plan.recovery_start}")
|
|
lines.append(f"Compromise Date: {self.plan.compromise_date}")
|
|
|
|
progress = self.get_recovery_progress()
|
|
lines.append(f"\nOverall Progress: {progress['progress']}%")
|
|
lines.append(f"Total Systems: {progress['total_systems']}")
|
|
|
|
for status, count in progress["by_status"].items():
|
|
lines.append(f" {status}: {count}")
|
|
|
|
lines.append("\nBy Tier:")
|
|
for tier, data in sorted(progress["by_tier"].items()):
|
|
lines.append(f" {tier}: {data['online']}/{data['total']} online")
|
|
|
|
# RTO violations
|
|
violations = self.check_rto_compliance()
|
|
if violations:
|
|
lines.append(f"\nRTO VIOLATIONS ({len(violations)}):")
|
|
for v in violations:
|
|
lines.append(f" {v['system']} (Tier {v['tier']}): "
|
|
f"RTO {v['rto_hours']}h exceeded by {v['exceeded_by_hours']}h")
|
|
|
|
# System details
|
|
lines.append("\nSystem Recovery Status:")
|
|
lines.append("-" * 50)
|
|
for tier in sorted(set(s.tier for s in self.plan.systems)):
|
|
tier_systems = [s for s in self.plan.systems if s.tier == tier]
|
|
lines.append(f"\n Tier {tier}:")
|
|
for sys in tier_systems:
|
|
status_icon = {"pending": "[ ]", "restoring": "[~]", "validating": "[?]",
|
|
"online": "[+]", "failed": "[X]"}.get(sys.status, "[?]")
|
|
lines.append(f" {status_icon} {sys.name} ({sys.system_type}) - {sys.status}")
|
|
if sys.restore_start and sys.restore_end:
|
|
start = datetime.fromisoformat(sys.restore_start)
|
|
end = datetime.fromisoformat(sys.restore_end)
|
|
duration = (end - start).total_seconds() / 3600
|
|
lines.append(f" Restore time: {duration:.1f} hours")
|
|
if sys.validation_checks:
|
|
for check, passed in sys.validation_checks.items():
|
|
result = "PASS" if passed else "FAIL"
|
|
lines.append(f" {check}: {result}")
|
|
|
|
# Next recoverable systems
|
|
ready = self.get_next_recoverable()
|
|
if ready:
|
|
lines.append(f"\nReady for Recovery ({len(ready)}):")
|
|
for sys in ready:
|
|
lines.append(f" - {sys.name} (Tier {sys.tier}, {sys.system_type})")
|
|
|
|
lines.append("\n" + "=" * 70)
|
|
return "\n".join(lines)
|
|
|
|
def export_plan(self, output_path: str):
|
|
with open(output_path, "w") as f:
|
|
json.dump(asdict(self.plan), f, indent=2)
|
|
|
|
|
|
def main():
|
|
"""Demo recovery orchestration."""
|
|
orch = RecoveryOrchestrator(
|
|
incident_id="INC-2026-0042",
|
|
org_name="Acme Manufacturing",
|
|
compromise_date="2026-02-20T03:00:00",
|
|
)
|
|
|
|
# Define systems with dependencies
|
|
orch.add_system(RecoverableSystem(
|
|
name="DC01", tier=1, system_type="dc", rto_hours=4,
|
|
))
|
|
orch.add_system(RecoverableSystem(
|
|
name="DC02", tier=1, system_type="dc", rto_hours=4,
|
|
))
|
|
orch.add_system(RecoverableSystem(
|
|
name="DNS01", tier=1, system_type="dns", rto_hours=4,
|
|
dependencies=["DC01"],
|
|
))
|
|
orch.add_system(RecoverableSystem(
|
|
name="SQL-ERP", tier=1, system_type="database", rto_hours=8,
|
|
dependencies=["DC01", "DNS01"],
|
|
))
|
|
orch.add_system(RecoverableSystem(
|
|
name="ERP-APP", tier=1, system_type="application", rto_hours=12,
|
|
dependencies=["SQL-ERP", "DC01"],
|
|
))
|
|
orch.add_system(RecoverableSystem(
|
|
name="Exchange", tier=2, system_type="email", rto_hours=12,
|
|
dependencies=["DC01", "DC02"],
|
|
))
|
|
orch.add_system(RecoverableSystem(
|
|
name="FileServer01", tier=2, system_type="fileserver", rto_hours=24,
|
|
dependencies=["DC01"],
|
|
))
|
|
orch.add_system(RecoverableSystem(
|
|
name="WebApp01", tier=2, system_type="web", rto_hours=24,
|
|
dependencies=["SQL-ERP"],
|
|
))
|
|
orch.add_system(RecoverableSystem(
|
|
name="DevServer", tier=3, system_type="other", rto_hours=48,
|
|
dependencies=["DC01"],
|
|
))
|
|
|
|
# Simulate recovery progress
|
|
orch.start_restore("DC01", "Immutable Veeam Hardened Repo")
|
|
orch.complete_restore("DC01")
|
|
orch.validate_system("DC01", {
|
|
"dcdiag": True, "repadmin": True, "dns_resolution": True,
|
|
"krbtgt_reset": True, "persistence_scan": True,
|
|
})
|
|
|
|
orch.start_restore("DC02", "Immutable Veeam Hardened Repo")
|
|
orch.complete_restore("DC02")
|
|
orch.validate_system("DC02", {
|
|
"dcdiag": True, "repadmin": True, "replication": True,
|
|
})
|
|
|
|
orch.start_restore("DNS01", "Immutable Veeam Hardened Repo")
|
|
|
|
print(orch.generate_report())
|
|
|
|
output_path = str(Path(__file__).parent / "recovery_plan.json")
|
|
orch.export_plan(output_path)
|
|
print(f"\nRecovery plan exported to: {output_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|