fix(proxy): keep the proxy error shape on credential endpoint refusals

This commit is contained in:
mateo-berri 2026-09-05 15:06:08 -07:00
parent 2a4cf5a78d
commit 9d681f5318
2 changed files with 19 additions and 16 deletions

View file

@ -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)

View file

@ -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):