#!/usr/bin/env python3
"""
CubicSec API Security Assessment Tool
--------------------------------------
A lightweight, interactive CLI scanner to evaluate the security posture of an API endpoint.
Scans for:
- Missing HTTP Security Headers
- Allowed HTTP Methods
- SSL/TLS Configurations

Usage:
  python api-security-assessment-tool.py <api_url>
"""

import sys
import urllib.request
import ssl
from urllib.error import URLError, HTTPError

# Core color configurations for high-tech visual output
GREEN = "\033[92m"
YELLOW = "\033[93m"
RED = "\033[91m"
BLUE = "\033[94m"
RESET = "\033[0m"
BOLD = "\033[1m"

ESSENTIAL_HEADERS = {
    "Content-Security-Policy": "Prevents cross-site scripting (XSS) and other injection attacks.",
    "Strict-Transport-Security": "Forces connection over HTTPS to prevent eavesdropping/MITM.",
    "X-Frame-Options": "Prevents Clickjacking attacks by controlling frame embedding.",
    "X-Content-Type-Options": "Prevents MIME-type sniffing.",
    "Referrer-Policy": "Controls how much referrer info is passed during navigation.",
    "Permissions-Policy": "Restricts browser feature usage (camera, location, etc.)."
}

def print_banner():
    print(f"{BLUE}{BOLD}================================================================{RESET}")
    print(f"{BLUE}{BOLD}           CUBICSEC API SECURITY ASSESSMENT TOOL                {RESET}")
    print(f"{BLUE}{BOLD}================================================================{RESET}\n")

def analyze_headers(headers):
    print(f"{BOLD}[+] Analyzing Security Headers...{RESET}")
    missing_headers = []
    found_headers = []

    for header, desc in ESSENTIAL_HEADERS.items():
        # Case insensitive check
        matching = [val for key, val in headers if key.lower() == header.lower()]
        if matching:
            found_headers.append((header, matching[0]))
        else:
            missing_headers.append((header, desc))

    for h, val in found_headers:
        print(f"  {GREEN}[✔] {h}:{RESET} {val[:50]}...")

    if missing_headers:
        print(f"\n{YELLOW}[!] Warnings - Missing Security Headers:{RESET}")
        for h, desc in missing_headers:
            print(f"  {RED}[✗] {h}:{RESET} {desc}")
    else:
        print(f"\n{GREEN}[✔] Excellent! All standard security headers are present.{RESET}")
    
    print("-" * 64)

def check_methods(url):
    print(f"{BOLD}[+] Checking Exposed HTTP Methods (OPTIONS request)...{RESET}")
    req = urllib.request.Request(url, method="OPTIONS")
    try:
        with urllib.request.urlopen(req, context=ssl._create_unverified_context()) as response:
            allow = response.headers.get("Allow")
            if allow:
                print(f"  {GREEN}[✔] Allowed Methods:{RESET} {allow}")
            else:
                print(f"  {YELLOW}[!] Options header present but 'Allow' missing.{RESET}")
    except HTTPError as e:
        print(f"  {YELLOW}[!] OPTIONS request returned HTTP {e.code}. Active method scanning blocked.{RESET}")
    except Exception as e:
        print(f"  {YELLOW}[!] Method scan failed: {str(e)}{RESET}")
    
    print("-" * 64)

def main():
    print_banner()
    if len(sys.argv) < 2:
        print(f"{RED}Usage:{RESET} python api-security-assessment-tool.py <target_api_url>")
        print("Example: python api-security-assessment-tool.py https://api.github.com")
        sys.exit(1)

    url = sys.argv[1]
    if not url.startswith("http://") and not url.startswith("https://"):
        url = "https://" + url

    print(f"{BOLD}[*] Scanning Target URL:{RESET} {url}")
    print("-" * 64)

    # Core request
    try:
        ctx = ssl.create_default_context()
        req = urllib.request.Request(url, headers={"User-Agent": "CubicSec-APIScanner/1.0"})
        with urllib.request.urlopen(req, context=ctx) as response:
            headers = response.getheaders()
            print(f"{GREEN}[✔] SSL/TLS handshake successful.{RESET}")
            print(f"{GREEN}[✔] Target responded with Status {response.status} OK.{RESET}\n")
            analyze_headers(headers)
    except URLError as e:
        if isinstance(e.reason, ssl.SSLError):
            print(f"{RED}[✗] SSL/TLS Configuration Error: {e.reason}{RESET}")
        else:
            print(f"{RED}[✗] Connection Error: {e.reason}{RESET}")
        sys.exit(1)
    except Exception as e:
        print(f"{RED}[✗] Unexpected Error: {str(e)}{RESET}")
        sys.exit(1)

    check_methods(url)
    print(f"\n{BLUE}{BOLD}[*] Scan Completed. Secure your APIs with CubicSec.{RESET}")

if __name__ == "__main__":
    main()
