fix(route_checks.py): ensure allowed passthrough endpoint routes are respected
This commit is contained in:
parent
ecc391be6b
commit
1d26397f17
@ -52,14 +52,11 @@ class RouteChecks:
|
||||
if len(valid_token.allowed_routes) == 0:
|
||||
return True
|
||||
|
||||
# explicit check for allowed routes
|
||||
if route in valid_token.allowed_routes:
|
||||
return True
|
||||
|
||||
# check if any allowed_route is a prefix of the actual route
|
||||
# e.g., allowed_route="/fake-openai-proxy-6" matches route="/fake-openai-proxy-6/v1/chat/completions"
|
||||
# explicit check for allowed routes (exact match or prefix match)
|
||||
for allowed_route in valid_token.allowed_routes:
|
||||
if route.startswith(allowed_route + "/") or route == allowed_route:
|
||||
if RouteChecks._route_matches_allowed_route(
|
||||
route=route, allowed_route=allowed_route
|
||||
):
|
||||
return True
|
||||
|
||||
## check if 'allowed_route' is a field name in LiteLLMRoutes
|
||||
@ -204,18 +201,19 @@ class RouteChecks:
|
||||
pass
|
||||
elif route.startswith("/v1/mcp/") or route.startswith("/mcp-rest/"):
|
||||
pass # authN/authZ handled by api itself
|
||||
elif RouteChecks.check_passthrough_route_access(
|
||||
route=route, user_api_key_dict=valid_token
|
||||
):
|
||||
pass
|
||||
elif valid_token.allowed_routes is not None:
|
||||
# check if route is in allowed_routes (exact match or prefix match)
|
||||
route_allowed = False
|
||||
if route in valid_token.allowed_routes:
|
||||
route_allowed = True
|
||||
else:
|
||||
# check if any allowed_route is a prefix of the actual route
|
||||
# e.g., allowed_route="/fake-openai-proxy-6" matches route="/fake-openai-proxy-6/v1/chat/completions"
|
||||
for allowed_route in valid_token.allowed_routes:
|
||||
if route.startswith(allowed_route + "/") or route == allowed_route:
|
||||
route_allowed = True
|
||||
break
|
||||
for allowed_route in valid_token.allowed_routes:
|
||||
if RouteChecks._route_matches_allowed_route(
|
||||
route=route, allowed_route=allowed_route
|
||||
):
|
||||
route_allowed = True
|
||||
break
|
||||
|
||||
if route_allowed:
|
||||
pass
|
||||
@ -382,6 +380,32 @@ class RouteChecks:
|
||||
# If there's no wildcard, the pattern and route should match exactly
|
||||
return route == pattern
|
||||
|
||||
@staticmethod
|
||||
def _route_matches_allowed_route(route: str, allowed_route: str) -> bool:
|
||||
"""
|
||||
Check if route matches the allowed_route pattern.
|
||||
Supports both exact match and prefix match.
|
||||
|
||||
Examples:
|
||||
- allowed_route="/fake-openai-proxy-6", route="/fake-openai-proxy-6" -> True (exact match)
|
||||
- allowed_route="/fake-openai-proxy-6", route="/fake-openai-proxy-6/v1/chat/completions" -> True (prefix match)
|
||||
- allowed_route="/fake-openai-proxy-6", route="/fake-openai-proxy-600" -> False (not a valid prefix)
|
||||
|
||||
Args:
|
||||
route: The actual route being accessed
|
||||
allowed_route: The allowed route pattern
|
||||
|
||||
Returns:
|
||||
bool: True if route matches (exact or prefix), False otherwise
|
||||
"""
|
||||
# Exact match
|
||||
if route == allowed_route:
|
||||
return True
|
||||
# Prefix match - ensure we add "/" to prevent false matches like /fake-openai-proxy-600
|
||||
if route.startswith(allowed_route + "/"):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def check_route_access(route: str, allowed_routes: List[str]) -> bool:
|
||||
"""
|
||||
@ -429,6 +453,33 @@ class RouteChecks:
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def check_passthrough_route_access(
|
||||
route: str, user_api_key_dict: UserAPIKeyAuth
|
||||
) -> bool:
|
||||
"""
|
||||
Check if route is a passthrough route.
|
||||
Supports both exact match and prefix match.
|
||||
"""
|
||||
metadata = user_api_key_dict.metadata
|
||||
if metadata is None:
|
||||
return False
|
||||
if "allowed_passthrough_routes" not in metadata:
|
||||
return False
|
||||
if metadata["allowed_passthrough_routes"] is None:
|
||||
return False
|
||||
|
||||
allowed_passthrough_routes = metadata["allowed_passthrough_routes"]
|
||||
|
||||
# Check if route matches any allowed passthrough route (exact or prefix match)
|
||||
for allowed_route in allowed_passthrough_routes:
|
||||
if RouteChecks._route_matches_allowed_route(
|
||||
route=route, allowed_route=allowed_route
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def _is_assistants_api_request(request: Request) -> bool:
|
||||
"""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user