mcp-proxy-adapter 6.9.17__py3-none-any.whl → 6.9.19__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/api/app.py +52 -52
- mcp_proxy_adapter/api/handlers.py +5 -5
- mcp_proxy_adapter/api/middleware/__init__.py +8 -8
- mcp_proxy_adapter/api/middleware/base.py +14 -14
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +7 -7
- mcp_proxy_adapter/api/middleware/error_handling.py +9 -9
- mcp_proxy_adapter/api/middleware/factory.py +17 -17
- mcp_proxy_adapter/api/middleware/logging.py +6 -6
- mcp_proxy_adapter/api/middleware/performance.py +3 -3
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +19 -19
- mcp_proxy_adapter/api/middleware/transport_middleware.py +3 -3
- mcp_proxy_adapter/api/middleware/unified_security.py +11 -11
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +21 -21
- mcp_proxy_adapter/api/tool_integration.py +3 -2
- mcp_proxy_adapter/api/tools.py +4 -3
- mcp_proxy_adapter/commands/auth_validation_command.py +6 -5
- mcp_proxy_adapter/commands/base.py +10 -10
- mcp_proxy_adapter/commands/builtin_commands.py +6 -6
- mcp_proxy_adapter/commands/catalog_manager.py +74 -74
- mcp_proxy_adapter/commands/cert_monitor_command.py +13 -12
- mcp_proxy_adapter/commands/certificate_management_command.py +20 -19
- mcp_proxy_adapter/commands/command_registry.py +68 -67
- mcp_proxy_adapter/commands/config_command.py +3 -1
- mcp_proxy_adapter/commands/dependency_manager.py +10 -10
- mcp_proxy_adapter/commands/help_command.py +21 -20
- mcp_proxy_adapter/commands/hooks.py +27 -27
- mcp_proxy_adapter/commands/key_management_command.py +19 -18
- mcp_proxy_adapter/commands/plugins_command.py +2 -1
- mcp_proxy_adapter/commands/protocol_management_command.py +6 -6
- mcp_proxy_adapter/commands/proxy_registration_command.py +9 -9
- mcp_proxy_adapter/commands/registration_status_command.py +4 -4
- mcp_proxy_adapter/commands/reload_command.py +5 -5
- mcp_proxy_adapter/commands/role_test_command.py +2 -1
- mcp_proxy_adapter/commands/roles_management_command.py +9 -8
- mcp_proxy_adapter/commands/security_command.py +3 -2
- mcp_proxy_adapter/commands/ssl_setup_command.py +7 -6
- mcp_proxy_adapter/commands/token_management_command.py +12 -11
- mcp_proxy_adapter/commands/transport_management_command.py +2 -2
- mcp_proxy_adapter/config.py +3 -3
- mcp_proxy_adapter/core/__init__.py +1 -1
- mcp_proxy_adapter/core/app_runner.py +3 -3
- mcp_proxy_adapter/core/auth_validator.py +9 -9
- mcp_proxy_adapter/core/certificate_utils.py +27 -27
- mcp_proxy_adapter/core/client_manager.py +13 -13
- mcp_proxy_adapter/core/client_security.py +26 -26
- mcp_proxy_adapter/core/config_converter.py +18 -18
- mcp_proxy_adapter/core/config_validator.py +5 -1
- mcp_proxy_adapter/core/crl_utils.py +22 -22
- mcp_proxy_adapter/core/logging.py +21 -13
- mcp_proxy_adapter/core/mtls_asgi.py +7 -7
- mcp_proxy_adapter/core/mtls_asgi_app.py +9 -9
- mcp_proxy_adapter/core/mtls_proxy.py +9 -9
- mcp_proxy_adapter/core/mtls_server.py +18 -18
- mcp_proxy_adapter/core/protocol_manager.py +29 -29
- mcp_proxy_adapter/core/proxy_registration.py +67 -67
- mcp_proxy_adapter/core/security_adapter.py +18 -18
- mcp_proxy_adapter/core/security_factory.py +16 -16
- mcp_proxy_adapter/core/security_integration.py +6 -6
- mcp_proxy_adapter/core/server_adapter.py +12 -12
- mcp_proxy_adapter/core/server_engine.py +17 -17
- mcp_proxy_adapter/core/signal_handler.py +12 -12
- mcp_proxy_adapter/core/ssl_utils.py +12 -12
- mcp_proxy_adapter/core/transport_manager.py +14 -14
- mcp_proxy_adapter/core/unified_config_adapter.py +6 -6
- mcp_proxy_adapter/core/utils.py +5 -5
- mcp_proxy_adapter/custom_openapi.py +7 -7
- mcp_proxy_adapter/examples/cert_manager_bugfix.py +2 -2
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +6 -5
- mcp_proxy_adapter/examples/full_application/commands/echo_command.py +44 -0
- mcp_proxy_adapter/examples/full_application/commands/help_command.py +66 -0
- mcp_proxy_adapter/examples/full_application/commands/list_command.py +64 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +21 -21
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +6 -6
- mcp_proxy_adapter/examples/full_application/main.py +28 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +38 -38
- mcp_proxy_adapter/examples/test_framework_complete.py +35 -35
- mcp_proxy_adapter/examples/test_mcp_server.py +2 -2
- mcp_proxy_adapter/examples/validate_generator_compatibility.py +386 -0
- mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +248 -0
- mcp_proxy_adapter/main.py +3 -0
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.9.19.dist-info/RECORD +149 -0
- mcp_proxy_adapter-6.9.17.dist-info/RECORD +0 -144
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.19.dist-info}/top_level.txt +0 -0
@@ -70,7 +70,7 @@ class CRLManager:
|
|
70
70
|
# Setup HTTP session with retry strategy
|
71
71
|
self._setup_http_session()
|
72
72
|
|
73
|
-
|
73
|
+
get_global_logger().info(
|
74
74
|
f"CRL Manager initialized - enabled: {self.crl_enabled}, certificates_enabled: {certificates_enabled}"
|
75
75
|
)
|
76
76
|
|
@@ -105,7 +105,7 @@ class CRLManager:
|
|
105
105
|
requests.RequestException: If CRL download fails
|
106
106
|
"""
|
107
107
|
if not self.crl_enabled:
|
108
|
-
|
108
|
+
get_global_logger().debug("CRL is disabled, skipping CRL check")
|
109
109
|
return None
|
110
110
|
|
111
111
|
# Check if CRL URL is configured
|
@@ -136,7 +136,7 @@ class CRLManager:
|
|
136
136
|
ValueError: If downloaded data is not valid CRL
|
137
137
|
"""
|
138
138
|
try:
|
139
|
-
|
139
|
+
get_global_logger().info(f"Downloading CRL from URL: {self.crl_url}")
|
140
140
|
|
141
141
|
# Download CRL
|
142
142
|
response = self.session.get(self.crl_url)
|
@@ -148,7 +148,7 @@ class CRLManager:
|
|
148
148
|
"application/pkix-crl" not in content_type
|
149
149
|
and "application/x-pkcs7-crl" not in content_type
|
150
150
|
):
|
151
|
-
|
151
|
+
get_global_logger().warning(f"Unexpected content type for CRL: {content_type}")
|
152
152
|
|
153
153
|
# Save to temporary file
|
154
154
|
with tempfile.NamedTemporaryFile(
|
@@ -161,14 +161,14 @@ class CRLManager:
|
|
161
161
|
if SECURITY_FRAMEWORK_AVAILABLE:
|
162
162
|
try:
|
163
163
|
is_crl_valid(temp_file_path)
|
164
|
-
|
164
|
+
get_global_logger().info(
|
165
165
|
f"CRL downloaded and validated successfully from {self.crl_url}"
|
166
166
|
)
|
167
167
|
except Exception as e:
|
168
168
|
os.unlink(temp_file_path)
|
169
169
|
raise ValueError(f"Downloaded CRL is not valid: {e}")
|
170
170
|
else:
|
171
|
-
|
171
|
+
get_global_logger().warning(
|
172
172
|
"mcp_security_framework not available, skipping CRL validation"
|
173
173
|
)
|
174
174
|
|
@@ -178,10 +178,10 @@ class CRLManager:
|
|
178
178
|
return temp_file_path
|
179
179
|
|
180
180
|
except requests.RequestException as e:
|
181
|
-
|
181
|
+
get_global_logger().error(f"Failed to download CRL from {self.crl_url}: {e}")
|
182
182
|
raise
|
183
183
|
except Exception as e:
|
184
|
-
|
184
|
+
get_global_logger().error(f"CRL download failed: {e}")
|
185
185
|
raise
|
186
186
|
|
187
187
|
def _get_crl_from_file(self) -> str:
|
@@ -202,11 +202,11 @@ class CRLManager:
|
|
202
202
|
if SECURITY_FRAMEWORK_AVAILABLE:
|
203
203
|
try:
|
204
204
|
is_crl_valid(self.crl_path)
|
205
|
-
|
205
|
+
get_global_logger().info(f"CRL file validated successfully: {self.crl_path}")
|
206
206
|
except Exception as e:
|
207
207
|
raise ValueError(f"CRL file is not valid: {e}")
|
208
208
|
else:
|
209
|
-
|
209
|
+
get_global_logger().warning(
|
210
210
|
"mcp_security_framework not available, skipping CRL validation"
|
211
211
|
)
|
212
212
|
|
@@ -230,28 +230,28 @@ class CRLManager:
|
|
230
230
|
return False
|
231
231
|
|
232
232
|
if not SECURITY_FRAMEWORK_AVAILABLE:
|
233
|
-
|
233
|
+
get_global_logger().warning("mcp_security_framework not available, skipping CRL check")
|
234
234
|
return False
|
235
235
|
|
236
236
|
try:
|
237
237
|
crl_data = self.get_crl_data()
|
238
238
|
if not crl_data:
|
239
|
-
|
239
|
+
get_global_logger().warning("CRL is enabled but no CRL data is available")
|
240
240
|
return False
|
241
241
|
|
242
242
|
is_revoked = is_certificate_revoked(cert_path, crl_data)
|
243
243
|
|
244
244
|
if is_revoked:
|
245
|
-
|
245
|
+
get_global_logger().warning(f"Certificate is revoked according to CRL: {cert_path}")
|
246
246
|
else:
|
247
|
-
|
247
|
+
get_global_logger().debug(
|
248
248
|
f"Certificate is not revoked according to CRL: {cert_path}"
|
249
249
|
)
|
250
250
|
|
251
251
|
return is_revoked
|
252
252
|
|
253
253
|
except Exception as e:
|
254
|
-
|
254
|
+
get_global_logger().error(f"CRL check failed for certificate {cert_path}: {e}")
|
255
255
|
# For security, consider certificate invalid if CRL check fails
|
256
256
|
return True
|
257
257
|
|
@@ -278,7 +278,7 @@ class CRLManager:
|
|
278
278
|
}
|
279
279
|
|
280
280
|
if not SECURITY_FRAMEWORK_AVAILABLE:
|
281
|
-
|
281
|
+
get_global_logger().warning(
|
282
282
|
"mcp_security_framework not available, skipping CRL validation"
|
283
283
|
)
|
284
284
|
return {
|
@@ -291,7 +291,7 @@ class CRLManager:
|
|
291
291
|
try:
|
292
292
|
crl_data = self.get_crl_data()
|
293
293
|
if not crl_data:
|
294
|
-
|
294
|
+
get_global_logger().warning("CRL is enabled but no CRL data is available")
|
295
295
|
return {
|
296
296
|
"is_revoked": True, # For security, consider invalid if CRL unavailable
|
297
297
|
"crl_checked": False,
|
@@ -311,7 +311,7 @@ class CRLManager:
|
|
311
311
|
return result
|
312
312
|
|
313
313
|
except Exception as e:
|
314
|
-
|
314
|
+
get_global_logger().error(f"CRL validation failed for certificate {cert_path}: {e}")
|
315
315
|
# For security, consider certificate invalid if CRL validation fails
|
316
316
|
return {
|
317
317
|
"is_revoked": True,
|
@@ -331,7 +331,7 @@ class CRLManager:
|
|
331
331
|
return None
|
332
332
|
|
333
333
|
if not SECURITY_FRAMEWORK_AVAILABLE:
|
334
|
-
|
334
|
+
get_global_logger().warning("mcp_security_framework not available, cannot get CRL info")
|
335
335
|
return None
|
336
336
|
|
337
337
|
try:
|
@@ -342,7 +342,7 @@ class CRLManager:
|
|
342
342
|
return get_crl_info(crl_data)
|
343
343
|
|
344
344
|
except Exception as e:
|
345
|
-
|
345
|
+
get_global_logger().error(f"Failed to get CRL info: {e}")
|
346
346
|
return None
|
347
347
|
|
348
348
|
def cleanup_cache(self):
|
@@ -351,9 +351,9 @@ class CRLManager:
|
|
351
351
|
try:
|
352
352
|
if os.path.exists(temp_path):
|
353
353
|
os.unlink(temp_path)
|
354
|
-
|
354
|
+
get_global_logger().debug(f"Cleaned up temporary CRL file: {temp_path}")
|
355
355
|
except Exception as e:
|
356
|
-
|
356
|
+
get_global_logger().warning(f"Failed to cleanup temporary CRL file {temp_path}: {e}")
|
357
357
|
|
358
358
|
self._crl_cache.clear()
|
359
359
|
|
@@ -60,7 +60,7 @@ class RequestLogger:
|
|
60
60
|
|
61
61
|
def __init__(self, logger_name: str, request_id: Optional[str] = None):
|
62
62
|
"""
|
63
|
-
Initialize request
|
63
|
+
Initialize request get_global_logger().
|
64
64
|
|
65
65
|
Args:
|
66
66
|
logger_name: Logger name.
|
@@ -69,31 +69,31 @@ class RequestLogger:
|
|
69
69
|
self.logger = logging.getLogger(logger_name)
|
70
70
|
self.request_id = request_id or str(uuid.uuid4())
|
71
71
|
self.filter = RequestContextFilter(self.request_id)
|
72
|
-
|
72
|
+
get_global_logger().addFilter(self.filter)
|
73
73
|
|
74
74
|
def debug(self, msg: str, *args, **kwargs):
|
75
75
|
"""Log message with DEBUG level."""
|
76
|
-
|
76
|
+
get_global_logger().debug(f"[{self.request_id}] {msg}", *args, **kwargs)
|
77
77
|
|
78
78
|
def info(self, msg: str, *args, **kwargs):
|
79
79
|
"""Log message with INFO level."""
|
80
|
-
|
80
|
+
get_global_logger().info(f"[{self.request_id}] {msg}", *args, **kwargs)
|
81
81
|
|
82
82
|
def warning(self, msg: str, *args, **kwargs):
|
83
83
|
"""Log message with WARNING level."""
|
84
|
-
|
84
|
+
get_global_logger().warning(f"[{self.request_id}] {msg}", *args, **kwargs)
|
85
85
|
|
86
86
|
def error(self, msg: str, *args, **kwargs):
|
87
87
|
"""Log message with ERROR level."""
|
88
|
-
|
88
|
+
get_global_logger().error(f"[{self.request_id}] {msg}", *args, **kwargs)
|
89
89
|
|
90
90
|
def exception(self, msg: str, *args, **kwargs):
|
91
91
|
"""Log exception with traceback."""
|
92
|
-
|
92
|
+
get_global_logger().exception(f"[{self.request_id}] {msg}", *args, **kwargs)
|
93
93
|
|
94
94
|
def critical(self, msg: str, *args, **kwargs):
|
95
95
|
"""Log message with CRITICAL level."""
|
96
|
-
|
96
|
+
get_global_logger().critical(f"[{self.request_id}] {msg}", *args, **kwargs)
|
97
97
|
|
98
98
|
|
99
99
|
def setup_logging(
|
@@ -118,7 +118,7 @@ def setup_logging(
|
|
118
118
|
rotation_interval: Interval for rotation. By default, taken from configuration.
|
119
119
|
|
120
120
|
Returns:
|
121
|
-
Configured
|
121
|
+
Configured get_global_logger().
|
122
122
|
"""
|
123
123
|
# Use provided parameters or defaults
|
124
124
|
level = level or "INFO"
|
@@ -247,16 +247,24 @@ def _parse_file_size(size_str) -> int:
|
|
247
247
|
|
248
248
|
def get_logger(name: str) -> logging.Logger:
|
249
249
|
"""
|
250
|
-
Get a
|
250
|
+
Get a get_global_logger() with the specified name.
|
251
251
|
|
252
252
|
Args:
|
253
253
|
name: Logger name.
|
254
254
|
|
255
255
|
Returns:
|
256
|
-
Configured
|
256
|
+
Configured get_global_logger() instance.
|
257
257
|
"""
|
258
258
|
return logging.getLogger(name)
|
259
259
|
|
260
260
|
|
261
|
-
# Global
|
262
|
-
|
261
|
+
# Global get_global_logger() for use throughout the application
|
262
|
+
# Initialize lazily to avoid import-time errors
|
263
|
+
logger = None
|
264
|
+
|
265
|
+
def get_global_logger():
|
266
|
+
"""Get the global logger, initializing it if necessary."""
|
267
|
+
global logger
|
268
|
+
if logger is None:
|
269
|
+
logger = setup_logging()
|
270
|
+
return logger
|
@@ -37,7 +37,7 @@ class MTLSASGIApp:
|
|
37
37
|
self.verify_client = ssl_config.get("verify_client", False)
|
38
38
|
self.client_cert_required = ssl_config.get("client_cert_required", False)
|
39
39
|
|
40
|
-
|
40
|
+
get_global_logger().info(
|
41
41
|
f"MTLS ASGI app initialized: verify_client={self.verify_client}, "
|
42
42
|
f"client_cert_required={self.client_cert_required}"
|
43
43
|
)
|
@@ -58,11 +58,11 @@ class MTLSASGIApp:
|
|
58
58
|
if client_cert:
|
59
59
|
# Store certificate in scope for middleware access
|
60
60
|
scope["client_certificate"] = client_cert
|
61
|
-
|
61
|
+
get_global_logger().debug(
|
62
62
|
f"Client certificate extracted: {client_cert.get('subject', {})}"
|
63
63
|
)
|
64
64
|
elif self.client_cert_required:
|
65
|
-
|
65
|
+
get_global_logger().warning("Client certificate required but not provided")
|
66
66
|
# Return 401 Unauthorized
|
67
67
|
await self._send_unauthorized_response(send)
|
68
68
|
return
|
@@ -71,7 +71,7 @@ class MTLSASGIApp:
|
|
71
71
|
await self.app(scope, receive, send)
|
72
72
|
|
73
73
|
except Exception as e:
|
74
|
-
|
74
|
+
get_global_logger().error(f"Error in MTLS ASGI app: {e}")
|
75
75
|
await self._send_error_response(send, str(e))
|
76
76
|
|
77
77
|
def _extract_client_certificate(self, scope: Scope) -> Optional[Dict[str, Any]]:
|
@@ -97,7 +97,7 @@ class MTLSASGIApp:
|
|
97
97
|
return None
|
98
98
|
|
99
99
|
except Exception as e:
|
100
|
-
|
100
|
+
get_global_logger().error(f"Failed to extract client certificate: {e}")
|
101
101
|
return None
|
102
102
|
|
103
103
|
async def _send_unauthorized_response(self, send: Send) -> None:
|
@@ -153,8 +153,8 @@ def create_mtls_asgi_app(app: ASGIApp, ssl_config: Dict[str, Any]) -> ASGIApp:
|
|
153
153
|
MTLS-enabled ASGI application
|
154
154
|
"""
|
155
155
|
if ssl_config.get("mode") == "mtls" or ssl_config.get("verify_client", False):
|
156
|
-
|
156
|
+
get_global_logger().info("Creating MTLS-enabled ASGI application")
|
157
157
|
return MTLSASGIApp(app, ssl_config)
|
158
158
|
else:
|
159
|
-
|
159
|
+
get_global_logger().info("Creating standard ASGI application (no mTLS)")
|
160
160
|
return app
|
@@ -37,7 +37,7 @@ class MTLSASGIApp:
|
|
37
37
|
self.ssl_config = ssl_config
|
38
38
|
self.client_cert_required = ssl_config.get("client_cert_required", True)
|
39
39
|
|
40
|
-
|
40
|
+
get_global_logger().info(
|
41
41
|
f"MTLS ASGI app initialized: client_cert_required={self.client_cert_required}"
|
42
42
|
)
|
43
43
|
|
@@ -57,11 +57,11 @@ class MTLSASGIApp:
|
|
57
57
|
if client_cert:
|
58
58
|
# Store certificate in scope for middleware access
|
59
59
|
scope["client_certificate"] = client_cert
|
60
|
-
|
60
|
+
get_global_logger().debug(
|
61
61
|
f"Client certificate extracted: {client_cert.get('subject', {})}"
|
62
62
|
)
|
63
63
|
elif self.client_cert_required:
|
64
|
-
|
64
|
+
get_global_logger().warning("Client certificate required but not provided")
|
65
65
|
# Return 401 Unauthorized
|
66
66
|
await self._send_unauthorized_response(send)
|
67
67
|
return
|
@@ -70,7 +70,7 @@ class MTLSASGIApp:
|
|
70
70
|
await self.app(scope, receive, send)
|
71
71
|
|
72
72
|
except Exception as e:
|
73
|
-
|
73
|
+
get_global_logger().error(f"Error in MTLS ASGI app: {e}")
|
74
74
|
await self._send_error_response(send, str(e))
|
75
75
|
|
76
76
|
def _extract_client_certificate(
|
@@ -88,7 +88,7 @@ class MTLSASGIApp:
|
|
88
88
|
try:
|
89
89
|
ssl_context = scope.get("ssl")
|
90
90
|
if not ssl_context:
|
91
|
-
|
91
|
+
get_global_logger().debug("No SSL context found in scope")
|
92
92
|
return None
|
93
93
|
|
94
94
|
# Try to get peer certificate
|
@@ -99,14 +99,14 @@ class MTLSASGIApp:
|
|
99
99
|
cert = x509.load_der_x509_certificate(cert_data)
|
100
100
|
return self._cert_to_dict(cert)
|
101
101
|
else:
|
102
|
-
|
102
|
+
get_global_logger().debug("No certificate data in SSL context")
|
103
103
|
return None
|
104
104
|
else:
|
105
|
-
|
105
|
+
get_global_logger().debug("SSL context has no getpeercert method")
|
106
106
|
return None
|
107
107
|
|
108
108
|
except Exception as e:
|
109
|
-
|
109
|
+
get_global_logger().error(f"Failed to extract client certificate: {e}")
|
110
110
|
return None
|
111
111
|
|
112
112
|
def _cert_to_dict(self, cert: x509.Certificate) -> Dict[str, Any]:
|
@@ -152,7 +152,7 @@ class MTLSASGIApp:
|
|
152
152
|
},
|
153
153
|
}
|
154
154
|
except Exception as e:
|
155
|
-
|
155
|
+
get_global_logger().error(f"Failed to convert certificate to dict: {e}")
|
156
156
|
return {"error": str(e)}
|
157
157
|
|
158
158
|
async def _send_unauthorized_response(self, send):
|
@@ -72,11 +72,11 @@ class MTLSProxy:
|
|
72
72
|
ssl=ssl_context
|
73
73
|
)
|
74
74
|
|
75
|
-
|
76
|
-
|
75
|
+
get_global_logger().info(f"🔐 mTLS Proxy started on {self.external_host}:{self.external_port}")
|
76
|
+
get_global_logger().info(f"🌐 Proxying to {self.internal_host}:{self.internal_port}")
|
77
77
|
|
78
78
|
except Exception as e:
|
79
|
-
|
79
|
+
get_global_logger().error(f"❌ Failed to start mTLS proxy: {e}")
|
80
80
|
raise
|
81
81
|
|
82
82
|
async def stop(self):
|
@@ -84,14 +84,14 @@ class MTLSProxy:
|
|
84
84
|
if self.server:
|
85
85
|
self.server.close()
|
86
86
|
await self.server.wait_closed()
|
87
|
-
|
87
|
+
get_global_logger().info("🔐 mTLS Proxy stopped")
|
88
88
|
|
89
89
|
async def _handle_client(self, reader, writer):
|
90
90
|
"""Handle client connection."""
|
91
91
|
try:
|
92
92
|
# Get client address
|
93
93
|
client_addr = writer.get_extra_info('peername')
|
94
|
-
|
94
|
+
get_global_logger().info(f"🔐 mTLS connection from {client_addr}")
|
95
95
|
|
96
96
|
# Connect to internal server
|
97
97
|
internal_reader, internal_writer = await asyncio.open_connection(
|
@@ -105,7 +105,7 @@ class MTLSProxy:
|
|
105
105
|
)
|
106
106
|
|
107
107
|
except Exception as e:
|
108
|
-
|
108
|
+
get_global_logger().error(f"❌ Error handling client connection: {e}")
|
109
109
|
finally:
|
110
110
|
try:
|
111
111
|
writer.close()
|
@@ -123,7 +123,7 @@ class MTLSProxy:
|
|
123
123
|
writer.write(data)
|
124
124
|
await writer.drain()
|
125
125
|
except Exception as e:
|
126
|
-
|
126
|
+
get_global_logger().debug(f"Proxy connection closed ({direction}): {e}")
|
127
127
|
finally:
|
128
128
|
try:
|
129
129
|
writer.close()
|
@@ -148,7 +148,7 @@ async def start_mtls_proxy(config: Dict[str, Any]) -> Optional[MTLSProxy]:
|
|
148
148
|
|
149
149
|
# Only start mTLS proxy if mTLS is explicitly enabled
|
150
150
|
if protocol != "mtls" and not verify_client:
|
151
|
-
|
151
|
+
get_global_logger().info("🌐 Regular mode: no mTLS proxy needed")
|
152
152
|
return None
|
153
153
|
|
154
154
|
# Get configuration
|
@@ -164,7 +164,7 @@ async def start_mtls_proxy(config: Dict[str, Any]) -> Optional[MTLSProxy]:
|
|
164
164
|
ca_cert = transport_config.get("ca_cert")
|
165
165
|
|
166
166
|
if not cert_file or not key_file:
|
167
|
-
|
167
|
+
get_global_logger().warning("⚠️ mTLS enabled but certificates not configured")
|
168
168
|
return None
|
169
169
|
|
170
170
|
# Create and start proxy
|
@@ -25,8 +25,8 @@ class mTLSHandler(BaseHTTPRequestHandler):
|
|
25
25
|
super().__init__(*args, **kwargs)
|
26
26
|
|
27
27
|
def log_message(self, format, *args):
|
28
|
-
"""Override to use our
|
29
|
-
|
28
|
+
"""Override to use our get_global_logger()."""
|
29
|
+
get_global_logger().info(f"mTLS Server: {format % args}")
|
30
30
|
|
31
31
|
def do_GET(self):
|
32
32
|
"""Handle GET requests."""
|
@@ -58,7 +58,7 @@ class mTLSHandler(BaseHTTPRequestHandler):
|
|
58
58
|
self.wfile.write(json.dumps(response_data).encode())
|
59
59
|
|
60
60
|
except Exception as e:
|
61
|
-
|
61
|
+
get_global_logger().error(f"Error in mTLS GET handler: {e}")
|
62
62
|
self.send_error(500, str(e))
|
63
63
|
|
64
64
|
def do_POST(self):
|
@@ -100,7 +100,7 @@ class mTLSHandler(BaseHTTPRequestHandler):
|
|
100
100
|
self.wfile.write(json.dumps(response_data).encode())
|
101
101
|
|
102
102
|
except Exception as e:
|
103
|
-
|
103
|
+
get_global_logger().error(f"Error in mTLS POST handler: {e}")
|
104
104
|
self.send_error(500, str(e))
|
105
105
|
|
106
106
|
def _forward_to_main_app(
|
@@ -124,7 +124,7 @@ class mTLSHandler(BaseHTTPRequestHandler):
|
|
124
124
|
"forwarded": True,
|
125
125
|
}
|
126
126
|
except Exception as e:
|
127
|
-
|
127
|
+
get_global_logger().error(f"Error forwarding to main app: {e}")
|
128
128
|
return {
|
129
129
|
"status": "error",
|
130
130
|
"message": f"Forwarding failed: {e}",
|
@@ -167,7 +167,7 @@ class mTLSServer:
|
|
167
167
|
self.server_thread: Optional[threading.Thread] = None
|
168
168
|
self.running = False
|
169
169
|
|
170
|
-
|
170
|
+
get_global_logger().info(f"mTLS Server initialized: {host}:{port}")
|
171
171
|
|
172
172
|
def _create_handler(self):
|
173
173
|
"""Create handler with main app reference."""
|
@@ -182,15 +182,15 @@ class mTLSServer:
|
|
182
182
|
try:
|
183
183
|
# Check if certificate files exist
|
184
184
|
if not os.path.exists(self.cert_file):
|
185
|
-
|
185
|
+
get_global_logger().error(f"Certificate file not found: {self.cert_file}")
|
186
186
|
return False
|
187
187
|
|
188
188
|
if not os.path.exists(self.key_file):
|
189
|
-
|
189
|
+
get_global_logger().error(f"Key file not found: {self.key_file}")
|
190
190
|
return False
|
191
191
|
|
192
192
|
if not os.path.exists(self.ca_cert_file):
|
193
|
-
|
193
|
+
get_global_logger().error(
|
194
194
|
f"CA certificate file not found: {self.ca_cert_file}"
|
195
195
|
)
|
196
196
|
return False
|
@@ -217,24 +217,24 @@ class mTLSServer:
|
|
217
217
|
self.server_thread.start()
|
218
218
|
|
219
219
|
self.running = True
|
220
|
-
|
220
|
+
get_global_logger().info(
|
221
221
|
f"✅ mTLS Server started on https://{self.host}:{self.port}"
|
222
222
|
)
|
223
223
|
return True
|
224
224
|
|
225
225
|
except Exception as e:
|
226
|
-
|
226
|
+
get_global_logger().error(f"Failed to start mTLS server: {e}")
|
227
227
|
return False
|
228
228
|
|
229
229
|
def _run_server(self):
|
230
230
|
"""Run the server (blocking)."""
|
231
231
|
try:
|
232
|
-
|
232
|
+
get_global_logger().info(
|
233
233
|
f"mTLS Server listening on https://{self.host}:{self.port}"
|
234
234
|
)
|
235
235
|
self.server.serve_forever()
|
236
236
|
except Exception as e:
|
237
|
-
|
237
|
+
get_global_logger().error(f"mTLS Server error: {e}")
|
238
238
|
finally:
|
239
239
|
self.running = False
|
240
240
|
|
@@ -245,9 +245,9 @@ class mTLSServer:
|
|
245
245
|
self.server.shutdown()
|
246
246
|
self.server.server_close()
|
247
247
|
self.running = False
|
248
|
-
|
248
|
+
get_global_logger().info("✅ mTLS Server stopped")
|
249
249
|
except Exception as e:
|
250
|
-
|
250
|
+
get_global_logger().error(f"Error stopping mTLS server: {e}")
|
251
251
|
|
252
252
|
def is_running(self) -> bool:
|
253
253
|
"""Check if server is running."""
|
@@ -278,7 +278,7 @@ def start_mtls_server_thread(
|
|
278
278
|
# Check if mTLS is enabled
|
279
279
|
verify_client = ssl_config.get("verify_client", False)
|
280
280
|
if not verify_client:
|
281
|
-
|
281
|
+
get_global_logger().info(
|
282
282
|
"mTLS not enabled (verify_client=False), skipping mTLS server"
|
283
283
|
)
|
284
284
|
return None
|
@@ -316,9 +316,9 @@ def start_mtls_server_thread(
|
|
316
316
|
if mtls_server.start():
|
317
317
|
return mtls_server
|
318
318
|
else:
|
319
|
-
|
319
|
+
get_global_logger().error("Failed to start mTLS server")
|
320
320
|
return None
|
321
321
|
|
322
322
|
except Exception as e:
|
323
|
-
|
323
|
+
get_global_logger().error(f"Error starting mTLS server thread: {e}")
|
324
324
|
return None
|