#!/usr/bin/env python3 """Report the Gitea account for an isolated Windows OAuth credential.""" import argparse import io import json import os import sys from urllib.request import Request, build_opener import credential_migrate as migration import credential_probe as probe import credential_win_oauth as vault class IdentityError(Exception): """Contains no secret values.""" def lookup(site, namespace, opener): try: request = migration.checked_request(site, "account") host = request["host"].decode("ascii") output = io.BytesIO() vault.run(namespace, "get", {"protocol": "https", "host": host, "username": "oauth2"}, output) fields = vault.parse_request(io.BytesIO(output.getvalue())) token = fields.get("password", "") if not token or not token.isascii() or any(ord(c) < 33 or ord(c) > 126 for c in token): raise IdentityError("The OAuth credential is unavailable.") api_request = Request("https://" + host + "/api/v1/user", headers={"Authorization": "token " + token, "Accept": "application/json"}) with opener.open(api_request, timeout=15) as response: body = response.read(65537) if len(body) > 65536: raise IdentityError("The identity response is too large.") data = json.loads(body) account = data.get("login") if isinstance(data, dict) else None if not isinstance(account, str) or not account or len(account) > 256 or any(ord(c) < 32 or ord(c) == 127 for c in account): raise IdentityError("The identity response is invalid.") return account except IdentityError: raise except Exception: raise IdentityError("The OAuth account could not be verified safely.") from None def main(argv=None): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--site", required=True, help="clean HTTPS site origin") parser.add_argument("--namespace", required=True, help="non-secret isolated vault namespace") parser.add_argument("--repo", help="repository context for site-specific refresh configuration") args = parser.parse_args(argv) try: if args.repo: os.chdir(args.repo) account = lookup(args.site, args.namespace, build_opener(probe.NoRedirect())) print("Verified Gitea account: " + json.dumps(account, ensure_ascii=True)) return 0 except (IdentityError, OSError): print("OAuth identity check could not complete; no secrets are displayed.", file=sys.stderr) return 1 if __name__ == "__main__": raise SystemExit(main())