mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
fix(anthropic): carry the federation disable sentinel through the kwargs funnel
When a client redirects api_base, the handler sets a sentinel so the deployment stops federating and no server credential is minted for a host the caller chose. get_litellm_params then rebuilds litellm_params from kwargs and did not carry that field, so it was dropped in transit and the deployment federated anyway. A flag the next hop discards is worse than no flag, because the code reads as protected. The sentinel now rides the funnel like the other federation fields, which also makes it request-banned, correctly: a caller must not be able to set it or clear it. It is declared on the params model for the same reason the others are, so it survives the strict dump rather than being rebuilt away.
This commit is contained in:
parent
7076219284
commit
c4a5459b49
4 changed files with 31 additions and 0 deletions
|
|
@ -50,6 +50,11 @@ ANTHROPIC_WIF_KWARGS_KEYS: Final = frozenset(
|
|||
"anthropic_keycloak_auth_method",
|
||||
"anthropic_keycloak_client_secret_ref",
|
||||
"anthropic_keycloak_scope",
|
||||
# Set server-side when a client redirects api_base, to stop a federated deployment minting
|
||||
# for a base the caller chose. It has to ride this funnel or it is dropped on the way and
|
||||
# the deployment federates anyway; being carried here also request-bans it, which is right,
|
||||
# since a caller must not be able to set it in either direction.
|
||||
"anthropic_disable_workload_identity_federation",
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -297,6 +297,9 @@ class CredentialLiteLLMParams(BaseModel):
|
|||
anthropic_keycloak_auth_method: str | None = None
|
||||
anthropic_keycloak_client_secret_ref: str | None = None
|
||||
anthropic_keycloak_scope: str | None = None
|
||||
# Server-set when a client redirects api_base. Declared so it survives the strict dump the
|
||||
# other federation fields above are declared for, rather than being rebuilt away in transit.
|
||||
anthropic_disable_workload_identity_federation: bool | None = None
|
||||
|
||||
|
||||
def anthropic_wif_fields_present(fields: Mapping[str, object]) -> tuple[str, ...]:
|
||||
|
|
|
|||
|
|
@ -3426,6 +3426,28 @@ class TestWifServerOwnedParamsAreUnconditional:
|
|||
|
||||
|
||||
class TestWifDisabledOnClientRedirectedBase:
|
||||
def test_the_sentinel_survives_the_kwargs_funnel(self):
|
||||
"""Setting the sentinel is only half of it. get_litellm_params rebuilds litellm_params from
|
||||
kwargs, so a field it does not carry is dropped on the way and the deployment federates for
|
||||
the caller-chosen base after all."""
|
||||
from litellm.litellm_core_utils.get_litellm_params import FORWARDED_KWARGS_KEYS
|
||||
from litellm.router_utils.clientside_credential_handler import (
|
||||
DISABLE_WORKLOAD_IDENTITY_PARAM,
|
||||
)
|
||||
|
||||
assert DISABLE_WORKLOAD_IDENTITY_PARAM in FORWARDED_KWARGS_KEYS
|
||||
|
||||
def test_the_sentinel_is_not_client_settable(self):
|
||||
"""It is server-owned in both directions: a caller must not be able to set it, and must not
|
||||
be able to clear it either."""
|
||||
from litellm.router_utils.clientside_credential_handler import (
|
||||
DISABLE_WORKLOAD_IDENTITY_PARAM,
|
||||
)
|
||||
from litellm.types.router import reject_server_owned_wif_params
|
||||
|
||||
with pytest.raises(ValueError, match=DISABLE_WORKLOAD_IDENTITY_PARAM):
|
||||
reject_server_owned_wif_params({DISABLE_WORKLOAD_IDENTITY_PARAM: False})
|
||||
|
||||
def test_base_override_clears_wif_and_sets_the_sentinel(self):
|
||||
"""A federation token minted for a client-chosen api_base would send the workload's assertion,
|
||||
and then the minted bearer, to that host."""
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ def test_credential_litellm_params_declares_every_anthropic_wif_field():
|
|||
def test_anthropic_wif_fields_round_trip_through_model_dump():
|
||||
values = {field: f"value-for-{field}" for field in anthropic_wif_litellm_params}
|
||||
values["anthropic_issuer_ttl_seconds"] = 300
|
||||
values["anthropic_disable_workload_identity_federation"] = True
|
||||
|
||||
dumped = CredentialLiteLLMParams(**values).model_dump(exclude_none=True)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue