diff --git a/litellm/proxy/auth/handle_jwt.py b/litellm/proxy/auth/handle_jwt.py index d1fd5818f35..a4cd5068a1f 100644 --- a/litellm/proxy/auth/handle_jwt.py +++ b/litellm/proxy/auth/handle_jwt.py @@ -874,13 +874,15 @@ class JWTAuthManager: if role_based_models is None or model is None: return True - if model not in role_based_models: - raise HTTPException( - status_code=403, - detail=f"Role={rbac_role} not allowed to call model={model}. Allowed models={role_based_models}", - ) + if model in role_based_models or any( + fnmatch.fnmatch(model, pattern) for pattern in role_based_models + ): + return True - return True + raise HTTPException( + status_code=403, + detail=f"Role={rbac_role} not allowed to call model={model}. Allowed models={role_based_models}", + ) @staticmethod def check_scope_based_access( diff --git a/tests/proxy_unit_tests/test_user_api_key_auth.py b/tests/proxy_unit_tests/test_user_api_key_auth.py index 210347aaf94..0df3fa6125b 100644 --- a/tests/proxy_unit_tests/test_user_api_key_auth.py +++ b/tests/proxy_unit_tests/test_user_api_key_auth.py @@ -1051,6 +1051,42 @@ def test_can_rbac_role_call_model_no_role_permissions(): ) +def test_can_rbac_role_call_model_wildcard(): + """Wildcard patterns in role_permissions.models should match model names.""" + from litellm.proxy.auth.handle_jwt import JWTAuthManager + from litellm.proxy._types import RoleBasedPermissions + + roles_based_permissions = [ + RoleBasedPermissions( + role=LitellmUserRoles.INTERNAL_USER, + models=["bedrock-claude-*"], + ), + RoleBasedPermissions( + role=LitellmUserRoles.PROXY_ADMIN, + models=["*"], + ), + ] + + assert JWTAuthManager.can_rbac_role_call_model( + rbac_role=LitellmUserRoles.INTERNAL_USER, + general_settings={"role_permissions": roles_based_permissions}, + model="bedrock-claude-draft-rep-sonnet", + ) + + assert JWTAuthManager.can_rbac_role_call_model( + rbac_role=LitellmUserRoles.PROXY_ADMIN, + general_settings={"role_permissions": roles_based_permissions}, + model="any-model-name", + ) + + with pytest.raises(HTTPException): + JWTAuthManager.can_rbac_role_call_model( + rbac_role=LitellmUserRoles.INTERNAL_USER, + general_settings={"role_permissions": roles_based_permissions}, + model="openai-gpt-4", + ) + + @pytest.mark.parametrize( "route, request_data, expected_model", [