diff --git a/Data/Server/Modules/auth/jwt_service.py b/Data/Server/Modules/auth/jwt_service.py index aa66cc9..ab5640b 100644 --- a/Data/Server/Modules/auth/jwt_service.py +++ b/Data/Server/Modules/auth/jwt_service.py @@ -7,7 +7,6 @@ from __future__ import annotations import hashlib import time from datetime import datetime, timezone -from pathlib import Path from typing import Any, Dict, Optional import jwt @@ -16,8 +15,9 @@ from cryptography.hazmat.primitives.asymmetric import ed25519 from Modules.runtime import ensure_runtime_dir, runtime_path -_KEY_DIR = runtime_path("keys") +_KEY_DIR = runtime_path("auth_keys") _KEY_FILE = _KEY_DIR / "borealis-jwt-ed25519.key" +_LEGACY_KEY_FILE = runtime_path("keys") / "borealis-jwt-ed25519.key" class JWTService: @@ -98,11 +98,17 @@ def load_service() -> JWTService: def _load_or_create_private_key() -> ed25519.Ed25519PrivateKey: - ensure_runtime_dir("keys") + ensure_runtime_dir("auth_keys") + _migrate_legacy_key_if_present() + if _KEY_FILE.exists(): with _KEY_FILE.open("rb") as fh: return serialization.load_pem_private_key(fh.read(), password=None) + if _LEGACY_KEY_FILE.exists(): + with _LEGACY_KEY_FILE.open("rb") as fh: + return serialization.load_pem_private_key(fh.read(), password=None) + private_key = ed25519.Ed25519PrivateKey.generate() pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, @@ -118,3 +124,17 @@ def _load_or_create_private_key() -> ed25519.Ed25519PrivateKey: pass return private_key + +def _migrate_legacy_key_if_present() -> None: + if not _LEGACY_KEY_FILE.exists() or _KEY_FILE.exists(): + return + + try: + ensure_runtime_dir("auth_keys") + try: + _LEGACY_KEY_FILE.replace(_KEY_FILE) + except Exception: + _KEY_FILE.write_bytes(_LEGACY_KEY_FILE.read_bytes()) + except Exception: + return + diff --git a/Data/Server/Modules/crypto/signing.py b/Data/Server/Modules/crypto/signing.py index 13d6a86..b74e537 100644 --- a/Data/Server/Modules/crypto/signing.py +++ b/Data/Server/Modules/crypto/signing.py @@ -14,9 +14,11 @@ from Modules.runtime import ensure_runtime_dir, runtime_path from .keys import base64_from_spki_der -_KEY_DIR = runtime_path("keys") +_KEY_DIR = runtime_path("script_signing_keys") _SIGNING_KEY_FILE = _KEY_DIR / "borealis-script-ed25519.key" _SIGNING_PUB_FILE = _KEY_DIR / "borealis-script-ed25519.pub" +_LEGACY_KEY_FILE = runtime_path("keys") / "borealis-script-ed25519.key" +_LEGACY_PUB_FILE = runtime_path("keys") / "borealis-script-ed25519.pub" class ScriptSigner: @@ -43,11 +45,17 @@ def load_signer() -> ScriptSigner: def _load_or_create() -> ed25519.Ed25519PrivateKey: - ensure_runtime_dir("keys") + ensure_runtime_dir("script_signing_keys") + _migrate_legacy_material_if_present() + if _SIGNING_KEY_FILE.exists(): with _SIGNING_KEY_FILE.open("rb") as fh: return serialization.load_pem_private_key(fh.read(), password=None) + if _LEGACY_KEY_FILE.exists(): + with _LEGACY_KEY_FILE.open("rb") as fh: + return serialization.load_pem_private_key(fh.read(), password=None) + private_key = ed25519.Ed25519PrivateKey.generate() pem = private_key.private_bytes( encoding=serialization.Encoding.PEM, @@ -70,3 +78,23 @@ def _load_or_create() -> ed25519.Ed25519PrivateKey: return private_key + +def _migrate_legacy_material_if_present() -> None: + if not _LEGACY_KEY_FILE.exists() or _SIGNING_KEY_FILE.exists(): + return + + try: + ensure_runtime_dir("script_signing_keys") + try: + _LEGACY_KEY_FILE.replace(_SIGNING_KEY_FILE) + except Exception: + _SIGNING_KEY_FILE.write_bytes(_LEGACY_KEY_FILE.read_bytes()) + + if _LEGACY_PUB_FILE.exists() and not _SIGNING_PUB_FILE.exists(): + try: + _LEGACY_PUB_FILE.replace(_SIGNING_PUB_FILE) + except Exception: + _SIGNING_PUB_FILE.write_bytes(_LEGACY_PUB_FILE.read_bytes()) + except Exception: + return + diff --git a/Data/Server/server.py b/Data/Server/server.py index d1c234f..346562d 100644 --- a/Data/Server/server.py +++ b/Data/Server/server.py @@ -21,6 +21,7 @@ Section Guide: import os import sys from pathlib import Path +import ssl # Ensure the modular server package is importable when the runtime is launched # from a packaged directory (e.g., Server/Borealis). We look for the canonical @@ -41,6 +42,36 @@ eventlet.monkey_patch(thread=False) from eventlet import tpool +try: + from eventlet.wsgi import HttpProtocol # type: ignore +except Exception: + HttpProtocol = None # type: ignore[assignment] +else: + _original_handle_one_request = HttpProtocol.handle_one_request + + def _quiet_tls_http_mismatch(self): # type: ignore[override] + try: + return _original_handle_one_request(self) + except ssl.SSLError as exc: # type: ignore[arg-type] + reason = getattr(exc, "reason", "") + reason_text = str(reason).lower() if reason else "" + message = " ".join(str(arg) for arg in exc.args if arg).lower() + if "http_request" in message or reason_text == "http request": + try: + self.close_connection = True # type: ignore[attr-defined] + except Exception: + pass + try: + conn = getattr(self, "socket", None) or getattr(self, "connection", None) + if conn: + conn.close() + except Exception: + pass + return None + raise + + HttpProtocol.handle_one_request = _quiet_tls_http_mismatch # type: ignore[assignment] + import requests import re import base64