#!/usr/bin/env python3
"""Cloudflare Access zero trust audit agent using Cloudflare API."""

import json
import sys
import argparse
from datetime import datetime

try:
    import requests
except ImportError:
    print("Install: pip install requests")
    sys.exit(1)


class CloudflareAccessClient:
    """Cloudflare Access API client."""

    def __init__(self, api_token, account_id):
        self.base = f"https://api.cloudflare.com/client/v4/accounts/{account_id}/access"
        self.headers = {"Authorization": f"Bearer {api_token}", "Content-Type": "application/json"}

    def _get(self, endpoint):
        resp = requests.get(f"{self.base}/{endpoint}", headers=self.headers, timeout=30)
        resp.raise_for_status()
        return resp.json()

    def list_applications(self):
        return self._get("apps")

    def list_policies(self, app_id):
        return self._get(f"apps/{app_id}/policies")

    def list_groups(self):
        return self._get("groups")

    def list_identity_providers(self):
        return self._get("identity_providers")

    def list_service_tokens(self):
        return self._get("service_tokens")


def audit_access_config(client):
    """Audit Cloudflare Access configuration."""
    findings = []
    apps = client.list_applications()
    for app in apps.get("result", []):
        if not app.get("session_duration"):
            findings.append({
                "type": "no_session_timeout",
                "app": app.get("name", ""),
                "severity": "MEDIUM",
            })
    tokens = client.list_service_tokens()
    for token in tokens.get("result", []):
        if token.get("expires_at"):
            expiry = datetime.fromisoformat(token["expires_at"].replace("Z", "+00:00"))
            if expiry.replace(tzinfo=None) < datetime.utcnow():
                findings.append({
                    "type": "expired_service_token",
                    "token_name": token.get("name", ""),
                    "severity": "HIGH",
                })
    return findings


def run_audit(api_token, account_id):
    """Execute Cloudflare Access audit."""
    client = CloudflareAccessClient(api_token, account_id)
    print(f"\n{'='*60}")
    print(f"  CLOUDFLARE ACCESS ZERO TRUST AUDIT")
    print(f"  Generated: {datetime.utcnow().isoformat()} UTC")
    print(f"{'='*60}\n")

    apps = client.list_applications()
    app_list = apps.get("result", [])
    print(f"--- APPLICATIONS ({len(app_list)}) ---")
    for a in app_list[:10]:
        print(f"  {a.get('name', '')}: domain={a.get('domain', '')} type={a.get('type', '')}")

    idps = client.list_identity_providers()
    idp_list = idps.get("result", [])
    print(f"\n--- IDENTITY PROVIDERS ({len(idp_list)}) ---")
    for idp in idp_list:
        print(f"  {idp.get('name', '')}: type={idp.get('type', '')}")

    findings = audit_access_config(client)
    print(f"\n--- FINDINGS ({len(findings)}) ---")
    for f in findings:
        print(f"  [{f['severity']}] {f['type']}: {f.get('app', f.get('token_name', ''))}")

    return {"apps": len(app_list), "idps": len(idp_list), "findings": findings}


def main():
    parser = argparse.ArgumentParser(description="Cloudflare Access Audit Agent")
    parser.add_argument("--api-token", required=True, help="Cloudflare API token")
    parser.add_argument("--account-id", required=True, help="Cloudflare account ID")
    parser.add_argument("--output", help="Save report to JSON file")
    args = parser.parse_args()

    report = run_audit(args.api_token, args.account_id)
    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()
