#!/usr/bin/env python3
"""Windows event logging configuration audit agent."""

import json
import argparse
import subprocess
from datetime import datetime


CRITICAL_AUDIT_POLICIES = {
    "Logon/Logoff": {"Logon": "Success,Failure", "Logoff": "Success"},
    "Account Logon": {"Credential Validation": "Success,Failure", "Kerberos Authentication Service": "Success,Failure"},
    "Object Access": {"File System": "Success,Failure", "Registry": "Success,Failure"},
    "Privilege Use": {"Sensitive Privilege Use": "Success,Failure"},
    "Process Tracking": {"Process Creation": "Success"},
    "DS Access": {"Directory Service Access": "Success,Failure"},
    "Policy Change": {"Audit Policy Change": "Success,Failure", "Authentication Policy Change": "Success"},
}


def get_audit_policy():
    """Get current advanced audit policy configuration."""
    cmd = ["auditpol", "/get", "/category:*"]
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=15)
        lines = result.stdout.strip().split("\n")
        policies = {}
        current_category = ""
        for line in lines:
            stripped = line.strip()
            if not stripped or "Machine Name" in stripped or "Category" in stripped:
                continue
            if not stripped.startswith("  "):
                current_category = stripped
                policies[current_category] = {}
            else:
                parts = stripped.rsplit("  ", 1)
                if len(parts) == 2:
                    policies[current_category][parts[0].strip()] = parts[1].strip()
        return policies
    except (FileNotFoundError, subprocess.TimeoutExpired) as e:
        return {"error": str(e)}


def check_sysmon_installed():
    """Check if Sysmon is installed and running."""
    cmd = ["powershell", "-Command", "Get-Service Sysmon* | ConvertTo-Json"]
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=15)
        if result.stdout.strip():
            service = json.loads(result.stdout)
            if isinstance(service, list):
                service = service[0]
            return {"installed": True, "status": service.get("Status", ""),
                    "name": service.get("Name", "")}
        return {"installed": False, "severity": "HIGH",
                "recommendation": "Install Sysmon with SwiftOnSecurity config"}
    except (FileNotFoundError, json.JSONDecodeError):
        return {"installed": False}


def check_log_sizes():
    """Check event log maximum sizes."""
    logs = ["Security", "System", "Application", "Microsoft-Windows-Sysmon/Operational",
            "Microsoft-Windows-PowerShell/Operational"]
    results = []
    for log_name in logs:
        cmd = ["powershell", "-Command",
               f"(Get-WinEvent -ListLog '{log_name}' -ErrorAction SilentlyContinue).MaximumSizeInBytes"]
        try:
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
            size_bytes = int(result.stdout.strip()) if result.stdout.strip() else 0
            size_mb = round(size_bytes / (1024 * 1024), 1)
            results.append({
                "log": log_name,
                "max_size_mb": size_mb,
                "severity": "MEDIUM" if size_mb < 100 else "INFO",
            })
        except (ValueError, subprocess.TimeoutExpired):
            results.append({"log": log_name, "error": "Cannot query"})
    return results


def check_powershell_logging():
    """Check PowerShell script block logging and transcription."""
    checks = {}
    for name, path in [
        ("ScriptBlockLogging", r"HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"),
        ("Transcription", r"HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription"),
    ]:
        cmd = ["powershell", "-Command", f"Get-ItemProperty -Path '{path}' -ErrorAction SilentlyContinue | ConvertTo-Json"]
        try:
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
            checks[name] = json.loads(result.stdout) if result.stdout.strip() else {"enabled": False}
        except (json.JSONDecodeError, subprocess.TimeoutExpired):
            checks[name] = {"enabled": False}
    return checks


def run_audit():
    """Execute Windows event logging audit."""
    print(f"\n{'='*60}")
    print(f"  WINDOWS EVENT LOGGING AUDIT")
    print(f"  Generated: {datetime.utcnow().isoformat()} UTC")
    print(f"{'='*60}\n")

    sysmon = check_sysmon_installed()
    print(f"--- SYSMON ---")
    print(f"  Installed: {sysmon.get('installed', False)}")
    print(f"  Status: {sysmon.get('status', 'N/A')}")

    logs = check_log_sizes()
    print(f"\n--- LOG SIZES ---")
    for l in logs:
        if "error" not in l:
            print(f"  {l['log']}: {l['max_size_mb']} MB [{l['severity']}]")

    ps_logging = check_powershell_logging()
    print(f"\n--- POWERSHELL LOGGING ---")
    for name, config in ps_logging.items():
        enabled = config.get("EnableScriptBlockLogging", config.get("EnableTranscripting", False))
        print(f"  {name}: {'Enabled' if enabled else 'Disabled'}")

    return {"sysmon": sysmon, "log_sizes": logs, "powershell": ps_logging}


def main():
    parser = argparse.ArgumentParser(description="Windows Event Logging Audit Agent")
    parser.add_argument("--audit", action="store_true", help="Run full audit")
    parser.add_argument("--output", help="Save report to JSON file")
    args = parser.parse_args()

    if args.audit:
        report = run_audit()
        if args.output:
            with open(args.output, "w") as f:
                json.dump(report, f, indent=2, default=str)
            print(f"\n[+] Report saved to {args.output}")
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
