mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-21 00:21:49 +00:00
test_add_guardrails_from_policy_engine_accepts_dynamic_policies_and_pops_from_data
This commit is contained in:
parent
28ef76ba16
commit
c7ee433fc4
2 changed files with 66 additions and 6 deletions
|
|
@ -1500,10 +1500,13 @@ def add_guardrails_from_policy_engine(
|
|||
Add guardrails from the policy engine based on request context.
|
||||
|
||||
This function:
|
||||
1. Gets matching policies based on team_alias, key_alias, and model
|
||||
2. Resolves guardrails from matching policies (including inheritance)
|
||||
3. Adds guardrails to request metadata
|
||||
4. Tracks applied policies in metadata for response headers
|
||||
1. Extracts "policies" from request body (if present) for dynamic policy application
|
||||
2. Gets matching policies based on team_alias, key_alias, and model (via attachments)
|
||||
3. Combines dynamic policies with attachment-based policies
|
||||
4. Resolves guardrails from all policies (including inheritance)
|
||||
5. Adds guardrails to request metadata
|
||||
6. Tracks applied policies in metadata for response headers
|
||||
7. Removes "policies" from request body so it's not forwarded to LLM provider
|
||||
|
||||
Args:
|
||||
data: The request data to update
|
||||
|
|
@ -1519,6 +1522,10 @@ def add_guardrails_from_policy_engine(
|
|||
from litellm.proxy.policy_engine.policy_resolver import PolicyResolver
|
||||
from litellm.types.proxy.policy_engine import PolicyMatchContext
|
||||
|
||||
# Extract dynamic policies from request body (if present)
|
||||
# These will be combined with attachment-based policies
|
||||
request_body_policies = data.pop("policies", None)
|
||||
|
||||
registry = get_policy_registry()
|
||||
verbose_proxy_logger.debug(
|
||||
f"Policy engine: registry initialized={registry.is_initialized()}, "
|
||||
|
|
@ -1545,12 +1552,18 @@ def add_guardrails_from_policy_engine(
|
|||
|
||||
verbose_proxy_logger.debug(f"Policy engine: matched policies via attachments: {matching_policy_names}")
|
||||
|
||||
if not matching_policy_names:
|
||||
# Combine attachment-based policies with dynamic request body policies
|
||||
all_policy_names = set(matching_policy_names)
|
||||
if request_body_policies and isinstance(request_body_policies, list):
|
||||
all_policy_names.update(request_body_policies)
|
||||
verbose_proxy_logger.debug(f"Policy engine: added dynamic policies from request body: {request_body_policies}")
|
||||
|
||||
if not all_policy_names:
|
||||
return
|
||||
|
||||
# Filter to only policies whose conditions match the context
|
||||
applied_policy_names = PolicyMatcher.get_policies_with_matching_conditions(
|
||||
policy_names=matching_policy_names,
|
||||
policy_names=list(all_policy_names),
|
||||
context=context,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1548,3 +1548,50 @@ def test_add_guardrails_from_policy_engine():
|
|||
policy_registry._initialized = False
|
||||
attachment_registry._attachments = []
|
||||
attachment_registry._initialized = False
|
||||
|
||||
|
||||
def test_add_guardrails_from_policy_engine_accepts_dynamic_policies_and_pops_from_data():
|
||||
"""
|
||||
Test that add_guardrails_from_policy_engine accepts dynamic 'policies' from the request body
|
||||
and removes them to prevent forwarding to the LLM provider.
|
||||
|
||||
This is critical because 'policies' is a LiteLLM proxy-specific parameter that should
|
||||
not be sent to the actual LLM API (e.g., OpenAI, Anthropic, etc.).
|
||||
"""
|
||||
from litellm.proxy.policy_engine.policy_registry import get_policy_registry
|
||||
|
||||
# Setup test data with 'policies' in the request body
|
||||
data = {
|
||||
"model": "gpt-4",
|
||||
"messages": [{"role": "user", "content": "Hello"}],
|
||||
"policies": ["PII-POLICY-GLOBAL", "HIPAA-POLICY"], # Dynamic policies - should be accepted and removed
|
||||
"metadata": {},
|
||||
}
|
||||
|
||||
user_api_key_dict = UserAPIKeyAuth(
|
||||
api_key="test-key",
|
||||
team_alias="test-team",
|
||||
key_alias="test-key",
|
||||
)
|
||||
|
||||
# Initialize empty policy registry (we're just testing the accept and pop behavior)
|
||||
policy_registry = get_policy_registry()
|
||||
policy_registry._policies = {}
|
||||
policy_registry._initialized = False
|
||||
|
||||
# Call the function - should accept dynamic policies and not raise an error
|
||||
add_guardrails_from_policy_engine(
|
||||
data=data,
|
||||
metadata_variable_name="metadata",
|
||||
user_api_key_dict=user_api_key_dict,
|
||||
)
|
||||
|
||||
# Verify that 'policies' was removed from the request body
|
||||
assert "policies" not in data, "'policies' should be removed from request body to prevent forwarding to LLM provider"
|
||||
|
||||
# Verify that other fields are preserved
|
||||
assert "model" in data
|
||||
assert data["model"] == "gpt-4"
|
||||
assert "messages" in data
|
||||
assert data["messages"] == [{"role": "user", "content": "Hello"}]
|
||||
assert "metadata" in data
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue