From 99e7e914bae16616337cefdab32d2e329a271dda Mon Sep 17 00:00:00 2001 From: Nicole Rappe Date: Wed, 29 Oct 2025 18:13:06 -0600 Subject: [PATCH] ENGINE: Fixed Certificates Rotating at every Reboot --- Borealis.ps1 | 35 ++++++++++++++++++------- Data/Engine/auth/jwt_service.py | 38 ---------------------------- Data/Engine/config.py | 4 +-- Data/Engine/security/certificates.py | 6 ++++- 4 files changed, 33 insertions(+), 50 deletions(-) diff --git a/Borealis.ps1 b/Borealis.ps1 index ba0a779d..6e84eb12 100644 --- a/Borealis.ps1 +++ b/Borealis.ps1 @@ -189,26 +189,43 @@ function Ensure-EngineTlsMaterial { [string]$CertificateRoot ) - if (-not (Test-Path $CertificateRoot)) { - New-Item -Path $CertificateRoot -ItemType Directory -Force | Out-Null - } + $effectiveRoot = $null if (Test-Path $PythonPath) { $code = @' -from Data.Engine.services.crypto import certificates +from Data.Engine.security import certificates certificates.ensure_certificate() +print(certificates.engine_certificates_root()) '@ try { - & $PythonPath -c $code | Out-Null + $output = & $PythonPath -c $code + if ($output) { + $raw = $output | Select-Object -Last 1 + if ($raw) { + $effectiveRoot = ([string]$raw).Trim() + } + } } catch { Write-Host "Failed to pre-generate Engine TLS certificates: $($_.Exception.Message)" -ForegroundColor Yellow } } - $env:BOREALIS_CERT_DIR = $CertificateRoot - $env:BOREALIS_TLS_CERT = Join-Path $CertificateRoot 'borealis-server-cert.pem' - $env:BOREALIS_TLS_KEY = Join-Path $CertificateRoot 'borealis-server-key.pem' - $env:BOREALIS_TLS_BUNDLE = Join-Path $CertificateRoot 'borealis-server-bundle.pem' + if (-not $effectiveRoot -and $CertificateRoot) { + $effectiveRoot = $CertificateRoot + } + + if (-not $effectiveRoot) { + $effectiveRoot = Join-Path $scriptDir 'Engine\Certificates' + } + + if (-not (Test-Path $effectiveRoot)) { + New-Item -Path $effectiveRoot -ItemType Directory -Force | Out-Null + } + + $env:BOREALIS_CERT_DIR = $effectiveRoot + $env:BOREALIS_TLS_CERT = Join-Path $effectiveRoot 'borealis-server-cert.pem' + $env:BOREALIS_TLS_KEY = Join-Path $effectiveRoot 'borealis-server-key.pem' + $env:BOREALIS_TLS_BUNDLE = Join-Path $effectiveRoot 'borealis-server-bundle.pem' } function Ensure-EngineWebInterface { diff --git a/Data/Engine/auth/jwt_service.py b/Data/Engine/auth/jwt_service.py index 9098e5d0..eae36cc0 100644 --- a/Data/Engine/auth/jwt_service.py +++ b/Data/Engine/auth/jwt_service.py @@ -22,7 +22,6 @@ from cryptography.hazmat.primitives.asymmetric import ed25519 from ..security.certificates import project_root_path _TOKEN_ENV_ROOT = "BOREALIS_ENGINE_AUTH_TOKEN_ROOT" -_LEGACY_SERVER_ROOT_ENV = "BOREALIS_SERVER_ROOT" _KEY_FILENAME = "borealis-jwt-ed25519.key" @@ -59,16 +58,6 @@ def _token_root() -> Path: return root -def _legacy_key_paths() -> Dict[str, Path]: - project_root = project_root_path() - server_root = _env_path(_LEGACY_SERVER_ROOT_ENV) or (project_root / "Server" / "Borealis") - candidates = { - "auth_keys": server_root / "auth_keys" / _KEY_FILENAME, - "keys": server_root / "keys" / _KEY_FILENAME, - } - return candidates - - def _tighten_permissions(path: Path) -> None: try: if os.name != "nt": @@ -159,7 +148,6 @@ def load_service() -> JWTService: def _load_or_create_private_key() -> ed25519.Ed25519PrivateKey: _KEY_DIR.mkdir(parents=True, exist_ok=True) - _migrate_legacy_key_if_present() if _KEY_FILE.exists(): with _KEY_FILE.open("rb") as fh: @@ -177,30 +165,4 @@ def _load_or_create_private_key() -> ed25519.Ed25519PrivateKey: return private_key -def _migrate_legacy_key_if_present() -> None: - if _KEY_FILE.exists(): - return - - legacy_paths = _legacy_key_paths() - for legacy_file in legacy_paths.values(): - if not legacy_file.exists(): - continue - try: - legacy_bytes = legacy_file.read_bytes() - except Exception: - continue - - try: - _KEY_FILE.write_bytes(legacy_bytes) - _tighten_permissions(_KEY_FILE) - except Exception: - continue - - try: - legacy_file.unlink() - except Exception: - pass - break - - __all__ = ["JWTService", "load_service"] diff --git a/Data/Engine/config.py b/Data/Engine/config.py index c716ed35..4b3456d0 100644 --- a/Data/Engine/config.py +++ b/Data/Engine/config.py @@ -24,7 +24,7 @@ environment variables prefixed with ``BOREALIS_``, and finally built-in defaults that mirror the legacy server runtime. Key environment variables are ``BOREALIS_DATABASE_PATH`` path to the SQLite database file. Defaults to -``/database.db``. +the Engine runtime copy under ``/Engine/Data/Engine/database.db``. ``BOREALIS_CORS_ORIGINS`` comma separated list of allowed origins for CORS. ``BOREALIS_SECRET`` Flask session secret key. ``BOREALIS_COOKIE_*`` Session cookie policies (``SAMESITE``, ``SECURE``, @@ -72,7 +72,7 @@ def _discover_project_root() -> Path: PROJECT_ROOT = _discover_project_root() -DEFAULT_DATABASE_PATH = PROJECT_ROOT / "database.db" +DEFAULT_DATABASE_PATH = PROJECT_ROOT / "Engine" / "Data" / "Engine" / "database.db" LOG_ROOT = PROJECT_ROOT / "Engine" / "Logs" LOG_FILE_PATH = LOG_ROOT / "engine.log" ERROR_LOG_FILE_PATH = LOG_ROOT / "error.log" diff --git a/Data/Engine/security/certificates.py b/Data/Engine/security/certificates.py index 64571149..e9fdf708 100644 --- a/Data/Engine/security/certificates.py +++ b/Data/Engine/security/certificates.py @@ -266,7 +266,11 @@ def _server_certificate_needs_regeneration( try: san = certificate.extensions.get_extension_for_class(x509.SubjectAlternativeName).value # type: ignore[attr-defined] - names = {entry.value for entry in san.get_values_for_type(x509.DNSName)} + raw_names = san.get_values_for_type(x509.DNSName) + names = { + entry if isinstance(entry, str) else getattr(entry, "value", str(entry)) + for entry in raw_names + } except Exception: names = set()