mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-05 08:07:05 +00:00
fix(team): compare the family's values, not its variable names
Comparing per variable rejected a credential written under its other spelling: langfuse_secret and langfuse_secret_key are one key, so repeating the stored secret under the other name read as a new value. Ask instead whether the value is one the owning entries already carry. A destination the caller controls is by definition not, so the redirect stays closed, and no alias table has to stay complete for that to hold.
This commit is contained in:
parent
bf29ecf115
commit
c0282621c7
2 changed files with 21 additions and 13 deletions
|
|
@ -77,7 +77,7 @@ def cross_entry_family_error(
|
|||
callback_vars: Mapping[str, str] | None,
|
||||
stored_vars_by_entry: Sequence[Mapping[str, str]],
|
||||
) -> str | None:
|
||||
"""Reject an entry that changes a credential family another entry already holds.
|
||||
"""Reject an entry that brings a new value to a family another entry holds.
|
||||
|
||||
Every stored entry's variables are flattened into one dict before a request
|
||||
reads them, and the flattened dict is what the exporter authenticates and
|
||||
|
|
@ -86,12 +86,14 @@ def cross_entry_family_error(
|
|||
with the key from the first, and the request carries that key to the new
|
||||
host.
|
||||
|
||||
Requiring one entry to own a family end to end removes the pairing. Repeating
|
||||
a value the holding entry already stores is allowed, because flattening then
|
||||
produces the same dict either way -- that is how the same integration gets
|
||||
registered for both the success and the failure event. A team admin who does
|
||||
want to move a family deletes the entry holding it first, which reveals
|
||||
nothing.
|
||||
A destination the caller controls is by definition a value the owning entries
|
||||
do not already carry, so requiring every value to be one of theirs removes
|
||||
the pairing. Repeating what they carry is allowed: that is how the same
|
||||
integration gets registered for both the success and the failure event, and
|
||||
it holds for the spellings the same credential has (``langfuse_secret`` and
|
||||
``langfuse_secret_key`` are one key) without anything here having to list
|
||||
them. A team admin who does want to move a family deletes the entry holding
|
||||
it first, which reveals nothing.
|
||||
|
||||
Only the writers this endpoint newly admits are held to this, because a proxy
|
||||
admin already holds every credential the proxy has.
|
||||
|
|
@ -101,16 +103,20 @@ def cross_entry_family_error(
|
|||
"""
|
||||
if not callback_vars:
|
||||
return None
|
||||
stored: Final = { # mutable-ok: local view of the stored entries, never stored
|
||||
var: value for entry in stored_vars_by_entry for var, value in entry.items() if _family_of(var) is not None
|
||||
}
|
||||
held: Final = {_family_of(var) for var in stored} # mutable-ok: local index, never stored
|
||||
stored: Final = tuple(
|
||||
(family, value)
|
||||
for entry in stored_vars_by_entry
|
||||
for var, value in entry.items()
|
||||
if (family := _family_of(var)) is not None
|
||||
)
|
||||
held_values: Final = frozenset(stored)
|
||||
held_families: Final = frozenset(family for family, _ in stored)
|
||||
return next(
|
||||
(
|
||||
f"{family} is already configured by another callback entry on this team. "
|
||||
f"Remove that entry before setting {var} here."
|
||||
f"Remove that entry before setting {var} to a new value here."
|
||||
for var, value, family in ((v, callback_vars[v], _family_of(v)) for v in callback_vars)
|
||||
if family in held and stored.get(var) != value
|
||||
if family in held_families and (family, value) not in held_values
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1541,6 +1541,8 @@ async def test_proxy_admin_still_told_the_team_is_unknown():
|
|||
# the same integration registered for a second event: identical values
|
||||
# flatten to the identical dict, so there is nothing to redirect
|
||||
({"langfuse_host": "https://us.cloud.langfuse.com", "langfuse_public_key": "pk", "langfuse_secret_key": "sk"}, [{"langfuse_host": "https://us.cloud.langfuse.com", "langfuse_public_key": "pk", "langfuse_secret_key": "sk"}], False),
|
||||
# the same credential under its other spelling is the same credential
|
||||
({"langfuse_secret": "sk"}, [{"langfuse_public_key": "pk", "langfuse_secret_key": "sk"}], False),
|
||||
# the same shape with one value moved is the redirect again
|
||||
({"langfuse_host": "http://attacker.invalid", "langfuse_public_key": "pk", "langfuse_secret_key": "sk"}, [{"langfuse_host": "https://us.cloud.langfuse.com", "langfuse_public_key": "pk", "langfuse_secret_key": "sk"}], True),
|
||||
],
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue