from pathlib import Path from fastapi.testclient import TestClient from app import auth from app import main as main_module from app.store import Store def test_disabled_auth_preserves_v15_api_access(tmp_path: Path, monkeypatch) -> None: monkeypatch.setenv("SERVICEMAP_AUTH_MODE", "disabled") main_module.store = Store(str(tmp_path / "servicemap.db")) client = TestClient(main_module.app) response = client.post( "/api/v1/services", json={"name": "API", "kind": "http", "url": "https://api.local"}, ) assert response.status_code == 201 def test_oidc_mode_fails_closed_but_health_stays_available(monkeypatch) -> None: monkeypatch.setenv("SERVICEMAP_AUTH_MODE", "oidc") monkeypatch.delenv("SERVICEMAP_OIDC_ISSUER", raising=False) monkeypatch.delenv("SERVICEMAP_OIDC_AUDIENCE", raising=False) client = TestClient(main_module.app) assert client.get("/health").status_code == 200 assert client.get("/api/v1/services").status_code == 503 def test_oidc_roles_enforce_read_operator_and_admin_boundaries(tmp_path: Path, monkeypatch) -> None: main_module.store = Store(str(tmp_path / "servicemap.db")) config = auth.AuthConfig(mode="oidc", issuer="https://id.example", audience="servicemap") monkeypatch.setattr(auth.AuthConfig, "from_environment", classmethod(lambda cls: config)) client = TestClient(main_module.app) monkeypatch.setattr(auth, "verify_bearer", lambda token, _: {"viewer"}) assert ( client.get("/api/v1/services", headers={"Authorization": "Bearer viewer"}).status_code == 200 ) assert ( client.post( "/api/v1/services", headers={"Authorization": "Bearer viewer"}, json={"name": "Denied", "kind": "http", "url": "https://denied.local"}, ).status_code == 403 ) monkeypatch.setattr(auth, "verify_bearer", lambda token, _: {"operator", "viewer"}) assert ( client.post( "/api/v1/services", headers={"Authorization": "Bearer operator"}, json={"name": "Allowed", "kind": "http", "url": "https://allowed.local"}, ).status_code == 201 ) assert ( client.post( "/api/v1/config/import", headers={"Authorization": "Bearer operator"}, json={"content": "version: 1\nservices: []", "format": "yaml", "mode": "merge"}, ).status_code == 403 )