()
| 103 | |
| 104 | |
| 105 | def main(): |
| 106 | args = parse_args() |
| 107 | |
| 108 | # Handle cert-only commands before loading config so they can run standalone. |
| 109 | if args.install_cert or args.uninstall_cert: |
| 110 | configure_logging("INFO") |
| 111 | _log = logging.getLogger("Main") |
| 112 | |
| 113 | if args.install_cert: |
| 114 | _log.info("Installing CA certificate…") |
| 115 | if not os.path.exists(CA_CERT_FILE): |
| 116 | from proxy.mitm import MITMCertManager |
| 117 | MITMCertManager() # side-effect: creates ca/ca.crt + ca/ca.key |
| 118 | ok = install_ca(CA_CERT_FILE) |
| 119 | sys.exit(0 if ok else 1) |
| 120 | |
| 121 | _log.info("Removing CA certificate…") |
| 122 | ok = uninstall_ca(CA_CERT_FILE) |
| 123 | if ok: |
| 124 | _log.info("CA certificate removed successfully.") |
| 125 | else: |
| 126 | _log.warning("CA certificate removal may have failed. Check logs above.") |
| 127 | sys.exit(0 if ok else 1) |
| 128 | |
| 129 | config_path = args.config |
| 130 | |
| 131 | try: |
| 132 | with open(config_path) as f: |
| 133 | config = json.load(f) |
| 134 | except FileNotFoundError: |
| 135 | print(f"Config not found: {config_path}") |
| 136 | # Offer the interactive wizard if it's available and we're on a TTY. |
| 137 | wizard = os.path.join(os.path.dirname(os.path.abspath(__file__)), "setup.py") |
| 138 | if os.path.exists(wizard) and sys.stdin.isatty(): |
| 139 | try: |
| 140 | answer = input("Run the interactive setup wizard now? [Y/n]: ").strip().lower() |
| 141 | except EOFError: |
| 142 | answer = "n" |
| 143 | if answer in ("", "y", "yes"): |
| 144 | import subprocess |
| 145 | rc = subprocess.call([sys.executable, wizard]) |
| 146 | if rc != 0: |
| 147 | sys.exit(rc) |
| 148 | try: |
| 149 | with open(config_path) as f: |
| 150 | config = json.load(f) |
| 151 | except Exception as e: |
| 152 | print(f"Could not load config after setup: {e}") |
| 153 | sys.exit(1) |
| 154 | else: |
| 155 | print("Copy config.example.json to config.json and fill in your values,") |
| 156 | print("or run: python setup.py") |
| 157 | sys.exit(1) |
| 158 | else: |
| 159 | print("Run: python setup.py (or copy config.example.json to config.json)") |
| 160 | sys.exit(1) |
| 161 | except json.JSONDecodeError as e: |
| 162 | print(f"Invalid JSON in config: {e}") |
no test coverage detected