fix(proxy_server.py): re-encrypt env var on config save + use original value on decrypt error (#15671)
* fix(proxy_server.py): re-encrypt env var on config save + use original value on decrypt error Closes https://github.com/BerriAI/litellm/issues/14854 Fixes https://github.com/BerriAI/litellm/issues/13406 * docs: email.md document PROXY_BASE_URL param * fix(proxy_server.py): pop model list before writing to db
This commit is contained in:
parent
a91e3f1873
commit
c1355e92dc
@ -141,6 +141,7 @@ LiteLLM allows you to customize various aspects of your email notifications. Bel
|
||||
| Email Signature | `EMAIL_SIGNATURE` | string (HTML) | Standard LiteLLM footer | `"<p>Best regards,<br/>Your Team</p><p><a href='https://your-company.com'>Visit us</a></p>"` | HTML-formatted footer for all emails |
|
||||
| Invitation Subject | `EMAIL_SUBJECT_INVITATION` | string | "LiteLLM: New User Invitation" | `"Welcome to Your Company!"` | Subject line for invitation emails |
|
||||
| Key Creation Subject | `EMAIL_SUBJECT_KEY_CREATED` | string | "LiteLLM: API Key Created" | `"Your New API Key is Ready"` | Subject line for key creation emails |
|
||||
| Proxy Base URL | `PROXY_BASE_URL` | string | http://0.0.0.0:4000 | `"https://proxy.your-company.com"` | Base URL for the LiteLLM Proxy (used in email links) |
|
||||
|
||||
|
||||
## HTML Support in Email Signature
|
||||
@ -180,6 +181,9 @@ EMAIL_SIGNATURE="<p>Best regards,<br/>Your Company Team</p><p><a href='https://y
|
||||
# Email Subject Lines
|
||||
EMAIL_SUBJECT_INVITATION="Welcome to Your Company!" # Subject for invitation emails
|
||||
EMAIL_SUBJECT_KEY_CREATED="Your API Key is Ready" # Subject for key creation emails
|
||||
|
||||
# Proxy Configuration
|
||||
PROXY_BASE_URL="https://proxy.your-company.com" # Base URL for the LiteLLM Proxy (used in email links)
|
||||
```
|
||||
|
||||
## HTML Support in Email Signature
|
||||
@ -225,3 +229,17 @@ EMAIL_SUBJECT_KEY_CREATED="Your \{company_name\} API Key"
|
||||
```
|
||||
|
||||
The system will automatically replace `\{event_message\}` and other template variables with their actual values when sending emails.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why do I see "http://0.0.0.0:4000" in the email links?
|
||||
|
||||
The `PROXY_BASE_URL` environment variable is used to construct email links. If you are using the LiteLLM Proxy in a local environment, you will see "http://0.0.0.0:4000" in the email links.
|
||||
|
||||
If you are using the LiteLLM Proxy in a production environment, you will see the actual base URL of the LiteLLM Proxy.
|
||||
|
||||
You can set the `PROXY_BASE_URL` environment variable to the actual base URL of the LiteLLM Proxy.
|
||||
|
||||
```bash
|
||||
PROXY_BASE_URL="https://proxy.your-company.com"
|
||||
```
|
||||
@ -61,9 +61,12 @@ def decrypt_value_helper(
|
||||
verbose_proxy_logger.debug(
|
||||
f"Unable to decrypt value={value} for key: {key}, returning None"
|
||||
)
|
||||
verbose_proxy_logger.exception(error_message)
|
||||
# [Non-Blocking Exception. - this should not block decrypting other values]
|
||||
return value if return_original_value else None
|
||||
if return_original_value:
|
||||
return value
|
||||
else:
|
||||
verbose_proxy_logger.exception(error_message)
|
||||
# [Non-Blocking Exception. - this should not block decrypting other values]
|
||||
return None
|
||||
|
||||
|
||||
def encrypt_value(value: str, signing_key: str):
|
||||
|
||||
@ -262,9 +262,7 @@ from litellm.proxy.management_endpoints.customer_endpoints import (
|
||||
from litellm.proxy.management_endpoints.internal_user_endpoints import (
|
||||
router as internal_user_router,
|
||||
)
|
||||
from litellm.proxy.management_endpoints.internal_user_endpoints import (
|
||||
user_update,
|
||||
)
|
||||
from litellm.proxy.management_endpoints.internal_user_endpoints import user_update
|
||||
from litellm.proxy.management_endpoints.key_management_endpoints import (
|
||||
delete_verification_tokens,
|
||||
duration_in_seconds,
|
||||
@ -312,9 +310,7 @@ from litellm.proxy.ocr_endpoints.endpoints import router as ocr_router
|
||||
from litellm.proxy.openai_files_endpoints.files_endpoints import (
|
||||
router as openai_files_router,
|
||||
)
|
||||
from litellm.proxy.openai_files_endpoints.files_endpoints import (
|
||||
set_files_config,
|
||||
)
|
||||
from litellm.proxy.openai_files_endpoints.files_endpoints import set_files_config
|
||||
from litellm.proxy.pass_through_endpoints.llm_passthrough_endpoints import (
|
||||
passthrough_endpoint_router,
|
||||
)
|
||||
@ -1669,8 +1665,28 @@ class ProxyConfig:
|
||||
):
|
||||
# if using - db for config - models are in ModelTable
|
||||
|
||||
new_config.pop("model_list", None)
|
||||
await prisma_client.insert_data(data=new_config, table_name="config")
|
||||
# Make a copy to avoid mutating the original config
|
||||
config_to_save = new_config.copy()
|
||||
|
||||
# SECURITY: Always encrypt environment_variables before DB write
|
||||
if (
|
||||
"environment_variables" in config_to_save
|
||||
and config_to_save["environment_variables"]
|
||||
):
|
||||
|
||||
# decrypt the environment_variables - in case a caller function has already encrypted the environment_variables
|
||||
decrypted_env_vars = self._decrypt_and_set_db_env_variables(
|
||||
environment_variables=config_to_save["environment_variables"],
|
||||
return_original_value=True,
|
||||
)
|
||||
|
||||
# encrypt the environment_variables,
|
||||
config_to_save["environment_variables"] = self._encrypt_env_variables(
|
||||
environment_variables=decrypted_env_vars
|
||||
)
|
||||
|
||||
config_to_save.pop("model_list", None)
|
||||
await prisma_client.insert_data(data=config_to_save, table_name="config")
|
||||
else:
|
||||
# Save the updated config - if user is not using a dB
|
||||
## YAML
|
||||
@ -2847,7 +2863,9 @@ class ProxyConfig:
|
||||
encrypted_env_vars[k] = encrypted_value
|
||||
return encrypted_env_vars
|
||||
|
||||
def _decrypt_and_set_db_env_variables(self, environment_variables: dict) -> dict:
|
||||
def _decrypt_and_set_db_env_variables(
|
||||
self, environment_variables: dict, return_original_value: bool = False
|
||||
) -> dict:
|
||||
"""
|
||||
Decrypts a dictionary of environment variables and then sets them in the environment
|
||||
|
||||
@ -2858,7 +2876,9 @@ class ProxyConfig:
|
||||
decrypted_env_vars = {}
|
||||
for k, v in environment_variables.items():
|
||||
try:
|
||||
decrypted_value = decrypt_value_helper(value=v, key=k)
|
||||
decrypted_value = decrypt_value_helper(
|
||||
value=v, key=k, return_original_value=return_original_value
|
||||
)
|
||||
if decrypted_value is not None:
|
||||
os.environ[k] = decrypted_value
|
||||
decrypted_env_vars[k] = decrypted_value
|
||||
@ -3056,7 +3076,9 @@ class ProxyConfig:
|
||||
d[k] = v
|
||||
|
||||
if param_name == "environment_variables":
|
||||
decrypted_env_vars = self._decrypt_and_set_db_env_variables(db_param_value)
|
||||
decrypted_env_vars = self._decrypt_and_set_db_env_variables(
|
||||
db_param_value, return_original_value=True
|
||||
)
|
||||
current_config.setdefault("environment_variables", {}).update(
|
||||
decrypted_env_vars
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user