mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-14 23:21:35 +00:00
feat(proxy): warn at startup when no master key is configured
This commit is contained in:
parent
2f4032a984
commit
d729121a14
4 changed files with 61 additions and 18 deletions
|
|
@ -3,13 +3,20 @@ from typing import Final
|
|||
INSECURE_MASTER_KEYS: Final = frozenset({"sk-1234"})
|
||||
|
||||
|
||||
def insecure_master_key_warning(master_key: str | None) -> str | None:
|
||||
if master_key not in INSECURE_MASTER_KEYS:
|
||||
return None
|
||||
return (
|
||||
"LITELLM_MASTER_KEY is set to the example key 'sk-1234' from the docs. "
|
||||
"Anyone who has read the docs can administer this gateway, and publicly reachable "
|
||||
"gateways using this key have been compromised. Set a strong random master key "
|
||||
"(e.g. `python -c \"import secrets; print('sk-' + secrets.token_urlsafe(32))\"`). "
|
||||
"A future release will refuse to start with this key."
|
||||
)
|
||||
def insecure_master_key_warning(master_key: str | None, alternative_auth_enabled: bool) -> str | None:
|
||||
if master_key in INSECURE_MASTER_KEYS:
|
||||
return (
|
||||
"LITELLM_MASTER_KEY is set to the example key 'sk-1234' from the docs. "
|
||||
"Anyone who has read the docs can administer this gateway, and publicly reachable "
|
||||
"gateways using this key have been compromised. Set a strong random master key "
|
||||
"(e.g. `python -c \"import secrets; print('sk-' + secrets.token_urlsafe(32))\"`). "
|
||||
"A future release will refuse to start with this key."
|
||||
)
|
||||
if (master_key is None or master_key == "") and not alternative_auth_enabled:
|
||||
return (
|
||||
"No master key is set (LITELLM_MASTER_KEY or general_settings.master_key). "
|
||||
"Every request to this proxy is accepted without authentication, including "
|
||||
'admin routes. Set a strong random master key (e.g. `python -c "import secrets; '
|
||||
"print('sk-' + secrets.token_urlsafe(32))\"`) before exposing it to a network."
|
||||
)
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -1160,7 +1160,12 @@ async def proxy_startup_event(app: FastAPI) -> AsyncGenerator[None, None]:
|
|||
if isinstance(worker_config, dict):
|
||||
await initialize(**worker_config)
|
||||
|
||||
_insecure_master_key_warning: Final = insecure_master_key_warning(master_key)
|
||||
_alternative_auth_enabled: Final = any(
|
||||
general_settings.get(k, False) for k in ("enable_jwt_auth", "enable_oauth2_auth", "enable_oauth2_proxy_auth")
|
||||
)
|
||||
_insecure_master_key_warning: Final = insecure_master_key_warning(
|
||||
master_key, alternative_auth_enabled=_alternative_auth_enabled
|
||||
)
|
||||
if _insecure_master_key_warning is not None:
|
||||
verbose_proxy_logger.warning(_insecure_master_key_warning)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,22 +3,36 @@ from litellm.proxy.auth.master_key_policy import insecure_master_key_warning
|
|||
|
||||
|
||||
def test_insecure_master_key_warning_returned_for_example_key():
|
||||
warning = insecure_master_key_warning("sk-1234")
|
||||
warning = insecure_master_key_warning("sk-1234", alternative_auth_enabled=False)
|
||||
|
||||
assert warning is not None
|
||||
assert "sk-1234" in warning
|
||||
|
||||
|
||||
def test_insecure_master_key_warning_for_missing_key():
|
||||
warning = insecure_master_key_warning(None, alternative_auth_enabled=False)
|
||||
|
||||
assert warning is not None
|
||||
assert "No master key" in warning
|
||||
|
||||
|
||||
def test_insecure_master_key_warning_for_empty_key():
|
||||
warning = insecure_master_key_warning("", alternative_auth_enabled=False)
|
||||
|
||||
assert warning is not None
|
||||
assert "No master key" in warning
|
||||
|
||||
|
||||
def test_insecure_master_key_warning_none_for_missing_key_with_alt_auth():
|
||||
assert insecure_master_key_warning(None, alternative_auth_enabled=True) is None
|
||||
|
||||
|
||||
def test_insecure_master_key_warning_none_for_strong_key():
|
||||
assert insecure_master_key_warning("sk-strong-random-key") is None
|
||||
|
||||
|
||||
def test_insecure_master_key_warning_none_for_none():
|
||||
assert insecure_master_key_warning(None) is None
|
||||
assert insecure_master_key_warning("sk-strong-random-key", alternative_auth_enabled=False) is None
|
||||
|
||||
|
||||
def test_insecure_master_key_warning_survives_redaction():
|
||||
warning = insecure_master_key_warning("sk-1234")
|
||||
warning = insecure_master_key_warning("sk-1234", alternative_auth_enabled=False)
|
||||
|
||||
assert warning is not None
|
||||
assert "secrets.token_urlsafe" in redact_string(warning)
|
||||
|
|
|
|||
|
|
@ -1090,3 +1090,20 @@ async def test_proxy_startup_event_warns_but_does_not_raise_for_docs_example_mas
|
|||
pass
|
||||
|
||||
assert "sk-1234" in caplog.text, "startup should log the insecure master key warning"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_proxy_startup_event_warns_but_does_not_raise_for_missing_master_key(monkeypatch, caplog):
|
||||
monkeypatch.delenv("LITELLM_MASTER_KEY", raising=False)
|
||||
|
||||
try:
|
||||
with caplog.at_level(logging.WARNING, logger="LiteLLM Proxy"):
|
||||
async with proxy_startup_event(app=None):
|
||||
pass
|
||||
except ValueError as e:
|
||||
if "master key" in str(e).lower():
|
||||
pytest.fail("proxy_startup_event refused to boot without a master key")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
assert "No master key" in caplog.text, "startup should log the missing master key warning"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue