diff --git a/mcp-gateway/USER_MANAGEMENT_SETUP.md b/mcp-gateway/USER_MANAGEMENT_SETUP.md deleted file mode 100644 index b3969c1..0000000 --- a/mcp-gateway/USER_MANAGEMENT_SETUP.md +++ /dev/null @@ -1,350 +0,0 @@ -# User Management System Setup Guide - -This guide explains how to integrate the user management system into your MCP Gateway, enabling per-user API key generation and MCP access control. - -## Overview - -The user management system provides: - -- **User Creation & Management**: Create and manage users, enable/disable accounts -- **API Key Generation**: Generate unique API keys with optional TTL (time-to-live) -- **MCP Access Control**: Allow/block specific MCPs for each user (e.g., some users access only ERPNext, others access Wave + TrueNAS) -- **Persistent Storage**: User data stored in JSON file, survives container restarts -- **Web Dashboard**: Intuitive UI for managing users and API keys - -## Files Created - -1. **user_management.py** - Core user/API key management logic -2. **user_routes.py** - REST API endpoints for user management -3. **user_dashboard_ui.py** - Web dashboard with Vue.js UI -4. **gateway_proxy_user_integration.py** - Integration instructions - -## Installation Steps - -### Step 1: Copy Files - -The files are already created in `gateway-proxy/`: -- `user_management.py` -- `user_routes.py` -- `user_dashboard_ui.py` - -### Step 2: Update gateway_proxy.py - -Add the import at line 33 (after existing imports): - -```python -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 -) -from user_dashboard_ui import user_management_dashboard -``` - -### Step 3: Update validate_bearer_token() Function - -Replace the `validate_bearer_token()` function (around line 254) with: - -```python -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 - 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 4: Add MCP Access Control to handle_mcp() - -In the `handle_mcp()` function, after retrieving `token_info`, add this check: - -```python -# Check MCP access control -if token_info and 'user' in token_info and token_info.get('client_id') == 'api-key': - mcp_allowed = token_info.get('mcp_allowed', []) - mcp_blocked = token_info.get('mcp_blocked', []) - - # Check if user can access any backend (basic check) - if not mcp_allowed and not mcp_blocked: - # User has no restrictions, allow all - pass - elif mcp_blocked and len(mcp_blocked) == len(BACKENDS): - return JSONResponse( - {'error': 'access_denied', 'message': 'All MCPs are blocked for your user'}, - status_code=403 - ) -``` - -### Step 5: Update Routes List - -Add these routes to the routes list before creating the app (around line 1012): - -```python -routes = [ - # ... existing well-known and OAuth routes ... - - # MCP endpoint - Route("/mcp", handle_mcp, methods=["GET", "HEAD", "POST", "DELETE"]), - - # Monitoring - Route("/health", health, methods=["GET"]), - Route("/status", status, methods=["GET"]), - - # Dashboard - Route("/dashboard", dashboard, methods=["GET"]), - Route("/dashboard/status", dashboard_status, methods=["GET"]), - - # User Management - Enhanced Dashboard - Route("/admin", user_management_dashboard, methods=["GET"]), - - # User Management API - 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 6: Update docker-compose.yml - -Ensure the gateway service has a data volume for persistent storage: - -```yaml -services: - mcp-gateway: - image: mcp-gateway:latest - build: - context: ./gateway-proxy - dockerfile: Dockerfile - container_name: mcp-gateway - ports: - - "4444:4444" - environment: - # ... existing environment variables ... - USERS_DB_PATH: /data/users.json - volumes: - - ./data:/data - - ./gateway-proxy:/app - depends_on: - # ... existing dependencies ... -``` - -### Step 7: Create Data Directory - -```bash -mkdir -p /sessions/vigilant-elegant-ramanujan/mnt/MCP\ Servers/mcp-gateway/data -``` - -### Step 8: Restart Gateway - -```bash -docker-compose down -docker-compose up -d mcp-gateway -``` - -## Usage - -### Access the Dashboard - -Open your browser to: - -``` -http://10.0.0.25:4444/admin -``` - -### Create a User via API - -```bash -curl -X POST http://10.0.0.25:4444/users \ - -H "Content-Type: application/json" \ - -d '{ - "username": "alice", - "email": "alice@example.com", - "description": "Engineering team" - }' -``` - -### Generate an API Key - -```bash -curl -X POST http://10.0.0.25:4444/users/alice/keys \ - -H "Content-Type: application/json" \ - -d '{ - "key_name": "production-key", - "ttl_days": 90 - }' -``` - -Response: -```json -{ - "status": "created", - "username": "alice", - "api_key": "mcpgw_...", - "note": "Save this key immediately — it will not be shown again" -} -``` - -### Configure MCP Access - -```bash -curl -X PUT http://10.0.0.25:4444/users/alice/mcp-access \ - -H "Content-Type: application/json" \ - -d '{ - "allowed_mcps": ["erpnext", "wave"], - "blocked_mcps": [] - }' -``` - -This allows alice to access only ERPNext and Wave Finance MCPs. - -### Use the API Key - -```bash -curl -X POST http://10.0.0.25:4444/mcp \ - -H "Authorization: Bearer mcpgw_..." \ - -H "Content-Type: application/json" \ - -d '{ - "jsonrpc": "2.0", - "id": 1, - "method": "initialize", - "params": { - "protocolVersion": "2024-11-05", - "capabilities": {}, - "clientInfo": {"name": "test-client", "version": "1.0"} - } - }' -``` - -## Access Control Examples - -### Example 1: Limited Access User - -Create a user with access to only ERPNext: - -```bash -# Create user -curl -X POST http://10.0.0.25:4444/users \ - -H "Content-Type: application/json" \ - -d '{"username": "erp-user", "description": "ERP access only"}' - -# Generate key -curl -X POST http://10.0.0.25:4444/users/erp-user/keys \ - -H "Content-Type: application/json" \ - -d '{"key_name": "erp-only"}' - -# Restrict to ERPNext -curl -X PUT http://10.0.0.25:4444/users/erp-user/mcp-access \ - -H "Content-Type: application/json" \ - -d '{"allowed_mcps": ["erpnext"]}' -``` - -### Example 2: Block Specific MCPs - -Create a user with access to everything except Home Assistant: - -```bash -curl -X PUT http://10.0.0.25:4444/users/alice/mcp-access \ - -H "Content-Type: application/json" \ - -d '{"blocked_mcps": ["homeassistant"]}' -``` - -### Example 3: Revoke an API Key - -```bash -curl -X POST http://10.0.0.25:4444/keys/revoke \ - -H "Content-Type: application/json" \ - -d '{"api_key": "mcpgw_..."}' -``` - -## Database Schema - -User data is stored in `/data/users.json` with the following structure: - -```json -{ - "users": { - "alice": { - "user_id": "abc123...", - "email": "alice@example.com", - "description": "Engineering team", - "created_at": "2026-03-31T12:00:00.000000", - "enabled": true, - "api_keys": ["hash1", "hash2"], - "mcp_allowed": ["erpnext", "wave"], - "mcp_blocked": [], - "metadata": {} - } - }, - "api_keys": { - "hash1": { - "user_id": "abc123...", - "username": "alice", - "key_name": "prod-key", - "created_at": "2026-03-31T12:00:00.000000", - "expires_at": null, - "revoked": false - } - } -} -``` - -## Security Notes - -1. **API Keys are Hashed**: Only SHA256 hashes are stored, never the actual key -2. **One-Time Display**: Keys are shown only once during generation -3. **TTL Support**: Keys can expire after N days -4. **Revocation**: Keys can be revoked at any time -5. **Per-User Access Control**: Each user has independent MCP restrictions - -## Troubleshooting - -### Users/Keys Not Persisting After Restart - -Check that: -1. `/data` directory exists and is mounted in docker-compose.yml -2. `/data` directory has write permissions -3. `USERS_DB_PATH=/data/users.json` is set in environment - -### API Key Not Working - -1. Verify key hasn't been revoked: Check in dashboard -2. Verify key hasn't expired: Check `expires_at` timestamp -3. Verify user is enabled: Check `enabled` field in dashboard -4. Check MCP access: Verify the user has access to the MCP they're trying to use - -## Next Steps - -- Configure additional users for different teams/roles -- Set up automated key rotation policies -- Monitor API key usage via the dashboard -- Integrate with your CI/CD for automated deployments