Files
mukul975 c47eed6a64 Production hardening: security fixes, code quality, 724 skills complete
- Fix 25 shell=True subprocess calls with list-based commands
- Fix 49 verify=False in defensive skills (env-var override)
- Add timeout to 231 HTTP/subprocess/socket calls
- Fix 6 SQL injection patterns with whitelist validation
- Replace 8 __import__() with standard imports
- Remove 701 unused imports across 442 files
- Add authorized-testing disclaimers to all offensive skills
- Complete 11 incomplete skill directories
- Expand 10 stub SKILL.md files with full content
- Fix 2 YAML parse errors in frontmatter
- Fix 5 pre-existing syntax errors
- Convert 22 hardcoded paths/ports to environment variables
- Back up 21 redundant skill pairs to .bak
- Fix 2 global declaration errors
- 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE)
- 0 compile errors across all 724 agent.py files
2026-03-19 13:26:49 +01:00

107 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""Firewall Zone Segmentation Agent - audits zone-based firewall rules and inter-zone traffic policies."""
import json
import argparse
import logging
import subprocess
from collections import defaultdict
from datetime import datetime
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
def parse_firewall_config(config_file):
with open(config_file) as f:
return json.load(f)
def get_iptables_zones():
cmd = ["iptables", "-L", "-n", "-v", "--line-numbers"]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
chains = defaultdict(list)
current_chain = ""
for line in result.stdout.split("\n"):
if line.startswith("Chain"):
current_chain = line.split()[1]
elif line.strip() and not line.startswith("num"):
chains[current_chain].append(line.strip())
return dict(chains)
def audit_zone_rules(config):
findings = []
rules = config.get("rules", [])
for rule in rules:
src_zone = rule.get("source_zone", "")
dst_zone = rule.get("destination_zone", "")
action = rule.get("action", "")
service = rule.get("service", "any")
if action == "allow" and service == "any":
findings.append({"rule_id": rule.get("id", ""), "source_zone": src_zone, "dest_zone": dst_zone,
"issue": "Allows all services between zones", "severity": "high"})
if action == "allow" and src_zone == "untrust" and dst_zone == "trust":
findings.append({"rule_id": rule.get("id", ""), "issue": "Inbound from untrust to trust zone", "severity": "critical"})
if rule.get("log") is False and action == "allow":
findings.append({"rule_id": rule.get("id", ""), "issue": "Allow rule without logging", "severity": "medium"})
return findings
def check_default_zone_policies(config):
issues = []
for zone in config.get("zones", []):
if zone.get("default_action", "deny") != "deny":
issues.append({"zone": zone.get("name"), "default_action": zone.get("default_action"),
"issue": "Default zone policy is not deny", "severity": "critical"})
return issues
def analyze_rule_shadowing(rules):
shadowed = []
for i, rule in enumerate(rules):
for j in range(i):
prev = rules[j]
if (prev.get("source_zone") == rule.get("source_zone") and
prev.get("destination_zone") == rule.get("destination_zone") and
prev.get("service") == "any" and prev.get("action") == "allow"):
shadowed.append({"rule_id": rule.get("id"), "shadowed_by": prev.get("id"), "severity": "low"})
break
return shadowed
def generate_report(config, zone_findings, default_issues, shadowed):
all_findings = zone_findings + default_issues + shadowed
report = {
"timestamp": datetime.utcnow().isoformat(),
"total_zones": len(config.get("zones", [])),
"total_rules": len(config.get("rules", [])),
"zone_rule_findings": zone_findings,
"default_policy_issues": default_issues,
"shadowed_rules": shadowed,
"total_findings": len(all_findings),
"critical_findings": sum(1 for f in all_findings if f.get("severity") == "critical"),
}
return report
def main():
parser = argparse.ArgumentParser(description="Firewall Zone Segmentation Audit Agent")
parser.add_argument("--config", required=True, help="Firewall zone config JSON file")
parser.add_argument("--output", default="zone_segmentation_report.json")
args = parser.parse_args()
config = parse_firewall_config(args.config)
zone_findings = audit_zone_rules(config)
default_issues = check_default_zone_policies(config)
shadowed = analyze_rule_shadowing(config.get("rules", []))
report = generate_report(config, zone_findings, default_issues, shadowed)
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
logger.info("Zone audit: %d zones, %d rules, %d findings", report["total_zones"], report["total_rules"], report["total_findings"])
print(json.dumps(report, indent=2, default=str))
if __name__ == "__main__":
main()