Gate control-plane-only fields behind worker_registry presence

Only return JWT token in /v2/login response body when workers are
configured (control plane mode). Non-CP instances continue to set
the cookie only, avoiding unnecessary token exposure. Also make
workers list in discovery endpoint explicitly conditional on
is_control_plane flag.
This commit is contained in:
Ryan Crabbe 2026-03-14 10:47:19 -07:00
parent ec59eef43b
commit d3d2ecb44e
4 changed files with 13 additions and 3 deletions

View file

@ -39,5 +39,5 @@ async def get_ui_config():
admin_ui_disabled=admin_ui_disabled,
sso_configured=sso_configured,
is_control_plane=is_control_plane,
workers=proxy_config.worker_registry,
workers=proxy_config.worker_registry if is_control_plane else [],
)

View file

@ -11040,8 +11040,12 @@ async def login_v2(request: Request): # noqa: PLR0915
litellm_dashboard_ui += "/ui/"
litellm_dashboard_ui += "?login=success"
response_content: dict = {"redirect_url": litellm_dashboard_ui}
if len(proxy_config.worker_registry) > 0:
response_content["token"] = jwt_token
json_response = JSONResponse(
content={"redirect_url": litellm_dashboard_ui, "token": jwt_token},
content=response_content,
status_code=status.HTTP_200_OK,
)
json_response.set_cookie(key="token", value=jwt_token)

View file

@ -281,6 +281,10 @@ def test_ui_discovery_endpoints_is_control_plane_true_when_workers_configured():
assert response.status_code == 200
data = response.json()
assert data["is_control_plane"] is True
assert len(data["workers"]) == 1
assert data["workers"][0]["worker_id"] == "team-a"
assert data["workers"][0]["name"] == "Team A"
assert data["workers"][0]["url"] == "https://worker-1:4001"
def test_ui_discovery_endpoints_is_control_plane_false_when_no_workers():
@ -302,3 +306,4 @@ def test_ui_discovery_endpoints_is_control_plane_false_when_no_workers():
assert response.status_code == 200
data = response.json()
assert data["is_control_plane"] is False
assert data["workers"] == []

View file

@ -25,6 +25,7 @@ sys.path.insert(
import litellm
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
from litellm.proxy.proxy_server import app, initialize
from litellm.types.proxy.control_plane_endpoints import WorkerRegistryEntry
from litellm.utils import _invalidate_model_cost_lowercase_map
example_embedding_result = {
@ -106,8 +107,8 @@ def test_login_v2_returns_redirect_url_and_sets_cookie(monkeypatch):
assert response.status_code == 200
assert response.json() == {
"redirect_url": "http://testserver/ui/?login=success",
"token": "signed-token",
}
assert "token" not in response.json()
assert response.cookies.get("token") == "signed-token"
mock_authenticate_user.assert_awaited_once_with(