feat(update-service): SSRF-validated redirects + restart hardening

update_service grows explicit URL validation on the redirect chain so a
hostile mirror can't bounce the updater to a private IP. restart.ps1
gets stricter argument handling and clearer log lines.
default_config.yaml exposes the new toggles. test_system_routes pins
the new behaviour.
This commit is contained in:
2026-05-23 00:49:18 +03:00
parent 826e680f37
commit 45d12b2811
4 changed files with 217 additions and 62 deletions
+22 -2
View File
@@ -9,6 +9,17 @@ import pytest
from fastapi.testclient import TestClient
from ledgrab import __version__
from ledgrab.config import get_config
def _auth_headers() -> dict[str, str]:
"""Resolve the configured API key lazily so test ordering doesn't matter.
Evaluating ``get_config()`` at module import time produced a stale empty
key when other tests mutated the global config before this module ran.
"""
api_key = next(iter(get_config().auth.api_keys.values()), "")
return {"Authorization": f"Bearer {api_key}"} if api_key else {}
@pytest.fixture(scope="module")
@@ -55,17 +66,26 @@ class TestVersionEndpoint:
class TestOpenAPIEndpoint:
def test_openapi_available(self, client):
resp = client.get("/openapi.json")
resp = client.get("/openapi.json", headers=_auth_headers())
assert resp.status_code == 200
data = resp.json()
assert "info" in data
assert data["info"]["version"] == __version__
def test_swagger_ui(self, client):
resp = client.get("/docs")
resp = client.get("/docs", headers=_auth_headers())
assert resp.status_code == 200
assert "text/html" in resp.headers["content-type"]
def test_openapi_requires_auth(self, client):
"""Without a valid bearer token, the OpenAPI surface is unreachable."""
resp = client.get("/openapi.json")
assert resp.status_code == 401
def test_swagger_requires_auth(self, client):
resp = client.get("/docs")
assert resp.status_code == 401
class TestRootEndpoint:
def test_root_returns_html(self, client):