chore: pre-migration snapshot
Layer0, MCP servers, Terraform consolidation
This commit is contained in:
@@ -1,9 +1,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
MANAGED_WAF_RULESET_IDS = (
|
||||
# Cloudflare managed WAF ruleset IDs (last updated 2025-12-18).
|
||||
"efb7b8c949ac4650a09736fc376e9aee", # Cloudflare Managed Ruleset
|
||||
"4814384a9e5d4991b9815dcfc25d2f1f", # OWASP Core Ruleset
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class RuleViolation:
|
||||
@@ -57,6 +64,20 @@ class WAFRuleAnalyzer:
|
||||
Analyze Cloudflare WAF rules from Terraform with a quality-first posture.
|
||||
"""
|
||||
|
||||
def _has_managed_waf_rules(self, text: str) -> bool:
|
||||
text_lower = text.lower()
|
||||
|
||||
if "managed_rules" in text_lower:
|
||||
return True
|
||||
|
||||
if re.search(r'phase\s*=\s*"http_request_firewall_managed"', text_lower):
|
||||
return True
|
||||
|
||||
if "cf.waf" in text_lower:
|
||||
return True
|
||||
|
||||
return any(ruleset_id in text_lower for ruleset_id in MANAGED_WAF_RULESET_IDS)
|
||||
|
||||
def analyze_file(
|
||||
self,
|
||||
path: str | Path,
|
||||
@@ -70,7 +91,7 @@ class WAFRuleAnalyzer:
|
||||
violations: List[RuleViolation] = []
|
||||
|
||||
# Example heuristic: no managed rules present
|
||||
if "managed_rules" not in text:
|
||||
if not self._has_managed_waf_rules(text):
|
||||
violations.append(
|
||||
RuleViolation(
|
||||
rule_id=None,
|
||||
@@ -102,7 +123,7 @@ class WAFRuleAnalyzer:
|
||||
violations=violations,
|
||||
metadata={
|
||||
"file_size": path.stat().st_size,
|
||||
"heuristics_version": "0.2.0",
|
||||
"heuristics_version": "0.3.0",
|
||||
},
|
||||
)
|
||||
|
||||
@@ -125,7 +146,7 @@ class WAFRuleAnalyzer:
|
||||
tmp_path = Path(source_name)
|
||||
violations: List[RuleViolation] = []
|
||||
|
||||
if "managed_rules" not in text:
|
||||
if not self._has_managed_waf_rules(text):
|
||||
violations.append(
|
||||
RuleViolation(
|
||||
rule_id=None,
|
||||
@@ -141,7 +162,7 @@ class WAFRuleAnalyzer:
|
||||
result = AnalysisResult(
|
||||
source=str(tmp_path),
|
||||
violations=violations,
|
||||
metadata={"heuristics_version": "0.2.0"},
|
||||
metadata={"heuristics_version": "0.3.0"},
|
||||
)
|
||||
|
||||
result.violations = result.top_violations(
|
||||
@@ -161,27 +182,37 @@ class WAFRuleAnalyzer:
|
||||
) -> AnalysisResult:
|
||||
"""
|
||||
Enhanced analysis using threat intelligence data.
|
||||
|
||||
|
||||
Args:
|
||||
path: WAF config file path
|
||||
threat_indicators: List of ThreatIndicator objects from threat_intel module
|
||||
min_severity: Minimum severity to include
|
||||
min_confidence: Minimum confidence threshold
|
||||
|
||||
|
||||
Returns:
|
||||
AnalysisResult with violations informed by threat intel
|
||||
"""
|
||||
# Start with base analysis
|
||||
base_result = self.analyze_file(path, min_severity=min_severity, min_confidence=min_confidence)
|
||||
|
||||
base_result = self.analyze_file(
|
||||
path, min_severity=min_severity, min_confidence=min_confidence
|
||||
)
|
||||
|
||||
path = Path(path)
|
||||
text = path.read_text(encoding="utf-8")
|
||||
text_lower = text.lower()
|
||||
|
||||
|
||||
# Check if threat indicators are addressed by existing rules
|
||||
critical_ips = [i for i in threat_indicators if i.indicator_type == "ip" and i.severity in ("critical", "high")]
|
||||
critical_patterns = [i for i in threat_indicators if i.indicator_type == "pattern" and i.severity in ("critical", "high")]
|
||||
|
||||
critical_ips = [
|
||||
i
|
||||
for i in threat_indicators
|
||||
if i.indicator_type == "ip" and i.severity in ("critical", "high")
|
||||
]
|
||||
critical_patterns = [
|
||||
i
|
||||
for i in threat_indicators
|
||||
if i.indicator_type == "pattern" and i.severity in ("critical", "high")
|
||||
]
|
||||
|
||||
# Check for IP blocking coverage
|
||||
if critical_ips:
|
||||
ip_block_present = "ip.src" in text_lower or "cf.client.ip" in text_lower
|
||||
@@ -197,14 +228,14 @@ class WAFRuleAnalyzer:
|
||||
hint=f"Add IP blocking rules for identified threat actors. Sample IPs: {', '.join(i.value for i in critical_ips[:3])}",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# Check for pattern-based attack coverage
|
||||
attack_types_seen = set()
|
||||
for ind in critical_patterns:
|
||||
for tag in ind.tags:
|
||||
if tag in ("sqli", "xss", "rce", "path_traversal"):
|
||||
attack_types_seen.add(tag)
|
||||
|
||||
|
||||
# Check managed ruleset coverage
|
||||
for attack_type in attack_types_seen:
|
||||
if attack_type not in text_lower and f'"{attack_type}"' not in text_lower:
|
||||
@@ -219,13 +250,12 @@ class WAFRuleAnalyzer:
|
||||
hint=f"Enable Cloudflare managed rules for {attack_type.upper()} protection.",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# Update metadata with threat intel stats
|
||||
base_result.metadata["threat_intel"] = {
|
||||
"critical_ips": len(critical_ips),
|
||||
"critical_patterns": len(critical_patterns),
|
||||
"attack_types_seen": list(attack_types_seen),
|
||||
}
|
||||
|
||||
return base_result
|
||||
|
||||
return base_result
|
||||
|
||||
Reference in New Issue
Block a user