fix(proxy): keep yaml pass-through endpoints visible to auth after db overlay

Resolves LIT-2053

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
yassin 2026-09-15 21:50:07 +00:00
parent fa09de9e45
commit af4a0b4bc3
2 changed files with 40 additions and 2 deletions

View file

@ -7080,8 +7080,12 @@ class ProxyConfig:
## PASS-THROUGH ENDPOINTS ##
if "pass_through_endpoints" in _general_settings:
general_settings["pass_through_endpoints"] = _general_settings["pass_through_endpoints"]
await initialize_pass_through_endpoints(pass_through_endpoints=general_settings["pass_through_endpoints"])
db_pass_through_endpoints: Final = _general_settings["pass_through_endpoints"]
general_settings["pass_through_endpoints"] = [
*db_pass_through_endpoints,
*(config_passthrough_endpoints or []),
]
await initialize_pass_through_endpoints(pass_through_endpoints=db_pass_through_endpoints)
## UI ACCESS MODE ##
if "ui_access_mode" in _general_settings:

View file

@ -7401,6 +7401,40 @@ async def test_update_general_settings_apply_user_budget_to_team_keys_yaml_wins(
assert ps.general_settings["apply_user_budget_to_team_keys"] is True
@pytest.mark.asyncio
async def test_update_general_settings_keeps_yaml_pass_through_endpoints_next_to_db_ones():
"""user_api_key_auth honours ``auth: false`` only for entries it finds in
general_settings["pass_through_endpoints"]. The DB overlay used to replace that
list wholesale, so once one endpoint existed in the DB the YAML-declared
auth-disabled route started answering 401 while staying registered."""
from litellm.proxy._types import ProxyException
from litellm.proxy.proxy_server import ProxyConfig
yaml_endpoint: Final = {"path": "/v1/cuopt/request", "target": "https://example.com/post", "auth": False}
db_endpoint: Final = {"id": "db-1", "path": "/v1/db-echo", "target": "https://example.com/post", "auth": True}
def request_without_key(path: str) -> MagicMock:
request: Final = MagicMock()
request.url.path = path
request.headers = {}
request.query_params = {}
return request
settings: Final = patch("litellm.proxy.proxy_server.general_settings", {"pass_through_endpoints": [yaml_endpoint]}) # test-quality-ok: the method reads this module global; no injection seam
yaml_endpoints: Final = patch("litellm.proxy.proxy_server.config_passthrough_endpoints", [yaml_endpoint]) # test-quality-ok: module global holding the YAML endpoints the fix merges in
initialize: Final = patch("litellm.proxy.proxy_server.initialize_pass_through_endpoints", AsyncMock()) # test-quality-ok: route registration needs the FastAPI app; auth is the observable here
master_key: Final = patch("litellm.proxy.proxy_server.master_key", "sk-master") # test-quality-ok: a set master key is what makes a missing Authorization header a 401
with settings, yaml_endpoints, initialize, master_key:
await ProxyConfig()._update_general_settings(db_general_settings={"pass_through_endpoints": [db_endpoint]})
anonymous: Final = await user_api_key_auth(request=request_without_key("/v1/cuopt/request"), api_key=None)
assert anonymous.api_key is None
with pytest.raises(ProxyException) as still_protected:
await user_api_key_auth(request=request_without_key("/v1/db-echo"), api_key=None)
assert still_protected.value.code == "401"
def _fill_user_api_key_cache(cache: DualCache, count: int) -> None:
for index in range(count):
cache.set_cache(key=f"key-{index}", value={"token": f"key-{index}"}, local_only=True)