mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-15 04:19:08 +00:00
fix(proxy): enforce fallback model access by default (#46127)
This commit is contained in:
parent
6b7d1928b8
commit
0976c0889a
4 changed files with 26 additions and 6 deletions
|
|
@ -2796,7 +2796,7 @@ class ConfigGeneralSettings(LiteLLMPydanticObjectBase):
|
|||
)
|
||||
enforce_fallback_model_access: bool | None = Field(
|
||||
None,
|
||||
description="If True, router fallbacks configured in router_settings are only attempted when the calling key (and its team and project) is allowed to call the fallback model; unauthorized fallback targets are skipped and the primary model's error is returned. Default is False.",
|
||||
description="If True, router fallbacks configured in router_settings are only attempted when the calling key (and its team and project) is allowed to call the fallback model; unauthorized fallback targets are skipped and the primary model's error is returned. Default is True. Set False to disable fallback model access enforcement.",
|
||||
)
|
||||
disable_fallbacks_on_per_model_rate_limits: bool | None = Field(
|
||||
None,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ Authorize router fallback targets against the caller's key, team and project mod
|
|||
`_enforce_key_and_fallback_model_access` only sees fallbacks the client sends in the request body.
|
||||
Fallbacks configured on the router (`router_settings.fallbacks` and friends) are chosen after auth,
|
||||
inside the router, so this predicate is injected into the router to re-run the same model access
|
||||
checks for each fallback target before it is attempted. Opt-in via
|
||||
`general_settings.enforce_fallback_model_access: true`. Fallbacks of a search request always run the
|
||||
checks for each fallback target before it is attempted. Enabled by default. Opt out via
|
||||
`general_settings.enforce_fallback_model_access: false`. Fallbacks of a search request always run the
|
||||
key, team and user search tool grants instead, the same check /search runs on the requested tool.
|
||||
"""
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ class _RequestMetadata(LiteLLMBaseModel):
|
|||
|
||||
|
||||
class _FallbackAccessSettings(LiteLLMBaseModel):
|
||||
enforce_fallback_model_access: bool = False
|
||||
enforce_fallback_model_access: bool = True
|
||||
|
||||
|
||||
async def is_model_authorized_for_token(*, model: str, valid_token: UserAPIKeyAuth, llm_router: Router) -> bool:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from typing import Final
|
||||
|
||||
import pytest
|
||||
|
||||
from litellm import Router
|
||||
|
|
@ -89,8 +91,9 @@ async def test_check_allows_every_fallback_while_not_enforced():
|
|||
@pytest.mark.parametrize(
|
||||
("general_settings", "expected"),
|
||||
[
|
||||
({}, True),
|
||||
({}, False),
|
||||
({"enforce_fallback_model_access": False}, True),
|
||||
({"enforce_fallback_model_access": "false"}, True),
|
||||
({"enforce_fallback_model_access": True}, False),
|
||||
({"enforce_fallback_model_access": "true"}, False),
|
||||
],
|
||||
|
|
@ -100,6 +103,9 @@ async def test_proxy_check_reads_enforce_fallback_model_access_from_general_sett
|
|||
):
|
||||
monkeypatch.setattr("litellm.proxy.proxy_server.general_settings", general_settings)
|
||||
|
||||
assert await router_fallback_access_check(
|
||||
model="open-model", request_kwargs=_request_with_key(), llm_router=_router()
|
||||
)
|
||||
assert (
|
||||
await router_fallback_access_check(
|
||||
model="secret-model", request_kwargs=_request_with_key(), llm_router=_router()
|
||||
|
|
@ -172,3 +178,17 @@ async def test_fallback_named_like_both_a_model_and_a_search_tool_follows_the_re
|
|||
)
|
||||
|
||||
assert allowed is expected
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("metadata_field", ["metadata", "litellm_metadata"])
|
||||
async def test_default_check_enforces_team_models_for_a_key_without_model_restrictions(
|
||||
monkeypatch: pytest.MonkeyPatch, metadata_field: str
|
||||
) -> None:
|
||||
monkeypatch.setattr("litellm.proxy.proxy_server.general_settings", {})
|
||||
router: Final = _router()
|
||||
token: Final = UserAPIKeyAuth(api_key="hashed", models=[], team_id="qa-team", team_models=["open-model"])
|
||||
request_kwargs: Final = {metadata_field: {"user_api_key_auth": token}}
|
||||
|
||||
assert await router_fallback_access_check(model="open-model", request_kwargs=request_kwargs, llm_router=router)
|
||||
assert not await router_fallback_access_check(model="secret-model", request_kwargs=request_kwargs, llm_router=router)
|
||||
|
|
|
|||
2
ui/litellm-dashboard/src/lib/http/schema.d.ts
generated
vendored
2
ui/litellm-dashboard/src/lib/http/schema.d.ts
generated
vendored
|
|
@ -29601,7 +29601,7 @@ export interface components {
|
|||
enable_public_model_hub: boolean;
|
||||
/**
|
||||
* Enforce Fallback Model Access
|
||||
* @description If True, router fallbacks configured in router_settings are only attempted when the calling key (and its team and project) is allowed to call the fallback model; unauthorized fallback targets are skipped and the primary model's error is returned. Default is False.
|
||||
* @description If True, router fallbacks configured in router_settings are only attempted when the calling key (and its team and project) is allowed to call the fallback model; unauthorized fallback targets are skipped and the primary model's error is returned. Default is True. Set False to disable fallback model access enforcement.
|
||||
*/
|
||||
enforce_fallback_model_access?: boolean | null;
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue