mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
fix(proxy): keep the proxy error shape on credential endpoint refusals
This commit is contained in:
parent
2a4cf5a78d
commit
9d681f5318
2 changed files with 19 additions and 16 deletions
|
|
@ -7,7 +7,7 @@ from typing import (
|
|||
cast, # noqa: TID251 # jsonify_object in proxy/utils.py is annotated with a bare dict
|
||||
)
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Path, Request, Response
|
||||
from fastapi import APIRouter, Depends, HTTPException, Path, Request, Response, status
|
||||
|
||||
import litellm
|
||||
from litellm._logging import verbose_proxy_logger
|
||||
|
|
@ -23,7 +23,13 @@ from litellm.llms.base_llm.auth.identity_source import (
|
|||
InternalIssuerSource,
|
||||
)
|
||||
from litellm.llms.base_llm.auth.internal_issuer import internal_issuer_jwks_document
|
||||
from litellm.proxy._types import CommonProxyErrors, LitellmUserRoles, UserAPIKeyAuth
|
||||
from litellm.proxy._types import (
|
||||
CommonProxyErrors,
|
||||
LitellmUserRoles,
|
||||
ProxyErrorTypes,
|
||||
ProxyException,
|
||||
UserAPIKeyAuth,
|
||||
)
|
||||
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
|
||||
from litellm.proxy.common_utils.credential_hydration import (
|
||||
hydrate_named_credential,
|
||||
|
|
@ -51,14 +57,13 @@ def _reject_non_admin_wif_fields(
|
|||
"""
|
||||
if not wif_fields or user_api_key_dict.user_role == LitellmUserRoles.PROXY_ADMIN:
|
||||
return
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail={ # mutable-ok: starlette json.dumps()s HTTPException.detail raw, needs a real dict
|
||||
"error": (
|
||||
f"Only proxy admins can change {wif_fields[0]!r}, a server-owned workload identity federation "
|
||||
"parameter."
|
||||
)
|
||||
},
|
||||
raise ProxyException(
|
||||
message=(
|
||||
f"Only proxy admins can change {wif_fields[0]!r}, a server-owned workload identity federation parameter."
|
||||
),
|
||||
type=ProxyErrorTypes.auth_error.value,
|
||||
code=status.HTTP_403_FORBIDDEN,
|
||||
param=wif_fields[0],
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -422,8 +427,6 @@ async def delete_credential(
|
|||
## DELETE FROM LITELLM ##
|
||||
litellm.credential_list = [cred for cred in litellm.credential_list if cred.credential_name != credential_name]
|
||||
return {"success": True, "message": "Credential deleted successfully"}
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise handle_exception_on_proxy(e)
|
||||
|
||||
|
|
|
|||
|
|
@ -742,7 +742,7 @@ class TestNonAdminCannotTouchAStoredWifCredential:
|
|||
response = _delete_credential("federated-cred", auth=_as_non_admin)
|
||||
|
||||
assert response.status_code == 403, response.text
|
||||
assert "anthropic_keycloak_token_url" in response.text
|
||||
assert response.json()["error"]["param"] == "anthropic_keycloak_token_url"
|
||||
repository.delete_by_name.assert_not_awaited()
|
||||
|
||||
def test_a_stale_in_memory_copy_does_not_authorize_deleting_a_stored_wif_credential(
|
||||
|
|
@ -757,7 +757,7 @@ class TestNonAdminCannotTouchAStoredWifCredential:
|
|||
response = _delete_credential("federated-cred", auth=_as_non_admin)
|
||||
|
||||
assert response.status_code == 403, response.text
|
||||
assert "anthropic_keycloak_token_url" in response.text
|
||||
assert response.json()["error"]["param"] == "anthropic_keycloak_token_url"
|
||||
repository.delete_by_name.assert_not_awaited()
|
||||
|
||||
def test_proxy_admin_can_delete_a_stored_wif_credential(self, restore_credential_list):
|
||||
|
|
@ -839,7 +839,7 @@ class TestNonAdminCannotTouchAStoredWifCredential:
|
|||
response = _delete_credential("config-wif", auth=_as_non_admin)
|
||||
|
||||
assert response.status_code == 403, response.text
|
||||
assert "anthropic_keycloak_token_url" in response.text
|
||||
assert response.json()["error"]["param"] == "anthropic_keycloak_token_url"
|
||||
repository.delete_by_name.assert_not_awaited()
|
||||
assert litellm.credential_list == [config_credential]
|
||||
|
||||
|
|
@ -1053,7 +1053,7 @@ def test_delete_credential_answers_404_when_the_credential_does_not_exist(creden
|
|||
response = _delete_credential("definitely-not-there")
|
||||
|
||||
assert response.status_code == 404, f"delete of a missing credential answered {response.status_code}: {response.text}"
|
||||
assert "definitely-not-there" in response.text
|
||||
assert "definitely-not-there" in response.json()["error"]["message"]
|
||||
|
||||
|
||||
def test_delete_credential_still_answers_200_and_drops_the_credential_from_memory(credential_store):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue