Files
vm-cloudflare/mcp/waf_intelligence/orchestrator.py
Vault Sovereign f0b8d962de
Some checks failed
WAF Intelligence Guardrail / waf-intel (push) Waiting to run
Cloudflare Registry Validation / validate-registry (push) Has been cancelled
chore: pre-migration snapshot
Layer0, MCP servers, Terraform consolidation
2025-12-27 01:52:27 +00:00

378 lines
12 KiB
Python

from __future__ import annotations
import os
from dataclasses import dataclass, field
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional
from .analyzer import AnalysisResult, RuleViolation, WAFRuleAnalyzer
from .compliance import ComplianceMapper, FrameworkMapping
from .generator import GeneratedRule, WAFRuleGenerator
# Optional advanced modules (Phase 7)
try:
from .threat_intel import (
ThreatIntelCollector,
ThreatIntelReport,
ThreatIndicator,
)
_HAS_THREAT_INTEL = True
except ImportError:
_HAS_THREAT_INTEL = False
ThreatIntelCollector = None
try:
from .classifier import ThreatClassifier
_HAS_CLASSIFIER = True
except ImportError:
_HAS_CLASSIFIER = False
ThreatClassifier = None
@dataclass
class WAFInsight:
"""Single high-quality insight across analysis + generation + compliance."""
violation: RuleViolation | None
suggested_rule: GeneratedRule | None
mappings: List[FrameworkMapping]
@dataclass
class ThreatAssessment:
"""Phase 7: Comprehensive threat assessment result."""
analysis_result: Optional[AnalysisResult] = None
threat_report: Optional[Any] = None # ThreatIntelReport when available
classification_summary: Dict[str, int] = field(default_factory=dict)
risk_score: float = 0.0
recommended_actions: List[str] = field(default_factory=list)
generated_at: datetime = field(default_factory=datetime.utcnow)
@property
def risk_level(self) -> str:
if self.risk_score >= 0.8:
return "critical"
elif self.risk_score >= 0.6:
return "high"
elif self.risk_score >= 0.4:
return "medium"
else:
return "low"
class WAFIntelligence:
"""
Quality-first orchestration layer:
- analyze WAF config
- propose a few rules
- attach compliance mappings
- Phase 7: integrate threat intel and ML classification
"""
def __init__(
self,
workspace_path: Optional[str] = None,
enable_threat_intel: bool = True,
enable_ml_classifier: bool = True,
) -> None:
self.workspace = Path(workspace_path) if workspace_path else Path.cwd()
# Core components
self.analyzer = WAFRuleAnalyzer()
self.generator = WAFRuleGenerator()
self.mapper = ComplianceMapper()
# Phase 7 components (optional)
self.threat_intel: Optional[Any] = None
self.classifier: Optional[Any] = None
if enable_threat_intel and _HAS_THREAT_INTEL:
try:
self.threat_intel = ThreatIntelCollector()
except Exception:
pass
if enable_ml_classifier and _HAS_CLASSIFIER:
try:
self.classifier = ThreatClassifier()
except Exception:
pass
def analyze_and_recommend(
self,
path: str,
*,
limit: int = 3,
min_severity: str = "warning",
) -> List[WAFInsight]:
analysis: AnalysisResult = self.analyzer.analyze_file(
path,
min_severity=min_severity,
)
top_violations = analysis.top_violations(
min_severity=min_severity,
limit=limit,
)
insights: List[WAFInsight] = []
for violation in top_violations:
mappings = self.mapper.best_effort_from_violation(violation.message)
scenario = violation.message
rules = self.generator.generate_from_scenario(scenario, limit=1)
suggested = rules[0] if rules else None
insights.append(
WAFInsight(
violation=violation,
suggested_rule=suggested,
mappings=mappings,
)
)
return insights
# ─────────────────────────────────────────────────────────────────────────
# Phase 7: Advanced threat intelligence methods
# ─────────────────────────────────────────────────────────────────────────
def collect_threat_intel(
self,
log_paths: Optional[List[str]] = None,
max_indicators: int = 100,
) -> Optional[Any]:
"""
Collect threat intelligence from logs and external feeds.
Args:
log_paths: Paths to Cloudflare log files
max_indicators: Maximum indicators to collect
Returns:
ThreatIntelReport or None if unavailable
"""
if not self.threat_intel:
return None
# Default log paths
if log_paths is None:
log_paths = [
str(self.workspace / "logs"),
"/var/log/cloudflare",
]
return self.threat_intel.collect(
log_paths=log_paths,
max_indicators=max_indicators,
)
def classify_threat(self, payload: str) -> Optional[Any]:
"""
Classify a payload using ML classifier.
Args:
payload: Request payload to classify
Returns:
ClassificationResult or None
"""
if not self.classifier:
return None
return self.classifier.classify(payload)
def full_assessment(
self,
waf_config_path: Optional[str] = None,
log_paths: Optional[List[str]] = None,
include_threat_intel: bool = True,
) -> ThreatAssessment:
"""
Phase 7: Perform comprehensive threat assessment.
Combines:
- WAF configuration analysis
- Threat intelligence collection
- ML classification summary
- Risk scoring
Args:
waf_config_path: Path to WAF Terraform file
log_paths: Paths to log files
include_threat_intel: Whether to collect threat intel
Returns:
ThreatAssessment with full analysis results
"""
assessment = ThreatAssessment()
risk_factors: List[float] = []
recommendations: List[str] = []
# 1. Analyze WAF configuration
if waf_config_path is None:
waf_config_path = str(self.workspace / "terraform" / "waf.tf")
if Path(waf_config_path).exists():
assessment.analysis_result = self.analyzer.analyze_file(
waf_config_path,
min_severity="info",
)
# Calculate risk from violations
severity_weights = {"error": 0.8, "warning": 0.5, "info": 0.2}
for violation in assessment.analysis_result.violations:
weight = severity_weights.get(violation.severity, 0.3)
risk_factors.append(weight)
# Generate recommendations
critical_count = sum(
1
for v in assessment.analysis_result.violations
if v.severity == "error"
)
if critical_count > 0:
recommendations.append(
f"🔴 Fix {critical_count} critical WAF configuration issues"
)
# 2. Collect threat intelligence
if include_threat_intel and self.threat_intel:
try:
assessment.threat_report = self.collect_threat_intel(
log_paths=log_paths,
max_indicators=50,
)
if assessment.threat_report:
indicators = assessment.threat_report.indicators
# Count by severity
severity_counts = {"critical": 0, "high": 0, "medium": 0, "low": 0}
for ind in indicators:
sev = getattr(ind, "severity", "low")
severity_counts[sev] = severity_counts.get(sev, 0) + 1
# Add to classification summary
assessment.classification_summary["threat_indicators"] = len(
indicators
)
assessment.classification_summary.update(severity_counts)
# Calculate threat intel risk
if indicators:
critical_ratio = severity_counts["critical"] / len(indicators)
high_ratio = severity_counts["high"] / len(indicators)
risk_factors.append(critical_ratio * 0.9 + high_ratio * 0.7)
if severity_counts["critical"] > 0:
recommendations.append(
f"🚨 Block {severity_counts['critical']} critical threat IPs immediately"
)
except Exception:
pass
# 3. ML classification summary (from any collected data)
if self.classifier and assessment.threat_report:
try:
attack_types = {"sqli": 0, "xss": 0, "rce": 0, "clean": 0, "unknown": 0}
indicators = assessment.threat_report.indicators
pattern_indicators = [
i
for i in indicators
if getattr(i, "indicator_type", "") == "pattern"
]
for ind in pattern_indicators[:20]: # Sample first 20
result = self.classifier.classify(ind.value)
if result:
label = result.label
attack_types[label] = attack_types.get(label, 0) + 1
assessment.classification_summary["ml_classifications"] = attack_types
# Add ML risk factor
dangerous = attack_types.get("sqli", 0) + attack_types.get("rce", 0)
if dangerous > 5:
risk_factors.append(0.8)
recommendations.append(
f"⚠️ ML detected {dangerous} dangerous attack patterns"
)
except Exception:
pass
# 4. Calculate final risk score
if risk_factors:
assessment.risk_score = min(
1.0, sum(risk_factors) / max(len(risk_factors), 1)
)
else:
assessment.risk_score = 0.3 # Baseline risk
assessment.recommended_actions = recommendations
return assessment
def generate_gitops_proposals(
self,
threat_report: Optional[Any] = None,
max_proposals: int = 5,
) -> List[Dict[str, Any]]:
"""
Generate GitOps-ready rule proposals.
Args:
threat_report: ThreatIntelReport to use
max_proposals: Maximum proposals to generate
Returns:
List of proposal dicts ready for MR creation
"""
proposals: List[Dict[str, Any]] = []
if not threat_report:
return proposals
try:
# Import proposer dynamically
from gitops.waf_rule_proposer import WAFRuleProposer
proposer = WAFRuleProposer(workspace_path=str(self.workspace))
batch = proposer.generate_proposals(
threat_report=threat_report,
max_proposals=max_proposals,
)
for proposal in batch.proposals:
proposals.append(
{
"name": proposal.rule_name,
"type": proposal.rule_type,
"severity": proposal.severity,
"confidence": proposal.confidence,
"terraform": proposal.terraform_code,
"justification": proposal.justification,
"auto_deploy": proposal.auto_deploy_eligible,
}
)
except ImportError:
pass
return proposals
@property
def capabilities(self) -> Dict[str, bool]:
"""Report available capabilities."""
return {
"core_analysis": True,
"rule_generation": True,
"compliance_mapping": True,
"threat_intel": self.threat_intel is not None,
"ml_classification": self.classifier is not None,
}