#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = ["curl-cffi>=0.13"]
# ///
# Generate one fresh legacy ESP ticket from an owned Airlock IAM trial whose
# active target application uses EspSignTicketEncoder and response header
# X-ESP-Ticket.
#
# Invocation:
#   uv run --script esp_oracle_ticket.py \
#     --base https://login-j61hrn.ch-1.airlock.cloud/login \
#     --application portal-application-id --email EMAIL --password PASSWORD \
#     --output ticket.txt
#
# No engagement-identifying header is sent: this helper targets only a researcher-owned vendor tenant.
# Prerequisites:
# - The caller owns the Airlock tenant and account.
# - The active config emits X-ESP-Ticket after successful application access.
# - Supply secrets from engagement credential rows; this file embeds none.

import argparse
from pathlib import Path
from curl_cffi import requests


def main() -> None:
    ap = argparse.ArgumentParser()
    ap.add_argument("--base", required=True, help="Loginapp base ending in /login")
    ap.add_argument("--application", default="portal-application-id")
    ap.add_argument("--email", required=True)
    ap.add_argument("--password", required=True)
    ap.add_argument("--output")
    args = ap.parse_args()

    base = args.base.rstrip("/")
    s = requests.Session(impersonate="chrome")
    ident = {}
    common = {**ident, "X-Same-Domain": "1", "Accept": "application/json, text/plain, */*"}

    r = s.get(f"{base}/ui/app/auth/application/access", headers=ident, timeout=30)
    r.raise_for_status()
    s.delete(f"{base}/rest/public/authentication/flow", headers=common, timeout=30)

    r = s.post(
        f"{base}/rest/public/authentication/applications/{args.application}/access",
        headers={**common, "Content-Type": "application/json"},
        data=b"",
        timeout=30,
    )
    ticket = r.headers.get("X-ESP-Ticket")
    if not ticket and r.status_code == 401:
        r = s.post(
            f"{base}/rest/public/authentication/password/check",
            headers={**common, "X-Continue-Flow": "true", "Content-Type": "application/json"},
            json={"username": args.email, "password": args.password},
            timeout=30,
        )
        ticket = r.headers.get("X-ESP-Ticket")

    if not ticket:
        raise SystemExit(f"no X-ESP-Ticket returned (status={r.status_code}, body={r.text[:500]!r})")
    if args.output:
        Path(args.output).write_text(ticket)
    else:
        print(ticket)


if __name__ == "__main__":
    main()
