mcp-proxy-adapter 6.3.3__py3-none-any.whl → 6.3.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_proxy_adapter/__init__.py +9 -5
- mcp_proxy_adapter/__main__.py +1 -1
- mcp_proxy_adapter/api/app.py +227 -176
- mcp_proxy_adapter/api/handlers.py +68 -60
- mcp_proxy_adapter/api/middleware/__init__.py +7 -5
- mcp_proxy_adapter/api/middleware/base.py +19 -16
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
- mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
- mcp_proxy_adapter/api/middleware/factory.py +50 -52
- mcp_proxy_adapter/api/middleware/logging.py +46 -30
- mcp_proxy_adapter/api/middleware/performance.py +19 -16
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
- mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
- mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
- mcp_proxy_adapter/api/schemas.py +69 -43
- mcp_proxy_adapter/api/tool_integration.py +83 -63
- mcp_proxy_adapter/api/tools.py +60 -50
- mcp_proxy_adapter/commands/__init__.py +15 -6
- mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
- mcp_proxy_adapter/commands/base.py +108 -112
- mcp_proxy_adapter/commands/builtin_commands.py +28 -18
- mcp_proxy_adapter/commands/catalog_manager.py +394 -265
- mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
- mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
- mcp_proxy_adapter/commands/command_registry.py +275 -226
- mcp_proxy_adapter/commands/config_command.py +48 -33
- mcp_proxy_adapter/commands/dependency_container.py +22 -23
- mcp_proxy_adapter/commands/dependency_manager.py +65 -56
- mcp_proxy_adapter/commands/echo_command.py +15 -15
- mcp_proxy_adapter/commands/health_command.py +31 -29
- mcp_proxy_adapter/commands/help_command.py +97 -61
- mcp_proxy_adapter/commands/hooks.py +65 -49
- mcp_proxy_adapter/commands/key_management_command.py +148 -147
- mcp_proxy_adapter/commands/load_command.py +58 -40
- mcp_proxy_adapter/commands/plugins_command.py +80 -54
- mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
- mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
- mcp_proxy_adapter/commands/reload_command.py +43 -37
- mcp_proxy_adapter/commands/result.py +26 -33
- mcp_proxy_adapter/commands/role_test_command.py +26 -26
- mcp_proxy_adapter/commands/roles_management_command.py +176 -173
- mcp_proxy_adapter/commands/security_command.py +134 -122
- mcp_proxy_adapter/commands/settings_command.py +47 -56
- mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
- mcp_proxy_adapter/commands/token_management_command.py +129 -158
- mcp_proxy_adapter/commands/transport_management_command.py +41 -36
- mcp_proxy_adapter/commands/unload_command.py +42 -37
- mcp_proxy_adapter/config.py +36 -35
- mcp_proxy_adapter/core/__init__.py +19 -21
- mcp_proxy_adapter/core/app_factory.py +30 -9
- mcp_proxy_adapter/core/app_runner.py +81 -64
- mcp_proxy_adapter/core/auth_validator.py +176 -182
- mcp_proxy_adapter/core/certificate_utils.py +469 -426
- mcp_proxy_adapter/core/client.py +155 -126
- mcp_proxy_adapter/core/client_manager.py +60 -54
- mcp_proxy_adapter/core/client_security.py +108 -88
- mcp_proxy_adapter/core/config_converter.py +176 -143
- mcp_proxy_adapter/core/config_validator.py +12 -4
- mcp_proxy_adapter/core/crl_utils.py +21 -7
- mcp_proxy_adapter/core/errors.py +64 -20
- mcp_proxy_adapter/core/logging.py +34 -29
- mcp_proxy_adapter/core/mtls_asgi.py +29 -25
- mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
- mcp_proxy_adapter/core/protocol_manager.py +154 -104
- mcp_proxy_adapter/core/proxy_client.py +202 -144
- mcp_proxy_adapter/core/proxy_registration.py +12 -2
- mcp_proxy_adapter/core/role_utils.py +139 -125
- mcp_proxy_adapter/core/security_adapter.py +88 -77
- mcp_proxy_adapter/core/security_factory.py +50 -44
- mcp_proxy_adapter/core/security_integration.py +72 -24
- mcp_proxy_adapter/core/server_adapter.py +68 -64
- mcp_proxy_adapter/core/server_engine.py +71 -53
- mcp_proxy_adapter/core/settings.py +68 -58
- mcp_proxy_adapter/core/ssl_utils.py +69 -56
- mcp_proxy_adapter/core/transport_manager.py +72 -60
- mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
- mcp_proxy_adapter/core/utils.py +4 -2
- mcp_proxy_adapter/custom_openapi.py +107 -99
- mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/commands/__init__.py +1 -1
- mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
- mcp_proxy_adapter/examples/debug_request_state.py +38 -19
- mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
- mcp_proxy_adapter/examples/demo_client.py +48 -36
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
- mcp_proxy_adapter/examples/generate_certificates.py +31 -16
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
- mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
- mcp_proxy_adapter/examples/run_example.py +23 -5
- mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
- mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
- mcp_proxy_adapter/examples/run_security_tests.py +103 -41
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
- mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/security_test_client.py +196 -127
- mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
- mcp_proxy_adapter/examples/test_config.py +19 -4
- mcp_proxy_adapter/examples/test_config_generator.py +23 -7
- mcp_proxy_adapter/examples/test_examples.py +84 -56
- mcp_proxy_adapter/examples/universal_client.py +119 -62
- mcp_proxy_adapter/openapi.py +108 -115
- mcp_proxy_adapter/utils/config_generator.py +429 -274
- mcp_proxy_adapter/version.py +1 -2
- {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
- mcp_proxy_adapter-6.3.3.dist-info/RECORD +0 -143
- {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
- {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -16,9 +16,12 @@ from starlette.middleware.base import BaseHTTPMiddleware
|
|
16
16
|
|
17
17
|
# Direct import from framework
|
18
18
|
try:
|
19
|
-
from mcp_security_framework.middleware.fastapi_middleware import
|
19
|
+
from mcp_security_framework.middleware.fastapi_middleware import (
|
20
|
+
FastAPISecurityMiddleware,
|
21
|
+
)
|
20
22
|
from mcp_security_framework import SecurityManager
|
21
23
|
from mcp_security_framework.schemas.config import SecurityConfig
|
24
|
+
|
22
25
|
SECURITY_FRAMEWORK_AVAILABLE = True
|
23
26
|
except ImportError:
|
24
27
|
SECURITY_FRAMEWORK_AVAILABLE = False
|
@@ -32,7 +35,7 @@ from mcp_proxy_adapter.core.security_integration import create_security_integrat
|
|
32
35
|
|
33
36
|
class SecurityValidationError(Exception):
|
34
37
|
"""Security validation error."""
|
35
|
-
|
38
|
+
|
36
39
|
def __init__(self, message: str, error_code: int):
|
37
40
|
self.message = message
|
38
41
|
self.error_code = error_code
|
@@ -42,28 +45,30 @@ class SecurityValidationError(Exception):
|
|
42
45
|
class UnifiedSecurityMiddleware(BaseHTTPMiddleware):
|
43
46
|
"""
|
44
47
|
Unified security middleware using mcp_security_framework.
|
45
|
-
|
48
|
+
|
46
49
|
This middleware now directly uses the security framework's FastAPI middleware
|
47
50
|
and components instead of custom implementations.
|
48
51
|
"""
|
49
|
-
|
52
|
+
|
50
53
|
def __init__(self, app, config: Dict[str, Any]):
|
51
54
|
"""
|
52
55
|
Initialize unified security middleware.
|
53
|
-
|
56
|
+
|
54
57
|
Args:
|
55
58
|
app: FastAPI application
|
56
59
|
config: mcp_proxy_adapter configuration dictionary
|
57
60
|
"""
|
58
61
|
super().__init__(app)
|
59
62
|
self.config = config
|
60
|
-
|
63
|
+
|
61
64
|
# Create security integration
|
62
65
|
try:
|
63
66
|
security_config = config.get("security", {})
|
64
67
|
self.security_integration = create_security_integration(security_config)
|
65
68
|
# Use framework's FastAPI middleware
|
66
|
-
self.framework_middleware =
|
69
|
+
self.framework_middleware = (
|
70
|
+
self.security_integration.security_manager.create_fastapi_middleware()
|
71
|
+
)
|
67
72
|
logger.info("Using mcp_security_framework FastAPI middleware")
|
68
73
|
# IMPORTANT: Don't replace self.app! This breaks the middleware chain.
|
69
74
|
# Instead, store the framework middleware for use in dispatch method.
|
@@ -71,31 +76,39 @@ class UnifiedSecurityMiddleware(BaseHTTPMiddleware):
|
|
71
76
|
except Exception as e:
|
72
77
|
logger.error(f"Security framework integration failed: {e}")
|
73
78
|
# Instead of raising error, log warning and continue without security
|
74
|
-
logger.warning(
|
79
|
+
logger.warning(
|
80
|
+
"Continuing without security framework - some security features will be disabled"
|
81
|
+
)
|
75
82
|
self.security_integration = None
|
76
83
|
self.framework_middleware = None
|
77
84
|
# Keep original app in place when framework middleware is unavailable
|
78
85
|
# BaseHTTPMiddleware initialized it via super().__init__(app)
|
79
|
-
|
86
|
+
|
80
87
|
logger.info("Unified security middleware initialized")
|
81
|
-
|
82
|
-
async def dispatch(
|
88
|
+
|
89
|
+
async def dispatch(
|
90
|
+
self, request: Request, call_next: Callable[[Request], Awaitable[Response]]
|
91
|
+
) -> Response:
|
83
92
|
"""
|
84
93
|
Process request using framework middleware.
|
85
|
-
|
94
|
+
|
86
95
|
Args:
|
87
96
|
request: Request object
|
88
97
|
call_next: Next handler
|
89
|
-
|
98
|
+
|
90
99
|
Returns:
|
91
100
|
Response object
|
92
101
|
"""
|
93
102
|
try:
|
94
103
|
# Simple built-in API key enforcement if configured
|
95
|
-
security_cfg =
|
104
|
+
security_cfg = (
|
105
|
+
self.config.get("security", {}) if isinstance(self.config, dict) else {}
|
106
|
+
)
|
96
107
|
auth_cfg = security_cfg.get("auth", {})
|
97
108
|
permissions_cfg = security_cfg.get("permissions", {})
|
98
|
-
public_paths = set(
|
109
|
+
public_paths = set(
|
110
|
+
auth_cfg.get("public_paths", ["/health", "/docs", "/openapi.json"])
|
111
|
+
)
|
99
112
|
# JSON-RPC endpoint must not be public when API key is required
|
100
113
|
public_paths.discard("/api/jsonrpc")
|
101
114
|
path = request.url.path
|
@@ -103,7 +116,11 @@ class UnifiedSecurityMiddleware(BaseHTTPMiddleware):
|
|
103
116
|
api_keys: Dict[str, str] = auth_cfg.get("api_keys", {}) or {}
|
104
117
|
|
105
118
|
# Enforce only for non-public paths when api_key method configured
|
106
|
-
if
|
119
|
+
if (
|
120
|
+
security_cfg.get("enabled", False)
|
121
|
+
and ("api_key" in methods)
|
122
|
+
and (path not in public_paths)
|
123
|
+
):
|
107
124
|
# Accept either X-API-Key or Authorization: Bearer
|
108
125
|
token = request.headers.get("X-API-Key")
|
109
126
|
if not token:
|
@@ -112,19 +129,25 @@ class UnifiedSecurityMiddleware(BaseHTTPMiddleware):
|
|
112
129
|
token = authz[7:]
|
113
130
|
if not token or (api_keys and token not in api_keys):
|
114
131
|
from fastapi.responses import JSONResponse
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
"
|
120
|
-
|
121
|
-
|
132
|
+
|
133
|
+
return JSONResponse(
|
134
|
+
status_code=401,
|
135
|
+
content={
|
136
|
+
"error": {
|
137
|
+
"code": 401,
|
138
|
+
"message": "Unauthorized: invalid or missing API key",
|
139
|
+
"type": "authentication_error",
|
140
|
+
}
|
141
|
+
},
|
142
|
+
)
|
122
143
|
|
123
144
|
# Continue with framework middleware or regular flow
|
124
145
|
if self.framework_middleware:
|
125
146
|
# If framework middleware exists, we need to call it manually
|
126
147
|
# This is a workaround since we can't chain ASGI apps in BaseHTTPMiddleware
|
127
|
-
logger.debug(
|
148
|
+
logger.debug(
|
149
|
+
"Framework middleware exists, continuing with regular call_next"
|
150
|
+
)
|
128
151
|
return await call_next(request)
|
129
152
|
else:
|
130
153
|
# No framework middleware, continue normally
|
@@ -137,61 +160,57 @@ class UnifiedSecurityMiddleware(BaseHTTPMiddleware):
|
|
137
160
|
# Handle other errors
|
138
161
|
logger.error(f"Unexpected error in unified security middleware: {e}")
|
139
162
|
return await self._handle_general_error(request, e)
|
140
|
-
|
141
163
|
|
142
|
-
|
143
|
-
|
164
|
+
async def _handle_security_error(
|
165
|
+
self, request: Request, error: SecurityValidationError
|
166
|
+
) -> Response:
|
144
167
|
"""
|
145
168
|
Handle security validation errors.
|
146
|
-
|
169
|
+
|
147
170
|
Args:
|
148
171
|
request: Request object
|
149
172
|
error: Security validation error
|
150
|
-
|
173
|
+
|
151
174
|
Returns:
|
152
175
|
Error response
|
153
176
|
"""
|
154
177
|
from fastapi.responses import JSONResponse
|
155
|
-
|
178
|
+
|
156
179
|
error_response = {
|
157
180
|
"error": {
|
158
181
|
"code": error.error_code,
|
159
182
|
"message": error.message,
|
160
|
-
"type": "security_validation_error"
|
183
|
+
"type": "security_validation_error",
|
161
184
|
}
|
162
185
|
}
|
163
|
-
|
186
|
+
|
164
187
|
logger.warning(f"Security validation failed: {error.message}")
|
165
|
-
|
166
|
-
return JSONResponse(
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
async def _handle_general_error(self, request: Request, error: Exception) -> Response:
|
188
|
+
|
189
|
+
return JSONResponse(status_code=error.error_code, content=error_response)
|
190
|
+
|
191
|
+
async def _handle_general_error(
|
192
|
+
self, request: Request, error: Exception
|
193
|
+
) -> Response:
|
172
194
|
"""
|
173
195
|
Handle general errors.
|
174
|
-
|
196
|
+
|
175
197
|
Args:
|
176
198
|
request: Request object
|
177
199
|
error: General error
|
178
|
-
|
200
|
+
|
179
201
|
Returns:
|
180
202
|
Error response
|
181
203
|
"""
|
182
204
|
from fastapi.responses import JSONResponse
|
183
|
-
|
205
|
+
|
184
206
|
error_response = {
|
185
|
-
|
207
|
+
"error": {
|
186
208
|
"code": 500,
|
187
|
-
|
188
|
-
"type": "general_error"
|
209
|
+
"message": "Internal server error",
|
210
|
+
"type": "general_error",
|
189
211
|
}
|
190
212
|
}
|
191
|
-
|
213
|
+
|
192
214
|
logger.error(f"General error in security middleware: {error}")
|
193
|
-
|
194
|
-
return JSONResponse(
|
195
|
-
status_code=500,
|
196
|
-
content=error_response
|
197
|
-
)
|
215
|
+
|
216
|
+
return JSONResponse(status_code=500, content=error_response)
|
@@ -17,15 +17,13 @@ from mcp_proxy_adapter.core.logging import logger
|
|
17
17
|
# Import mcp_security_framework components
|
18
18
|
try:
|
19
19
|
from mcp_security_framework import AuthManager, PermissionManager
|
20
|
-
from mcp_security_framework.schemas.config import
|
21
|
-
|
22
|
-
)
|
20
|
+
from mcp_security_framework.schemas.config import AuthConfig, PermissionConfig
|
21
|
+
|
23
22
|
_MCP_SECURITY_AVAILABLE = True
|
24
23
|
print("✅ mcp_security_framework available in middleware")
|
25
24
|
except ImportError:
|
26
25
|
_MCP_SECURITY_AVAILABLE = False
|
27
|
-
print("⚠️ mcp_security_framework not available in middleware, "
|
28
|
-
"using basic auth")
|
26
|
+
print("⚠️ mcp_security_framework not available in middleware, " "using basic auth")
|
29
27
|
|
30
28
|
|
31
29
|
class UserInfoMiddleware(BaseHTTPMiddleware):
|
@@ -35,6 +33,7 @@ class UserInfoMiddleware(BaseHTTPMiddleware):
|
|
35
33
|
This middleware extracts user information from authentication headers
|
36
34
|
and sets it in request.state for use by commands.
|
37
35
|
"""
|
36
|
+
|
38
37
|
def __init__(self, app, config: Dict[str, Any]):
|
39
38
|
"""
|
40
39
|
Initialize user info middleware.
|
@@ -59,12 +58,12 @@ class UserInfoMiddleware(BaseHTTPMiddleware):
|
|
59
58
|
|
60
59
|
# Check if permissions are enabled
|
61
60
|
permissions_enabled = permissions_config.get("enabled", False)
|
62
|
-
|
61
|
+
|
63
62
|
# Create AuthConfig for mcp_security_framework
|
64
63
|
mcp_auth_config = AuthConfig(
|
65
64
|
enabled=True,
|
66
65
|
methods=["api_key"],
|
67
|
-
api_keys=auth_config.get("api_keys", {})
|
66
|
+
api_keys=auth_config.get("api_keys", {}),
|
68
67
|
)
|
69
68
|
|
70
69
|
# Initialize PermissionManager only if permissions are enabled
|
@@ -85,7 +84,7 @@ class UserInfoMiddleware(BaseHTTPMiddleware):
|
|
85
84
|
"wildcard_permissions", False
|
86
85
|
),
|
87
86
|
strict_mode=permissions_config.get("strict_mode", True),
|
88
|
-
roles=permissions_config.get("roles", {})
|
87
|
+
roles=permissions_config.get("roles", {}),
|
89
88
|
)
|
90
89
|
|
91
90
|
# Initialize PermissionManager first
|
@@ -101,7 +100,7 @@ class UserInfoMiddleware(BaseHTTPMiddleware):
|
|
101
100
|
permission_cache_ttl=300,
|
102
101
|
wildcard_permissions=False,
|
103
102
|
strict_mode=False,
|
104
|
-
roles={}
|
103
|
+
roles={},
|
105
104
|
)
|
106
105
|
self.permission_manager = PermissionManager(mcp_permission_config)
|
107
106
|
|
@@ -109,8 +108,9 @@ class UserInfoMiddleware(BaseHTTPMiddleware):
|
|
109
108
|
self.auth_manager = AuthManager(
|
110
109
|
mcp_auth_config, self.permission_manager
|
111
110
|
)
|
112
|
-
logger.info(
|
113
|
-
|
111
|
+
logger.info(
|
112
|
+
"✅ User info middleware initialized with " "mcp_security_framework"
|
113
|
+
)
|
114
114
|
except Exception as e:
|
115
115
|
logger.warning(f"⚠️ Failed to initialize AuthManager: {e}")
|
116
116
|
self._security_available = False
|
@@ -123,8 +123,7 @@ class UserInfoMiddleware(BaseHTTPMiddleware):
|
|
123
123
|
logger.info("ℹ️ User info middleware initialized with basic auth")
|
124
124
|
|
125
125
|
async def dispatch(
|
126
|
-
self, request: Request,
|
127
|
-
call_next: Callable[[Request], Awaitable[Response]]
|
126
|
+
self, request: Request, call_next: Callable[[Request], Awaitable[Response]]
|
128
127
|
) -> Response:
|
129
128
|
"""
|
130
129
|
Process request and set user info in request.state.
|
@@ -148,41 +147,49 @@ class UserInfoMiddleware(BaseHTTPMiddleware):
|
|
148
147
|
# Set user info from AuthManager result
|
149
148
|
request.state.user = {
|
150
149
|
"id": api_key,
|
151
|
-
"role": (
|
152
|
-
|
150
|
+
"role": (
|
151
|
+
auth_result.roles[0] if auth_result.roles else "guest"
|
152
|
+
),
|
153
153
|
"roles": auth_result.roles or ["guest"],
|
154
154
|
"permissions": getattr(
|
155
|
-
auth_result,
|
156
|
-
)
|
155
|
+
auth_result, "permissions", ["read"]
|
156
|
+
),
|
157
157
|
}
|
158
|
-
logger.debug(
|
159
|
-
|
160
|
-
|
158
|
+
logger.debug(
|
159
|
+
f"✅ Authenticated user with "
|
160
|
+
f"mcp_security_framework: "
|
161
|
+
f"{request.state.user}"
|
162
|
+
)
|
161
163
|
else:
|
162
164
|
# Authentication failed
|
163
165
|
request.state.user = {
|
164
166
|
"id": None,
|
165
167
|
"role": "guest",
|
166
168
|
"roles": ["guest"],
|
167
|
-
"permissions": ["read"]
|
169
|
+
"permissions": ["read"],
|
168
170
|
}
|
169
|
-
logger.debug(
|
170
|
-
|
171
|
+
logger.debug(
|
172
|
+
f"❌ Authentication failed for API key: "
|
173
|
+
f"{api_key[:8]}..."
|
174
|
+
)
|
171
175
|
except Exception as e:
|
172
|
-
logger.warning(
|
173
|
-
|
176
|
+
logger.warning(
|
177
|
+
f"⚠️ AuthManager error: {e}, " f"falling back to basic auth"
|
178
|
+
)
|
174
179
|
self._security_available = False
|
175
180
|
|
176
181
|
if not self._security_available:
|
177
182
|
# Fallback to basic API key handling
|
178
|
-
if api_key in getattr(self,
|
183
|
+
if api_key in getattr(self, "api_keys", {}):
|
179
184
|
user_role = self.api_keys[api_key]
|
180
185
|
|
181
186
|
# Get permissions for this role from roles file if available
|
182
187
|
role_permissions = ["read"] # default permissions
|
183
|
-
if (
|
184
|
-
|
185
|
-
|
188
|
+
if (
|
189
|
+
hasattr(self, "roles_config")
|
190
|
+
and self.roles_config
|
191
|
+
and user_role in self.roles_config
|
192
|
+
):
|
186
193
|
role_permissions = self.roles_config[user_role].get(
|
187
194
|
"permissions", ["read"]
|
188
195
|
)
|
@@ -192,18 +199,20 @@ class UserInfoMiddleware(BaseHTTPMiddleware):
|
|
192
199
|
"id": api_key,
|
193
200
|
"role": user_role,
|
194
201
|
"roles": [user_role],
|
195
|
-
"permissions": role_permissions
|
202
|
+
"permissions": role_permissions,
|
196
203
|
}
|
197
204
|
|
198
|
-
logger.debug(
|
199
|
-
|
205
|
+
logger.debug(
|
206
|
+
f"✅ Authenticated user with basic auth: "
|
207
|
+
f"{request.state.user}"
|
208
|
+
)
|
200
209
|
else:
|
201
210
|
# API key not found
|
202
211
|
request.state.user = {
|
203
212
|
"id": None,
|
204
213
|
"role": "guest",
|
205
214
|
"roles": ["guest"],
|
206
|
-
"permissions": ["read"]
|
215
|
+
"permissions": ["read"],
|
207
216
|
}
|
208
217
|
logger.debug(f"❌ API key not found: {api_key[:8]}...")
|
209
218
|
else:
|
@@ -212,7 +221,7 @@ class UserInfoMiddleware(BaseHTTPMiddleware):
|
|
212
221
|
"id": None,
|
213
222
|
"role": "guest",
|
214
223
|
"roles": ["guest"],
|
215
|
-
"permissions": ["read"]
|
224
|
+
"permissions": ["read"],
|
216
225
|
}
|
217
226
|
logger.debug("ℹ️ No API key provided, using guest access")
|
218
227
|
|