#!/usr/bin/env python3
"""Cisco ISE NAC Agent - audits ISE policies, endpoint posture, and 802.1X configuration."""

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 ise_request(base_url, username, password, endpoint):
    """Execute Cisco ISE ERS API request."""
    cmd = ["curl", "-s", "-k", "-u", f"{username}:{password}",
           "-H", "Accept: application/json",
           f"{base_url}/ers/config{endpoint}"]
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
    return json.loads(result.stdout) if result.stdout else {}


def get_network_devices(base_url, user, pw):
    return ise_request(base_url, user, pw, "/networkdevice?size=100")


def get_endpoint_groups(base_url, user, pw):
    return ise_request(base_url, user, pw, "/endpointgroup")


def get_authorization_policies(base_url, user, pw):
    return ise_request(base_url, user, pw, "/authorizationprofile?size=100")


def get_active_sessions(base_url, user, pw):
    """Get active RADIUS sessions via MnT API."""
    cmd = ["curl", "-s", "-k", "-u", f"{user}:{pw}",
           "-H", "Accept: application/json",
           f"{base_url}/admin/API/mnt/Session/ActiveList"]
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
    return json.loads(result.stdout) if result.stdout else {}


def audit_authorization_profiles(profiles):
    """Audit authorization profiles for security best practices."""
    findings = []
    for profile in profiles.get("SearchResult", {}).get("resources", []):
        name = profile.get("name", "")
        if "permit" in name.lower() and "all" in name.lower():
            findings.append({"profile": name, "issue": "overly_permissive_profile", "severity": "high"})
    return findings


def analyze_session_data(sessions):
    """Analyze active session posture and authentication methods."""
    auth_methods = defaultdict(int)
    posture_status = defaultdict(int)
    failed_auths = 0
    for session in sessions:
        method = session.get("authentication_method", "unknown")
        auth_methods[method] += 1
        posture = session.get("posture_status", "unknown")
        posture_status[posture] += 1
        if session.get("authentication_status") == "failed":
            failed_auths += 1
    return {
        "total_sessions": len(sessions),
        "auth_methods": dict(auth_methods),
        "posture_distribution": dict(posture_status),
        "failed_authentications": failed_auths,
    }


def check_dot1x_compliance(devices):
    """Check 802.1X deployment across network devices."""
    device_list = devices.get("SearchResult", {}).get("resources", [])
    dot1x_enabled = sum(1 for d in device_list if d.get("NetworkDeviceIPList"))
    return {
        "total_devices": len(device_list),
        "dot1x_capable": dot1x_enabled,
        "coverage_percent": round(dot1x_enabled / max(len(device_list), 1) * 100, 1),
    }


def generate_report(devices, profiles, sessions, base_url):
    profile_audit = audit_authorization_profiles(profiles)
    session_analysis = analyze_session_data(sessions)
    dot1x = check_dot1x_compliance(devices)
    report = {
        "timestamp": datetime.utcnow().isoformat(),
        "ise_url": base_url,
        "dot1x_deployment": dot1x,
        "session_analysis": session_analysis,
        "authorization_profile_findings": profile_audit,
        "total_findings": len(profile_audit),
    }
    return report


def main():
    parser = argparse.ArgumentParser(description="Cisco ISE NAC Audit Agent")
    parser.add_argument("--ise-url", required=True, help="ISE admin URL (https://ise.example.com:9060)")
    parser.add_argument("--username", required=True, help="ISE ERS API username")
    parser.add_argument("--password", required=True, help="ISE ERS API password")
    parser.add_argument("--output", default="ise_nac_report.json")
    args = parser.parse_args()

    devices = get_network_devices(args.ise_url, args.username, args.password)
    profiles = get_authorization_policies(args.ise_url, args.username, args.password)
    sessions = get_active_sessions(args.ise_url, args.username, args.password)
    report = generate_report(devices, profiles, sessions, args.ise_url)
    with open(args.output, "w") as f:
        json.dump(report, f, indent=2, default=str)
    logger.info("ISE audit: 802.1X coverage %.1f%%, %d active sessions, %d findings",
                report["dot1x_deployment"]["coverage_percent"],
                report["session_analysis"]["total_sessions"], report["total_findings"])
    print(json.dumps(report, indent=2, default=str))


if __name__ == "__main__":
    main()
