feat(handle_jwt.py): initial commit adding custom RBAC support on jwt… (#8037)

* feat(handle_jwt.py): initial commit adding custom RBAC support on jwt auth

allows admin to define user role field and allowed roles which map to 'internal_user' on litellm

* fix(auth_checks.py): ensure user allowed to access model, when calling via personal keys

Fixes https://github.com/BerriAI/litellm/issues/8029

* feat(handle_jwt.py): support role based access with model permission control on proxy

Allows admin to just grant users roles on IDP (e.g. Azure AD/Keycloak) and user can immediately start calling models

* docs(rbac): add docs on rbac for model access control

make it clear how admin can use roles to control model access on proxy

* fix: fix linting errors

* test(test_user_api_key_auth.py): add unit testing to ensure rbac role is correctly enforced

* test(test_user_api_key_auth.py): add more testing

* test(test_users.py): add unit testing to ensure user model access is always checked for new keys

Resolves https://github.com/BerriAI/litellm/issues/8029

* test: fix unit test

* fix(dot_notation_indexing.py): fix typing to work with python 3.8
This commit is contained in:
Krish Dholakia
2025-01-28 16:27:06 -08:00
committed by GitHub
parent 9644e197f7
commit 2eaa0079f2
14 changed files with 648 additions and 84 deletions
+116
View File
@@ -0,0 +1,116 @@
import Image from '@theme/IdealImage';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# Control Model Access with SSO (Azure AD/Keycloak/etc.)
:::info
✨ JWT Auth is on LiteLLM Enterprise
[Enterprise Pricing](https://www.litellm.ai/#pricing)
[Get free 7-day trial key](https://www.litellm.ai/#trial)
:::
<Image img={require('../../img/control_model_access_jwt.png')} style={{ width: '100%', maxWidth: '4000px' }} />
## Example Token
<Tabs>
<TabItem value="Azure AD">
```bash
{
"sub": "1234567890",
"name": "John Doe",
"email": "john.doe@example.com",
"roles": ["basic_user"] # 👈 ROLE
}
```
</TabItem>
<TabItem value="Keycloak">
```bash
{
"sub": "1234567890",
"name": "John Doe",
"email": "john.doe@example.com",
"resource_access": {
"litellm-test-client-id": {
"roles": ["basic_user"] # 👈 ROLE
}
}
}
```
</TabItem>
</Tabs>
## Proxy Configuration
<Tabs>
<TabItem value="Azure AD">
```yaml
general_settings:
enable_jwt_auth: True
litellm_jwtauth:
user_roles_jwt_field: "roles" # the field in the JWT that contains the roles
user_allowed_roles: ["basic_user"] # roles that map to an 'internal_user' role on LiteLLM
enforce_rbac: true # if true, will check if the user has the correct role to access the model
role_permissions: # control what models are allowed for each role
- role: internal_user
models: ["anthropic-claude"]
model_list:
- model: anthropic-claude
litellm_params:
model: claude-3-5-haiku-20241022
- model: openai-gpt-4o
litellm_params:
model: gpt-4o
```
</TabItem>
<TabItem value="Keycloak">
```yaml
general_settings:
enable_jwt_auth: True
litellm_jwtauth:
user_roles_jwt_field: "resource_access.litellm-test-client-id.roles" # the field in the JWT that contains the roles
user_allowed_roles: ["basic_user"] # roles that map to an 'internal_user' role on LiteLLM
enforce_rbac: true # if true, will check if the user has the correct role to access the model
role_permissions: # control what models are allowed for each role
- role: internal_user
models: ["anthropic-claude"]
model_list:
- model: anthropic-claude
litellm_params:
model: claude-3-5-haiku-20241022
- model: openai-gpt-4o
litellm_params:
model: gpt-4o
```
</TabItem>
</Tabs>
## How it works
1. Specify JWT_PUBLIC_KEY_URL - This is the public keys endpoint of your OpenID provider. For Azure AD it's `https://login.microsoftonline.com/{tenant_id}/discovery/v2.0/keys`. For Keycloak it's `{keycloak_base_url}/realms/{your-realm}/protocol/openid-connect/certs`.
1. Map JWT roles to LiteLLM roles - Done via `user_roles_jwt_field` and `user_allowed_roles`
- Currently just `internal_user` is supported for role mapping.
2. Specify model access:
- `role_permissions`: control what models are allowed for each role.
- `role`: the LiteLLM role to control access for. Allowed roles = ["internal_user", "proxy_admin", "team"]
- `models`: list of models that the role is allowed to access.
- `model_list`: parent list of models on the proxy. [Learn more](./configs.md#llm-configs-model_list)
3. Model Checks: The proxy will run validation checks on the received JWT. [Code](https://github.com/BerriAI/litellm/blob/3a4f5b23b5025b87b6d969f2485cc9bc741f9ba6/litellm/proxy/auth/user_api_key_auth.py#L284)
@@ -344,3 +344,6 @@ curl -i http://localhost:4000/v1/chat/completions \
</TabItem>
</Tabs>
## [Role Based Access Control (RBAC)](./jwt_auth_arch)
+19 -1
View File
@@ -1,7 +1,7 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# JWT-based Auth
# SSO - JWT-based Auth
Use JWT's to auth admins / projects into the proxy.
@@ -183,6 +183,24 @@ Expected Scope in JWT:
}
```
### Control Model Access
```yaml
general_settings:
enable_jwt_auth: True
litellm_jwtauth:
user_roles_jwt_field: "resource_access.litellm-test-client-id.roles"
user_allowed_roles: ["basic_user"] # roles that map to an 'internal_user' role on LiteLLM
enforce_rbac: true # if true, will check if the user has the correct role to access the model + endpoint
role_permissions: # control what models + endpointsare allowed for each role
- role: internal_user
models: ["anthropic-claude"]
```
**[Architecture Diagram (Control Model Access)](./jwt_auth_arch)**
## Advanced - Allowed Routes
Configure which routes a JWT can access via the config.
Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

+1 -1
View File
@@ -51,7 +51,7 @@ const sidebars = {
{
type: "category",
label: "Architecture",
items: ["proxy/architecture", "proxy/db_info", "router_architecture", "proxy/user_management_heirarchy"],
items: ["proxy/architecture", "proxy/db_info", "router_architecture", "proxy/user_management_heirarchy", "proxy/jwt_auth_arch"],
},
{
type: "link",