mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-16 23:41:43 +00:00
fix(proxy/batches): fail closed when the managed file ownership lookup errors
A lookup exception previously fell back to dispatching the original unified id with the ownership gate unexecuted; the managed-files deployment hook maps unified ids from cache without re-checking ownership, so a database outage let a caller dispatch another tenant's file. Raise a clear 503 instead and lock the behavior with a regression test. No-database and no-row cases still fall back unchanged
This commit is contained in:
parent
f8fc629286
commit
0a33ea40c6
2 changed files with 22 additions and 12 deletions
|
|
@ -51,11 +51,13 @@ async def _resolve_managed_input_file_storage_url(
|
|||
) -> "str | None":
|
||||
"""Resolve a managed (unified) input_file_id to its backend storage_url.
|
||||
|
||||
Returns None when the proxy has no database, the lookup fails, no managed
|
||||
file row exists, or the row has no storage_url; callers fall back to
|
||||
dispatching the original id so the managed-files deployment hook can still
|
||||
map it via model_file_id_mapping. Raises a 404 when the caller does not
|
||||
own the managed file.
|
||||
Returns None when the proxy has no database, no managed file row exists,
|
||||
or the row has no storage_url; callers fall back to dispatching the
|
||||
original id so the managed-files deployment hook can still map it via
|
||||
model_file_id_mapping. Raises a 404 when the caller does not own the
|
||||
managed file and a 503 when the lookup fails, so an unverifiable id is
|
||||
never dispatched (the deployment hook maps ids from cache without
|
||||
re-checking ownership).
|
||||
"""
|
||||
from litellm.proxy.proxy_server import prisma_client
|
||||
|
||||
|
|
@ -65,7 +67,10 @@ async def _resolve_managed_input_file_storage_url(
|
|||
db_file = await ManagedFileRepository(prisma_client).table.find_first(where={"unified_file_id": input_file_id})
|
||||
except Exception as e:
|
||||
verbose_proxy_logger.warning("create_batch: managed file lookup failed for %s: %s", input_file_id, e)
|
||||
return None
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail={"error": "Unable to verify managed file access; please retry"},
|
||||
)
|
||||
if db_file is None:
|
||||
return None
|
||||
if not can_access_resource(
|
||||
|
|
|
|||
|
|
@ -605,10 +605,12 @@ async def test_create__unified_file_id_other_tenant_gets_404(harness):
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create__unified_file_id_db_error_falls_back_to_raw_id(harness):
|
||||
"""A database failure during resolution must not abort batch creation:
|
||||
the original id is dispatched so the managed-files deployment hook can
|
||||
still map it via model_file_id_mapping."""
|
||||
async def test_create__unified_file_id_db_error_fails_closed_503(harness):
|
||||
"""A lookup failure must fail closed: the ownership gate could not run, and
|
||||
the managed-files deployment hook maps unified ids from cache without
|
||||
re-checking ownership, so dispatching the unverified id would let a caller
|
||||
use another tenant's file during a database outage. Expect a clear 503 and
|
||||
no dispatch."""
|
||||
set_body(
|
||||
harness,
|
||||
{
|
||||
|
|
@ -629,9 +631,12 @@ async def test_create__unified_file_id_db_error_falls_back_to_raw_id(harness):
|
|||
patch.object(proxy_server, "prisma_client", MagicMock()),
|
||||
patch.object(endpoints, "ManagedFileRepository", fake_repo_cls),
|
||||
):
|
||||
await call_create(harness)
|
||||
with pytest.raises(ProxyException) as exc:
|
||||
await call_create(harness)
|
||||
|
||||
assert harness.router_kwargs()["input_file_id"] == "litellm_proxy_unified_id"
|
||||
assert exc.value.code == "503"
|
||||
harness.router_acreate.assert_not_called()
|
||||
harness.litellm_acreate.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue