Add mcp-gateway/gateway-proxy/gateway_proxy_user_integration.py
This commit is contained in:
parent
af1bb15bdd
commit
c05812853e
1 changed files with 147 additions and 0 deletions
147
mcp-gateway/gateway-proxy/gateway_proxy_user_integration.py
Normal file
147
mcp-gateway/gateway-proxy/gateway_proxy_user_integration.py
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
"""
|
||||
Integration instructions for user management into gateway_proxy.py
|
||||
==================================================================
|
||||
|
||||
STEP 1: Add import at the top of gateway_proxy.py (after line 32):
|
||||
-------------------------------------------------------------------
|
||||
from user_management import user_manager
|
||||
from user_routes import (
|
||||
create_user, list_users, get_user, delete_user, toggle_user,
|
||||
generate_api_key, revoke_api_key, set_mcp_access
|
||||
)
|
||||
|
||||
|
||||
STEP 2: Modify validate_bearer_token() function (around line 254):
|
||||
------------------------------------------------------------------
|
||||
Replace the validate_bearer_token function with:
|
||||
|
||||
def validate_bearer_token(request: Request) -> dict | None:
|
||||
auth_header = request.headers.get("Authorization", "")
|
||||
if not auth_header.startswith("Bearer "):
|
||||
return None
|
||||
token = auth_header[7:]
|
||||
|
||||
# Check static API key first (persistent, survives restarts)
|
||||
if STATIC_API_KEY and token == STATIC_API_KEY:
|
||||
return {"client_id": "static", "scope": "mcp:tools", "user": "static"}
|
||||
|
||||
# Check user API key
|
||||
user_info = user_manager.validate_api_key(token)
|
||||
if user_info:
|
||||
return {
|
||||
"client_id": "api-key",
|
||||
"scope": "mcp:tools",
|
||||
"user": user_info['username'],
|
||||
"user_id": user_info['user_id'],
|
||||
"mcp_allowed": user_info['mcp_allowed'],
|
||||
"mcp_blocked": user_info['mcp_blocked']
|
||||
}
|
||||
|
||||
# Check OAuth token
|
||||
token_hash = _hash(token)
|
||||
info = ACCESS_TOKENS.get(token_hash)
|
||||
if not info:
|
||||
return None
|
||||
if info["expires_at"] < time.time():
|
||||
del ACCESS_TOKENS[token_hash]
|
||||
return None
|
||||
return info
|
||||
|
||||
|
||||
STEP 3: Modify handle_mcp() function to filter by user MCP access:
|
||||
------------------------------------------------------------------
|
||||
In the handle_mcp() function, after getting token info, add:
|
||||
|
||||
# Check MCP access control
|
||||
if token_info and 'user' in token_info:
|
||||
# Check if user can access this backend
|
||||
user = token_info.get('user')
|
||||
mcp_allowed = token_info.get('mcp_allowed', [])
|
||||
mcp_blocked = token_info.get('mcp_blocked', [])
|
||||
|
||||
# Parse which backend is being accessed from params
|
||||
params = body.get('params', {})
|
||||
backend_name = params.get('backend') # Should be set by frontend
|
||||
|
||||
if backend_name:
|
||||
if backend_name in mcp_blocked:
|
||||
return JSONResponse(
|
||||
{'error': 'access_denied', 'message': f'Access to {backend_name} is blocked'},
|
||||
status_code=403
|
||||
)
|
||||
if mcp_allowed and backend_name not in mcp_allowed:
|
||||
return JSONResponse(
|
||||
{'error': 'access_denied', 'message': f'You do not have access to {backend_name}'},
|
||||
status_code=403
|
||||
)
|
||||
|
||||
|
||||
STEP 4: Add new routes before building the routes list (before line 1012):
|
||||
--------------------------------------------------------------------------
|
||||
Add these route definitions right before the routes list:
|
||||
|
||||
# User management routes
|
||||
Route("/users", create_user, methods=["POST"]),
|
||||
Route("/users", list_users, methods=["GET"]),
|
||||
Route("/users/{username}", get_user, methods=["GET"]),
|
||||
Route("/users/{username}", delete_user, methods=["DELETE"]),
|
||||
Route("/users/{username}/enable", toggle_user, methods=["PATCH"]),
|
||||
Route("/users/{username}/keys", generate_api_key, methods=["POST"]),
|
||||
Route("/users/{username}/mcp-access", set_mcp_access, methods=["PUT"]),
|
||||
Route("/keys/revoke", revoke_api_key, methods=["POST"]),
|
||||
|
||||
|
||||
STEP 5: Update the routes list (around line 1012):
|
||||
--------------------------------------------------
|
||||
Insert the user management routes into the routes list:
|
||||
|
||||
routes = [
|
||||
# ... existing routes ...
|
||||
|
||||
# User management (admin endpoints)
|
||||
Route("/users", create_user, methods=["POST"]),
|
||||
Route("/users", list_users, methods=["GET"]),
|
||||
Route("/users/{username}", get_user, methods=["GET"]),
|
||||
Route("/users/{username}", delete_user, methods=["DELETE"]),
|
||||
Route("/users/{username}/enable", toggle_user, methods=["PATCH"]),
|
||||
Route("/users/{username}/keys", generate_api_key, methods=["POST"]),
|
||||
Route("/users/{username}/mcp-access", set_mcp_access, methods=["PUT"]),
|
||||
Route("/keys/revoke", revoke_api_key, methods=["POST"]),
|
||||
|
||||
# ... rest of routes ...
|
||||
]
|
||||
|
||||
|
||||
STEP 6: Update docker-compose.yml volume mounts:
|
||||
-----------------------------------------------
|
||||
Add a data volume to persist user database:
|
||||
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./gateway-proxy:/app
|
||||
|
||||
And in the service, add:
|
||||
|
||||
volumes:
|
||||
- ./data:/data
|
||||
|
||||
|
||||
STEP 7: Optional - Create initial admin user during startup:
|
||||
----------------------------------------------------------
|
||||
In the startup() function, add:
|
||||
|
||||
async def startup():
|
||||
# Initialize admin user if not exists
|
||||
try:
|
||||
users = user_manager.list_users()
|
||||
if not any(u['username'] == 'admin' for u in users):
|
||||
user_manager.create_user('admin', email='admin@localhost', description='Administrator')
|
||||
admin_key = user_manager.generate_api_key('admin', key_name='initial-setup')
|
||||
logger.info(f"Created admin user. Initial API key: {admin_key}")
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not initialize admin user: {e}")
|
||||
|
||||
# ... rest of startup ...
|
||||
"""
|
||||
|
||||
print(__doc__)
|
||||
Loading…
Reference in a new issue