#!/usr/bin/env python3 """CLI lifecycle chei API (CORE securitate). Emitere/rotire/revocare/listare chei per cont. Adminul ruleaza pe masina gateway — nicio suprafata HTTP de admin. Cheia in clar se afiseaza O SINGURA DATA la creare/rotire; in DB traieste doar hash-ul SHA-256. Utilizare: python -m tools.apikey create --account 1 python -m tools.apikey rotate --account 1 python -m tools.apikey revoke --key-id 3 python -m tools.apikey list [--account 1] """ from __future__ import annotations import argparse import sys from app.auth import create_api_key, list_keys, revoke_api_key, rotate_api_key from app.db import get_connection, init_db def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description="Lifecycle chei API gateway RAR AUTOPASS") sub = parser.add_subparsers(dest="cmd", required=True) p_create = sub.add_parser("create", help="emite o cheie noua pentru cont") p_create.add_argument("--account", type=int, required=True, help="account_id") p_rotate = sub.add_parser("rotate", help="revoca cheile active ale contului + emite una noua") p_rotate.add_argument("--account", type=int, required=True, help="account_id") p_revoke = sub.add_parser("revoke", help="revoca o cheie dupa id") p_revoke.add_argument("--key-id", type=int, required=True, help="api_keys.id") p_list = sub.add_parser("list", help="listeaza chei (fara hash)") p_list.add_argument("--account", type=int, default=None, help="filtreaza pe cont") args = parser.parse_args(argv) init_db() # asigura schema (api_keys) + cont default conn = get_connection() try: if args.cmd == "create": try: key = create_api_key(conn, args.account) except ValueError as exc: print(f"eroare: {exc}", file=sys.stderr) return 2 print(f"Cheie creata pentru cont {args.account} (pastreaz-o, nu se mai afiseaza):") print(key) return 0 if args.cmd == "rotate": try: key = rotate_api_key(conn, args.account) except ValueError as exc: print(f"eroare: {exc}", file=sys.stderr) return 2 print(f"Chei vechi revocate. Cheie noua pentru cont {args.account}:") print(key) return 0 if args.cmd == "revoke": ok = revoke_api_key(conn, args.key_id) if ok: print(f"Cheie {args.key_id} revocata.") return 0 print(f"Cheie {args.key_id} inexistenta sau deja revocata.", file=sys.stderr) return 1 if args.cmd == "list": rows = list_keys(conn, args.account) if not rows: print("(nicio cheie)") return 0 print(f"{'id':>4} {'cont':>4} {'activa':>6} {'creata':<20} revocata") for r in rows: print( f"{r['id']:>4} {r['account_id']:>4} {('da' if r['active'] else 'nu'):>6} " f"{(r['created_at'] or ''):<20} {r['revoked_at'] or ''}" ) return 0 finally: conn.close() return 0 if __name__ == "__main__": sys.exit(main())