chore(proxy): block env callback refs in key metadata
This commit is contained in:
parent
b1b98c3fc7
commit
f2f1e3a0ba
@ -23,6 +23,13 @@ def _raise_env_reference_error(param: str, *, source: str) -> None:
|
||||
)
|
||||
|
||||
|
||||
def validate_no_callback_env_reference(
|
||||
param: str, value: object, *, source: str
|
||||
) -> None:
|
||||
if _is_env_reference(value):
|
||||
_raise_env_reference_error(param, source=source)
|
||||
|
||||
|
||||
# Hardcoded list of supported callback params to avoid runtime inspection issues with TypedDict
|
||||
_supported_callback_params = [
|
||||
"langfuse_public_key",
|
||||
@ -66,8 +73,9 @@ def initialize_standard_callback_dynamic_params(
|
||||
for param in _supported_callback_params:
|
||||
if param in kwargs:
|
||||
_param_value = kwargs.get(param)
|
||||
if _is_env_reference(_param_value):
|
||||
_raise_env_reference_error(param, source="request body")
|
||||
validate_no_callback_env_reference(
|
||||
param, _param_value, source="request body"
|
||||
)
|
||||
standard_callback_dynamic_params[param] = _param_value # type: ignore
|
||||
|
||||
# 2. Fallback: check "metadata" or "litellm_params" -> "metadata"
|
||||
@ -80,8 +88,9 @@ def initialize_standard_callback_dynamic_params(
|
||||
for param in _supported_callback_params:
|
||||
if param not in standard_callback_dynamic_params and param in metadata:
|
||||
_param_value = metadata.get(param)
|
||||
if _is_env_reference(_param_value):
|
||||
_raise_env_reference_error(param, source="metadata")
|
||||
validate_no_callback_env_reference(
|
||||
param, _param_value, source="metadata"
|
||||
)
|
||||
standard_callback_dynamic_params[param] = _param_value # type: ignore
|
||||
|
||||
return standard_callback_dynamic_params
|
||||
|
||||
@ -17,6 +17,9 @@ from typing_extensions import Required, TypedDict
|
||||
|
||||
from litellm._uuid import uuid
|
||||
from litellm.constants import MCP_STDIO_ALLOWED_COMMANDS
|
||||
from litellm.litellm_core_utils.initialize_dynamic_callback_params import (
|
||||
validate_no_callback_env_reference,
|
||||
)
|
||||
from litellm.types.integrations.slack_alerting import AlertType
|
||||
from litellm.types.llms.openai import (
|
||||
AllMessageValues,
|
||||
@ -1870,6 +1873,10 @@ class AddTeamCallback(LiteLLMPydanticObjectBase):
|
||||
)
|
||||
if not isinstance(value, str):
|
||||
callback_vars[key] = str(value)
|
||||
value = callback_vars[key]
|
||||
validate_no_callback_env_reference(
|
||||
key, value, source="key/team callback metadata"
|
||||
)
|
||||
return values
|
||||
|
||||
|
||||
|
||||
@ -228,9 +228,7 @@ def convert_key_logging_metadata_to_callback(
|
||||
for var, value in data.callback_vars.items():
|
||||
if team_callback_settings_obj.callback_vars is None:
|
||||
team_callback_settings_obj.callback_vars = {}
|
||||
team_callback_settings_obj.callback_vars[var] = str(
|
||||
litellm.utils.get_secret(value, default_value=value) or value
|
||||
)
|
||||
team_callback_settings_obj.callback_vars[var] = str(value)
|
||||
|
||||
return team_callback_settings_obj
|
||||
|
||||
@ -904,6 +902,14 @@ class LiteLLMProxyRequestSetup:
|
||||
callback_vars_dict.pop("team_id", None)
|
||||
callback_vars_dict.pop("success_callback", None)
|
||||
callback_vars_dict.pop("failure_callback", None)
|
||||
callback_vars_dict = {
|
||||
key: (
|
||||
litellm.utils.get_secret(value, default_value=value) or value
|
||||
if isinstance(value, str)
|
||||
else value
|
||||
)
|
||||
for key, value in callback_vars_dict.items()
|
||||
}
|
||||
|
||||
return TeamCallbackMetadata(
|
||||
success_callback=team_config.get("success_callback", None),
|
||||
|
||||
@ -235,18 +235,10 @@ async def test_add_key_or_team_level_spend_logs_metadata_to_request(
|
||||
"langfuse_host": "https://us.cloud.langfuse.com",
|
||||
"langfuse_public_key": "pk-lf-9636b7a6-c066",
|
||||
"langfuse_secret_key": "sk-lf-7cc8b620",
|
||||
},
|
||||
{
|
||||
"langfuse_host": "os.environ/LANGFUSE_HOST_TEMP",
|
||||
"langfuse_public_key": "os.environ/LANGFUSE_PUBLIC_KEY_TEMP",
|
||||
"langfuse_secret_key": "os.environ/LANGFUSE_SECRET_KEY_TEMP",
|
||||
},
|
||||
}
|
||||
],
|
||||
)
|
||||
def test_dynamic_logging_metadata_key_and_team_metadata(callback_vars):
|
||||
os.environ["LANGFUSE_PUBLIC_KEY_TEMP"] = "pk-lf-9636b7a6-c066"
|
||||
os.environ["LANGFUSE_SECRET_KEY_TEMP"] = "sk-lf-7cc8b620"
|
||||
os.environ["LANGFUSE_HOST_TEMP"] = "https://us.cloud.langfuse.com"
|
||||
from litellm.proxy.proxy_server import ProxyConfig
|
||||
|
||||
proxy_config = ProxyConfig()
|
||||
@ -317,6 +309,38 @@ def test_dynamic_logging_metadata_key_and_team_metadata(callback_vars):
|
||||
assert "os.environ" not in var
|
||||
|
||||
|
||||
def test_dynamic_logging_metadata_rejects_env_references_from_key_metadata(
|
||||
monkeypatch,
|
||||
):
|
||||
monkeypatch.setenv("LANGFUSE_SECRET_KEY_TEMP", "server-side-secret")
|
||||
from litellm.proxy.proxy_server import ProxyConfig
|
||||
|
||||
proxy_config = ProxyConfig()
|
||||
user_api_key_dict = UserAPIKeyAuth(
|
||||
api_key="test-key",
|
||||
metadata={
|
||||
"logging": [
|
||||
{
|
||||
"callback_name": "langfuse",
|
||||
"callback_type": "success",
|
||||
"callback_vars": {
|
||||
"langfuse_secret_key": "os.environ/LANGFUSE_SECRET_KEY_TEMP",
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
team_metadata={},
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
_get_dynamic_logging_metadata(
|
||||
user_api_key_dict=user_api_key_dict, proxy_config=proxy_config
|
||||
)
|
||||
|
||||
assert "os.environ/" in str(exc_info.value)
|
||||
assert "server-side-secret" not in str(exc_info.value)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"callback_vars",
|
||||
[
|
||||
@ -1263,11 +1287,16 @@ def test_proxy_config_state_post_init_callback_call(monkeypatch):
|
||||
}
|
||||
)
|
||||
|
||||
LiteLLMProxyRequestSetup.add_team_based_callbacks_from_config(
|
||||
callback_metadata = LiteLLMProxyRequestSetup.add_team_based_callbacks_from_config(
|
||||
team_id="test",
|
||||
proxy_config=pc,
|
||||
)
|
||||
|
||||
assert callback_metadata is not None
|
||||
assert callback_metadata.callback_vars is not None
|
||||
assert callback_metadata.callback_vars["langfuse_public_key"] == "test_public_key"
|
||||
assert callback_metadata.callback_vars["langfuse_secret"] == "test_secret_key"
|
||||
|
||||
config = pc.get_config_state()
|
||||
assert config["litellm_settings"]["default_team_settings"][0]["team_id"] == "test"
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user