mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
Address CR feedback: fix auth dependency duplication, correct logger wording, clean imports
This commit is contained in:
parent
ff38cd8c38
commit
2d2d7ced1a
4 changed files with 44 additions and 64 deletions
|
|
@ -2,6 +2,7 @@
|
|||
CRUD ENDPOINTS FOR GUARDRAILS
|
||||
"""
|
||||
|
||||
import concurrent.futures
|
||||
import inspect
|
||||
from typing import Any, Dict, List, Optional, Type, TypeVar, Union, cast
|
||||
|
||||
|
|
@ -11,9 +12,16 @@ from pydantic import BaseModel
|
|||
from litellm._logging import verbose_proxy_logger
|
||||
from litellm.constants import DEFAULT_MAX_RECURSE_DEPTH
|
||||
from litellm.integrations.custom_guardrail import CustomGuardrail
|
||||
from litellm.proxy._types import UserAPIKeyAuth
|
||||
from litellm.proxy._types import LitellmUserRoles, UserAPIKeyAuth
|
||||
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
|
||||
from litellm.proxy.guardrails.guardrail_registry import GuardrailRegistry
|
||||
from litellm.proxy.guardrails.guardrail_hooks.custom_code.code_validator import (
|
||||
CustomCodeValidationError,
|
||||
validate_custom_code,
|
||||
)
|
||||
from litellm.proxy.guardrails.guardrail_hooks.custom_code.primitives import (
|
||||
get_custom_code_primitives,
|
||||
)
|
||||
from litellm.proxy.guardrails.usage_endpoints import router as guardrails_usage_router
|
||||
from litellm.types.guardrails import (
|
||||
PII_ENTITY_CATEGORIES_MAP,
|
||||
|
|
@ -243,7 +251,6 @@ class CreateGuardrailRequest(BaseModel):
|
|||
@router.post(
|
||||
"/guardrails",
|
||||
tags=["Guardrails"],
|
||||
dependencies=[Depends(user_api_key_auth)],
|
||||
)
|
||||
async def create_guardrail(
|
||||
request: CreateGuardrailRequest,
|
||||
|
|
@ -298,7 +305,6 @@ async def create_guardrail(
|
|||
"""
|
||||
from litellm.proxy.guardrails.guardrail_registry import IN_MEMORY_GUARDRAIL_HANDLER
|
||||
from litellm.proxy.proxy_server import prisma_client
|
||||
from litellm.proxy._types import LitellmUserRoles
|
||||
|
||||
if user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN:
|
||||
raise HTTPException(
|
||||
|
|
@ -342,7 +348,6 @@ class UpdateGuardrailRequest(BaseModel):
|
|||
@router.put(
|
||||
"/guardrails/{guardrail_id}",
|
||||
tags=["Guardrails"],
|
||||
dependencies=[Depends(user_api_key_auth)],
|
||||
)
|
||||
async def update_guardrail(
|
||||
guardrail_id: str,
|
||||
|
|
@ -398,7 +403,6 @@ async def update_guardrail(
|
|||
"""
|
||||
from litellm.proxy.guardrails.guardrail_registry import IN_MEMORY_GUARDRAIL_HANDLER
|
||||
from litellm.proxy.proxy_server import prisma_client
|
||||
from litellm.proxy._types import LitellmUserRoles
|
||||
|
||||
if user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN:
|
||||
raise HTTPException(
|
||||
|
|
@ -450,7 +454,6 @@ async def update_guardrail(
|
|||
@router.delete(
|
||||
"/guardrails/{guardrail_id}",
|
||||
tags=["Guardrails"],
|
||||
dependencies=[Depends(user_api_key_auth)],
|
||||
)
|
||||
async def delete_guardrail(
|
||||
guardrail_id: str,
|
||||
|
|
@ -476,7 +479,6 @@ async def delete_guardrail(
|
|||
"""
|
||||
from litellm.proxy.guardrails.guardrail_registry import IN_MEMORY_GUARDRAIL_HANDLER
|
||||
from litellm.proxy.proxy_server import prisma_client
|
||||
from litellm.proxy._types import LitellmUserRoles
|
||||
|
||||
if user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN:
|
||||
raise HTTPException(
|
||||
|
|
@ -526,7 +528,6 @@ async def delete_guardrail(
|
|||
@router.patch(
|
||||
"/guardrails/{guardrail_id}",
|
||||
tags=["Guardrails"],
|
||||
dependencies=[Depends(user_api_key_auth)],
|
||||
)
|
||||
async def patch_guardrail(
|
||||
guardrail_id: str,
|
||||
|
|
@ -580,7 +581,6 @@ async def patch_guardrail(
|
|||
"""
|
||||
from litellm.proxy.guardrails.guardrail_registry import IN_MEMORY_GUARDRAIL_HANDLER
|
||||
from litellm.proxy.proxy_server import prisma_client
|
||||
from litellm.proxy._types import LitellmUserRoles
|
||||
|
||||
if user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN:
|
||||
raise HTTPException(
|
||||
|
|
@ -1406,7 +1406,6 @@ class TestCustomCodeGuardrailResponse(BaseModel):
|
|||
@router.post(
|
||||
"/guardrails/test_custom_code",
|
||||
tags=["Guardrails"],
|
||||
dependencies=[Depends(user_api_key_auth)],
|
||||
response_model=TestCustomCodeGuardrailResponse,
|
||||
)
|
||||
async def test_custom_code_guardrail(
|
||||
|
|
@ -1485,12 +1484,6 @@ async def test_custom_code_guardrail(
|
|||
}
|
||||
```
|
||||
"""
|
||||
import concurrent.futures
|
||||
|
||||
from litellm.proxy.guardrails.guardrail_hooks.custom_code.primitives import (
|
||||
get_custom_code_primitives,
|
||||
)
|
||||
from litellm.proxy._types import LitellmUserRoles
|
||||
|
||||
if user_api_key_dict.user_role != LitellmUserRoles.PROXY_ADMIN:
|
||||
raise HTTPException(
|
||||
|
|
@ -1502,10 +1495,6 @@ async def test_custom_code_guardrail(
|
|||
|
||||
try:
|
||||
# Step 0: Security validation - check for forbidden patterns
|
||||
from litellm.proxy.guardrails.guardrail_hooks.custom_code.code_validator import (
|
||||
validate_custom_code,
|
||||
CustomCodeValidationError,
|
||||
)
|
||||
|
||||
try:
|
||||
validate_custom_code(request.custom_code)
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ FORBIDDEN_PATTERNS: List[Tuple[str, str]] = [
|
|||
(r"\bos\.", "os module access is not allowed"),
|
||||
(r"\bsys\.", "sys module access is not allowed"),
|
||||
(r"\bsubprocess\.", "subprocess module access is not allowed"),
|
||||
(r"\bshutil\.", "shutil module access is not allowed"),
|
||||
(r"\bctypes\.", "ctypes module access is not allowed"),
|
||||
(r"\bsocket\.", "socket module access is not allowed"),
|
||||
(r"\bpickle\.", "pickle module access is not allowed"),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -144,6 +144,33 @@ class CustomCodeGuardrail(CustomGuardrail):
|
|||
"""Returns the config model for the UI."""
|
||||
return CustomCodeGuardrailConfigModel
|
||||
|
||||
def _do_compile(self) -> None:
|
||||
"""Internal compilation method without lock. Expected to run inside _compile_lock."""
|
||||
# Create a restricted execution environment
|
||||
# Only include our safe primitives
|
||||
exec_globals = get_custom_code_primitives().copy()
|
||||
|
||||
# CRITICAL: Restrict __builtins__ to prevent sandbox escape
|
||||
exec_globals["__builtins__"] = {}
|
||||
|
||||
# Execute the user code in the restricted environment
|
||||
exec(compile(self.custom_code, "<guardrail>", "exec"), exec_globals)
|
||||
|
||||
# Extract the apply_guardrail function
|
||||
if "apply_guardrail" not in exec_globals:
|
||||
raise CustomCodeCompilationError(
|
||||
"Custom code must define an 'apply_guardrail' function. "
|
||||
"Expected signature: apply_guardrail(inputs, request_data, input_type)"
|
||||
)
|
||||
|
||||
apply_fn = exec_globals["apply_guardrail"]
|
||||
if not callable(apply_fn):
|
||||
raise CustomCodeCompilationError(
|
||||
"'apply_guardrail' must be a callable function"
|
||||
)
|
||||
|
||||
self._compiled_function = apply_fn
|
||||
|
||||
def _compile_custom_code(self) -> None:
|
||||
"""
|
||||
Compile the custom code and extract the apply_guardrail function.
|
||||
|
|
@ -161,30 +188,8 @@ class CustomCodeGuardrail(CustomGuardrail):
|
|||
except CustomCodeValidationError as e:
|
||||
raise CustomCodeCompilationError(str(e)) from e
|
||||
|
||||
# Create a restricted execution environment
|
||||
# Only include our safe primitives
|
||||
exec_globals = get_custom_code_primitives().copy()
|
||||
|
||||
# CRITICAL: Restrict __builtins__ to prevent sandbox escape
|
||||
exec_globals["__builtins__"] = {}
|
||||
|
||||
# Execute the user code in the restricted environment
|
||||
exec(compile(self.custom_code, "<guardrail>", "exec"), exec_globals)
|
||||
|
||||
# Extract the apply_guardrail function
|
||||
if "apply_guardrail" not in exec_globals:
|
||||
raise CustomCodeCompilationError(
|
||||
"Custom code must define an 'apply_guardrail' function. "
|
||||
"Expected signature: apply_guardrail(inputs, request_data, input_type)"
|
||||
)
|
||||
|
||||
apply_fn = exec_globals["apply_guardrail"]
|
||||
if not callable(apply_fn):
|
||||
raise CustomCodeCompilationError(
|
||||
"'apply_guardrail' must be a callable function"
|
||||
)
|
||||
|
||||
self._compiled_function = apply_fn
|
||||
# Step 2: Compile logic
|
||||
self._do_compile()
|
||||
verbose_proxy_logger.debug(
|
||||
f"Custom code guardrail '{self.guardrail_name}' compiled successfully"
|
||||
)
|
||||
|
|
@ -415,25 +420,7 @@ class CustomCodeGuardrail(CustomGuardrail):
|
|||
|
||||
try:
|
||||
self.custom_code = new_code
|
||||
# Inline compilation instead of calling _compile_custom_code()
|
||||
# to avoid deadlock (re-acquiring self._compile_lock)
|
||||
exec_globals = get_custom_code_primitives().copy()
|
||||
exec_globals["__builtins__"] = {}
|
||||
exec(compile(self.custom_code, "<guardrail>", "exec"), exec_globals)
|
||||
|
||||
if "apply_guardrail" not in exec_globals:
|
||||
raise CustomCodeCompilationError(
|
||||
"Custom code must define an 'apply_guardrail' function. "
|
||||
"Expected signature: apply_guardrail(inputs, request_data, input_type)"
|
||||
)
|
||||
|
||||
apply_fn = exec_globals["apply_guardrail"]
|
||||
if not callable(apply_fn):
|
||||
raise CustomCodeCompilationError(
|
||||
"'apply_guardrail' must be a callable function"
|
||||
)
|
||||
|
||||
self._compiled_function = apply_fn
|
||||
self._do_compile()
|
||||
verbose_proxy_logger.info(
|
||||
f"Custom code guardrail '{self.guardrail_name}': Code updated successfully"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2994,7 +2994,7 @@ class ProxyConfig:
|
|||
litellm_master_key_hash = hash_token(master_key)
|
||||
else:
|
||||
verbose_proxy_logger.critical(
|
||||
"LITELLM_MASTER_KEY is not set! All unauthenticated requests will be treated as INTERNAL_USER. This is insecure for production."
|
||||
"LITELLM_MASTER_KEY is not set! All requests will be treated as INTERNAL_USER with no admin access. Set LITELLM_MASTER_KEY for production use."
|
||||
)
|
||||
### USER API KEY CACHE IN-MEMORY TTL ###
|
||||
user_api_key_cache_ttl = general_settings.get(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue