#!/usr/bin/env python3
"""osquery endpoint monitoring agent for security auditing."""

import json
import argparse
import subprocess
from datetime import datetime


SECURITY_QUERIES = {
    "listening_ports": "SELECT p.pid, p.name, l.port, l.protocol, l.address FROM listening_ports l JOIN processes p ON l.pid = p.pid WHERE l.port != 0",
    "suid_binaries": "SELECT path, username, permissions FROM suid_bin",
    "crontab_entries": "SELECT command, path, event FROM crontab",
    "authorized_keys": "SELECT uid, username, key_file FROM authorized_keys",
    "logged_in_users": "SELECT user, host, type, time FROM logged_in_users",
    "kernel_modules": "SELECT name, size, used_by, status FROM kernel_modules WHERE status = 'Live'",
    "processes_high_cpu": "SELECT pid, name, uid, resident_size, percent_processor_time FROM processes WHERE percent_processor_time > 50",
    "docker_containers": "SELECT id, name, image, status, started_at FROM docker_containers",
    "browser_extensions": "SELECT name, identifier, version, path, browser_type FROM chrome_extensions UNION ALL SELECT name, identifier, version, path, browser_type FROM firefox_addons",
    "startup_items": "SELECT name, path, source FROM startup_items",
}


def run_osquery(query, output_format="json"):
    """Execute osquery and return results."""
    cmd = ["osqueryi", f"--{output_format}", query]
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
        if output_format == "json" and result.stdout.strip():
            return json.loads(result.stdout)
        return [{"raw": result.stdout[:1000]}]
    except FileNotFoundError:
        return [{"error": "osquery not installed. Install from https://osquery.io/downloads/"}]
    except (json.JSONDecodeError, subprocess.TimeoutExpired) as e:
        return [{"error": str(e)}]


def check_fleet_status(fleet_url, api_token):
    """Check Fleet server host enrollment status."""
    import requests
    headers = {"Authorization": f"Bearer {api_token}"}
    try:
        resp = requests.get(f"{fleet_url}/api/v1/fleet/hosts", headers=headers, timeout=10)
        resp.raise_for_status()
        hosts = resp.json().get("hosts", [])
        return [{
            "hostname": h.get("hostname", ""),
            "platform": h.get("platform", ""),
            "osquery_version": h.get("osquery_version", ""),
            "status": h.get("status", ""),
            "last_seen": h.get("seen_time", ""),
        } for h in hosts]
    except Exception as e:
        return [{"error": str(e)}]


def run_audit(queries=None, fleet_url=None, api_token=None):
    """Execute osquery security audit."""
    print(f"\n{'='*60}")
    print(f"  OSQUERY ENDPOINT MONITORING AUDIT")
    print(f"  Generated: {datetime.utcnow().isoformat()} UTC")
    print(f"{'='*60}\n")

    selected = queries or list(SECURITY_QUERIES.keys())
    results = {}
    for name in selected:
        if name in SECURITY_QUERIES:
            data = run_osquery(SECURITY_QUERIES[name])
            results[name] = data
            count = len(data) if isinstance(data, list) else 0
            print(f"--- {name.upper()} ({count} results) ---")
            for row in (data[:5] if isinstance(data, list) else []):
                if "error" not in row:
                    print(f"  {json.dumps(row)[:100]}")

    if fleet_url and api_token:
        fleet = check_fleet_status(fleet_url, api_token)
        results["fleet_hosts"] = fleet
        print(f"\n--- FLEET HOSTS ({len(fleet)}) ---")
        for h in fleet[:10]:
            if "error" not in h:
                print(f"  {h['hostname']}: {h['platform']} ({h['status']})")

    return results


def main():
    parser = argparse.ArgumentParser(description="osquery Monitoring Agent")
    parser.add_argument("--queries", nargs="+", choices=list(SECURITY_QUERIES.keys()),
                        help="Specific queries to run")
    parser.add_argument("--fleet-url", help="Fleet server URL")
    parser.add_argument("--api-token", help="Fleet API token")
    parser.add_argument("--output", help="Save report to JSON file")
    args = parser.parse_args()

    report = run_audit(args.queries, args.fleet_url, args.api_token)
    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}")


if __name__ == "__main__":
    main()
