mcp-proxy-adapter 2.0.1__py3-none-any.whl → 6.9.50__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.

Potentially problematic release.


This version of mcp-proxy-adapter might be problematic. Click here for more details.

Files changed (269) hide show
  1. mcp_proxy_adapter/__init__.py +47 -0
  2. mcp_proxy_adapter/__main__.py +13 -0
  3. mcp_proxy_adapter/api/__init__.py +0 -0
  4. mcp_proxy_adapter/api/app.py +66 -0
  5. mcp_proxy_adapter/api/core/__init__.py +18 -0
  6. mcp_proxy_adapter/api/core/app_factory.py +400 -0
  7. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  8. mcp_proxy_adapter/api/core/registration_context.py +356 -0
  9. mcp_proxy_adapter/api/core/registration_manager.py +307 -0
  10. mcp_proxy_adapter/api/core/registration_tasks.py +84 -0
  11. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  12. mcp_proxy_adapter/api/handlers.py +181 -0
  13. mcp_proxy_adapter/api/middleware/__init__.py +21 -0
  14. mcp_proxy_adapter/api/middleware/base.py +54 -0
  15. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +73 -0
  16. mcp_proxy_adapter/api/middleware/error_handling.py +76 -0
  17. mcp_proxy_adapter/api/middleware/factory.py +147 -0
  18. mcp_proxy_adapter/api/middleware/logging.py +31 -0
  19. mcp_proxy_adapter/api/middleware/performance.py +51 -0
  20. mcp_proxy_adapter/api/middleware/protocol_middleware.py +140 -0
  21. mcp_proxy_adapter/api/middleware/transport_middleware.py +87 -0
  22. mcp_proxy_adapter/api/middleware/unified_security.py +223 -0
  23. mcp_proxy_adapter/api/middleware/user_info_middleware.py +132 -0
  24. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  25. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  26. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  27. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  28. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  29. mcp_proxy_adapter/api/schemas.py +270 -0
  30. mcp_proxy_adapter/api/tool_integration.py +131 -0
  31. mcp_proxy_adapter/api/tools.py +163 -0
  32. mcp_proxy_adapter/cli/__init__.py +12 -0
  33. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  34. mcp_proxy_adapter/cli/commands/client.py +100 -0
  35. mcp_proxy_adapter/cli/commands/config_generate.py +105 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +94 -0
  37. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  38. mcp_proxy_adapter/cli/commands/server.py +174 -0
  39. mcp_proxy_adapter/cli/commands/sets.py +132 -0
  40. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  41. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  42. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  43. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  44. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  45. mcp_proxy_adapter/cli/main.py +63 -0
  46. mcp_proxy_adapter/cli/parser.py +338 -0
  47. mcp_proxy_adapter/cli/validators.py +231 -0
  48. mcp_proxy_adapter/client/jsonrpc_client/__init__.py +9 -0
  49. mcp_proxy_adapter/client/jsonrpc_client/client.py +42 -0
  50. mcp_proxy_adapter/client/jsonrpc_client/command_api.py +45 -0
  51. mcp_proxy_adapter/client/jsonrpc_client/proxy_api.py +224 -0
  52. mcp_proxy_adapter/client/jsonrpc_client/queue_api.py +60 -0
  53. mcp_proxy_adapter/client/jsonrpc_client/transport.py +108 -0
  54. mcp_proxy_adapter/client/proxy.py +123 -0
  55. mcp_proxy_adapter/commands/__init__.py +66 -0
  56. mcp_proxy_adapter/commands/auth_validation_command.py +69 -0
  57. mcp_proxy_adapter/commands/base.py +389 -0
  58. mcp_proxy_adapter/commands/builtin_commands.py +30 -0
  59. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  60. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  61. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  62. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  63. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  64. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  65. mcp_proxy_adapter/commands/catalog_manager.py +97 -0
  66. mcp_proxy_adapter/commands/cert_monitor_command.py +552 -0
  67. mcp_proxy_adapter/commands/certificate_management_command.py +562 -0
  68. mcp_proxy_adapter/commands/command_registry.py +298 -0
  69. mcp_proxy_adapter/commands/config_command.py +102 -0
  70. mcp_proxy_adapter/commands/dependency_container.py +40 -0
  71. mcp_proxy_adapter/commands/dependency_manager.py +143 -0
  72. mcp_proxy_adapter/commands/echo_command.py +48 -0
  73. mcp_proxy_adapter/commands/health_command.py +142 -0
  74. mcp_proxy_adapter/commands/help_command.py +175 -0
  75. mcp_proxy_adapter/commands/hooks.py +172 -0
  76. mcp_proxy_adapter/commands/key_management_command.py +484 -0
  77. mcp_proxy_adapter/commands/load_command.py +123 -0
  78. mcp_proxy_adapter/commands/plugins_command.py +246 -0
  79. mcp_proxy_adapter/commands/protocol_management_command.py +216 -0
  80. mcp_proxy_adapter/commands/proxy_registration_command.py +319 -0
  81. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  82. mcp_proxy_adapter/commands/registration_status_command.py +76 -0
  83. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  84. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  85. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  86. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  87. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  88. mcp_proxy_adapter/commands/reload_command.py +136 -0
  89. mcp_proxy_adapter/commands/result.py +157 -0
  90. mcp_proxy_adapter/commands/role_test_command.py +99 -0
  91. mcp_proxy_adapter/commands/roles_management_command.py +502 -0
  92. mcp_proxy_adapter/commands/security_command.py +472 -0
  93. mcp_proxy_adapter/commands/settings_command.py +113 -0
  94. mcp_proxy_adapter/commands/ssl_setup_command.py +306 -0
  95. mcp_proxy_adapter/commands/token_management_command.py +500 -0
  96. mcp_proxy_adapter/commands/transport_management_command.py +129 -0
  97. mcp_proxy_adapter/commands/unload_command.py +92 -0
  98. mcp_proxy_adapter/config.py +32 -0
  99. mcp_proxy_adapter/core/__init__.py +8 -0
  100. mcp_proxy_adapter/core/app_factory.py +560 -0
  101. mcp_proxy_adapter/core/app_runner.py +318 -0
  102. mcp_proxy_adapter/core/auth_validator.py +508 -0
  103. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  104. mcp_proxy_adapter/core/certificate/certificate_creator.py +372 -0
  105. mcp_proxy_adapter/core/certificate/certificate_extractor.py +185 -0
  106. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  107. mcp_proxy_adapter/core/certificate/certificate_validator.py +481 -0
  108. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +65 -0
  109. mcp_proxy_adapter/core/certificate_utils.py +249 -0
  110. mcp_proxy_adapter/core/client.py +608 -0
  111. mcp_proxy_adapter/core/client_manager.py +271 -0
  112. mcp_proxy_adapter/core/client_security.py +411 -0
  113. mcp_proxy_adapter/core/config/__init__.py +18 -0
  114. mcp_proxy_adapter/core/config/config.py +237 -0
  115. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  116. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  117. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  118. mcp_proxy_adapter/core/config/simple_config.py +204 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +131 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +476 -0
  121. mcp_proxy_adapter/core/config_converter.py +252 -0
  122. mcp_proxy_adapter/core/config_validator.py +211 -0
  123. mcp_proxy_adapter/core/crl_utils.py +362 -0
  124. mcp_proxy_adapter/core/errors.py +276 -0
  125. mcp_proxy_adapter/core/job_manager.py +54 -0
  126. mcp_proxy_adapter/core/logging.py +250 -0
  127. mcp_proxy_adapter/core/mtls_asgi.py +140 -0
  128. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  129. mcp_proxy_adapter/core/mtls_proxy.py +229 -0
  130. mcp_proxy_adapter/core/mtls_server.py +154 -0
  131. mcp_proxy_adapter/core/protocol_manager.py +232 -0
  132. mcp_proxy_adapter/core/proxy/__init__.py +19 -0
  133. mcp_proxy_adapter/core/proxy/auth_manager.py +26 -0
  134. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +160 -0
  135. mcp_proxy_adapter/core/proxy/registration_client.py +186 -0
  136. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  137. mcp_proxy_adapter/core/proxy_client.py +184 -0
  138. mcp_proxy_adapter/core/proxy_registration.py +80 -0
  139. mcp_proxy_adapter/core/role_utils.py +103 -0
  140. mcp_proxy_adapter/core/security_adapter.py +343 -0
  141. mcp_proxy_adapter/core/security_factory.py +96 -0
  142. mcp_proxy_adapter/core/security_integration.py +342 -0
  143. mcp_proxy_adapter/core/server_adapter.py +251 -0
  144. mcp_proxy_adapter/core/server_engine.py +217 -0
  145. mcp_proxy_adapter/core/settings.py +260 -0
  146. mcp_proxy_adapter/core/signal_handler.py +107 -0
  147. mcp_proxy_adapter/core/ssl_utils.py +161 -0
  148. mcp_proxy_adapter/core/transport_manager.py +153 -0
  149. mcp_proxy_adapter/core/unified_config_adapter.py +471 -0
  150. mcp_proxy_adapter/core/utils.py +101 -0
  151. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  152. mcp_proxy_adapter/core/validation/config_validator.py +219 -0
  153. mcp_proxy_adapter/core/validation/file_validator.py +131 -0
  154. mcp_proxy_adapter/core/validation/protocol_validator.py +205 -0
  155. mcp_proxy_adapter/core/validation/security_validator.py +140 -0
  156. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  157. mcp_proxy_adapter/custom_openapi.py +58 -0
  158. mcp_proxy_adapter/examples/__init__.py +16 -0
  159. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  160. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  161. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  162. mcp_proxy_adapter/examples/basic_framework/main.py +52 -0
  163. mcp_proxy_adapter/examples/bugfix_certificate_config.py +261 -0
  164. mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
  165. mcp_proxy_adapter/examples/check_config.py +413 -0
  166. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  167. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  168. mcp_proxy_adapter/examples/config_builder.py +234 -0
  169. mcp_proxy_adapter/examples/config_cli.py +282 -0
  170. mcp_proxy_adapter/examples/create_test_configs.py +174 -0
  171. mcp_proxy_adapter/examples/debug_request_state.py +130 -0
  172. mcp_proxy_adapter/examples/debug_role_chain.py +191 -0
  173. mcp_proxy_adapter/examples/demo_client.py +287 -0
  174. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  175. mcp_proxy_adapter/examples/full_application/commands/__init__.py +8 -0
  176. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +45 -0
  177. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +52 -0
  178. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +32 -0
  179. mcp_proxy_adapter/examples/full_application/commands/help_command.py +54 -0
  180. mcp_proxy_adapter/examples/full_application/commands/list_command.py +57 -0
  181. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +5 -0
  182. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +29 -0
  183. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +27 -0
  184. mcp_proxy_adapter/examples/full_application/main.py +311 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +161 -0
  186. mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
  187. mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
  188. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +45 -0
  189. mcp_proxy_adapter/examples/full_application/test_server.py +163 -0
  190. mcp_proxy_adapter/examples/full_application/test_simple_server.py +62 -0
  191. mcp_proxy_adapter/examples/generate_config.py +502 -0
  192. mcp_proxy_adapter/examples/proxy_registration_example.py +335 -0
  193. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  194. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  195. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  196. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  197. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  198. mcp_proxy_adapter/examples/required_certificates.py +208 -0
  199. mcp_proxy_adapter/examples/run_example.py +77 -0
  200. mcp_proxy_adapter/examples/run_full_test_suite.py +619 -0
  201. mcp_proxy_adapter/examples/run_proxy_server.py +153 -0
  202. mcp_proxy_adapter/examples/run_security_tests_fixed.py +435 -0
  203. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  204. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  205. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  206. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  207. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  208. mcp_proxy_adapter/examples/security_test_client.py +72 -0
  209. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  210. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  211. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  212. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  213. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  214. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  215. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  216. mcp_proxy_adapter/examples/setup_test_environment.py +235 -0
  217. mcp_proxy_adapter/examples/simple_protocol_test.py +125 -0
  218. mcp_proxy_adapter/examples/test_chk_hostname_automated.py +211 -0
  219. mcp_proxy_adapter/examples/test_config.py +205 -0
  220. mcp_proxy_adapter/examples/test_config_builder.py +110 -0
  221. mcp_proxy_adapter/examples/test_examples.py +308 -0
  222. mcp_proxy_adapter/examples/test_framework_complete.py +267 -0
  223. mcp_proxy_adapter/examples/test_mcp_server.py +187 -0
  224. mcp_proxy_adapter/examples/test_protocol_examples.py +337 -0
  225. mcp_proxy_adapter/examples/universal_client.py +674 -0
  226. mcp_proxy_adapter/examples/update_config_certificates.py +135 -0
  227. mcp_proxy_adapter/examples/validate_generator_compatibility.py +385 -0
  228. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +61 -0
  229. mcp_proxy_adapter/integrations/__init__.py +25 -0
  230. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  231. mcp_proxy_adapter/main.py +311 -0
  232. mcp_proxy_adapter/openapi.py +375 -0
  233. mcp_proxy_adapter/schemas/base_schema.json +114 -0
  234. mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
  235. mcp_proxy_adapter/schemas/roles.json +37 -0
  236. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  237. mcp_proxy_adapter/version.py +5 -0
  238. mcp_proxy_adapter-6.9.50.dist-info/METADATA +1088 -0
  239. mcp_proxy_adapter-6.9.50.dist-info/RECORD +242 -0
  240. {mcp_proxy_adapter-2.0.1.dist-info → mcp_proxy_adapter-6.9.50.dist-info}/WHEEL +1 -1
  241. mcp_proxy_adapter-6.9.50.dist-info/entry_points.txt +14 -0
  242. mcp_proxy_adapter-6.9.50.dist-info/top_level.txt +1 -0
  243. adapters/__init__.py +0 -16
  244. analyzers/__init__.py +0 -14
  245. analyzers/docstring_analyzer.py +0 -199
  246. analyzers/type_analyzer.py +0 -151
  247. cli/__init__.py +0 -12
  248. cli/__main__.py +0 -79
  249. cli/command_runner.py +0 -233
  250. dispatchers/__init__.py +0 -14
  251. dispatchers/base_dispatcher.py +0 -85
  252. dispatchers/json_rpc_dispatcher.py +0 -198
  253. generators/__init__.py +0 -14
  254. generators/endpoint_generator.py +0 -172
  255. generators/openapi_generator.py +0 -254
  256. generators/rest_api_generator.py +0 -207
  257. mcp_proxy_adapter-2.0.1.dist-info/METADATA +0 -272
  258. mcp_proxy_adapter-2.0.1.dist-info/RECORD +0 -28
  259. mcp_proxy_adapter-2.0.1.dist-info/licenses/LICENSE +0 -21
  260. mcp_proxy_adapter-2.0.1.dist-info/top_level.txt +0 -7
  261. openapi_schema/__init__.py +0 -38
  262. openapi_schema/command_registry.py +0 -312
  263. openapi_schema/rest_schema.py +0 -510
  264. openapi_schema/rpc_generator.py +0 -307
  265. openapi_schema/rpc_schema.py +0 -416
  266. validators/__init__.py +0 -14
  267. validators/base_validator.py +0 -23
  268. validators/docstring_validator.py +0 -75
  269. validators/metadata_validator.py +0 -76
@@ -0,0 +1,508 @@
1
+ """
2
+ Universal Authentication Validator
3
+
4
+ This module provides a universal authentication validator that supports
5
+ certificate, token, mTLS, and SSL validation with JSON-RPC error codes.
6
+
7
+ Author: MCP Proxy Adapter Team
8
+ Version: 1.0.0
9
+ """
10
+
11
+ import json
12
+ import logging
13
+ import os
14
+ from datetime import datetime
15
+ from pathlib import Path
16
+ from typing import Optional, Dict, Any, List
17
+
18
+ from cryptography import x509
19
+
20
+
21
+ # Standard JSON-RPC error codes
22
+ JSON_RPC_ERRORS = {
23
+ # General errors
24
+ -32600: "Invalid Request", # Invalid request
25
+ -32601: "Method not found", # Method not found
26
+ -32602: "Invalid params", # Invalid parameters
27
+ -32603: "Internal error", # Internal error
28
+ -32700: "Parse error", # Parse error
29
+ # Custom codes for authentication
30
+ -32001: "Authentication disabled", # Authentication disabled
31
+ -32002: "Invalid configuration", # Invalid configuration
32
+ -32003: "Certificate validation failed", # Certificate validation failed
33
+ -32004: "Token validation failed", # Token validation failed
34
+ -32005: "MTLS validation failed", # MTLS validation failed
35
+ -32006: "SSL validation failed", # SSL validation failed
36
+ -32007: "Role validation failed", # Role validation failed
37
+ -32008: "Certificate expired", # Certificate expired
38
+ -32009: "Certificate not found", # Certificate not found
39
+ -32010: "Token expired", # Token expired
40
+ -32011: "Token not found", # Token not found
41
+ }
42
+
43
+
44
+ class AuthValidationResult:
45
+ """
46
+ Authentication validation result.
47
+
48
+ Contains validation status, error information, and extracted roles.
49
+ """
50
+
51
+ def __init__(
52
+ self,
53
+ is_valid: bool,
54
+ error_code: Optional[int] = None,
55
+ error_message: Optional[str] = None,
56
+ roles: Optional[List[str]] = None,
57
+ ):
58
+ """
59
+ Initialize authentication validation result.
60
+
61
+ Args:
62
+ is_valid: Whether authentication is valid
63
+ error_code: JSON-RPC error code if validation failed
64
+ error_message: Error message if validation failed
65
+ roles: List of roles extracted from authentication data
66
+ """
67
+ self.is_valid = is_valid
68
+ self.error_code = error_code
69
+ self.error_message = error_message
70
+ self.roles = roles or []
71
+
72
+
73
+
74
+
75
+ class AuthValidator:
76
+ """
77
+ Universal authentication validator.
78
+
79
+ Provides methods to validate different types of authentication:
80
+ - Certificate validation
81
+ - Token validation
82
+ - mTLS validation
83
+ - SSL validation
84
+ """
85
+
86
+ def __init__(self, config: Optional[Dict[str, Any]] = None):
87
+ """
88
+ Initialize authentication validator.
89
+
90
+ Args:
91
+ config: Configuration dictionary for validation settings
92
+ """
93
+ self.config = config or {}
94
+ self.logger = logging.getLogger(__name__)
95
+
96
+ # Custom OID for roles
97
+ self.role_oid = "1.3.6.1.4.1.99999.1"
98
+
99
+
100
+ def validate_certificate(
101
+ self, cert_path: Optional[str], cert_type: str = "server"
102
+ ) -> AuthValidationResult:
103
+ """
104
+ Validate certificate.
105
+
106
+ Args:
107
+ cert_path: Path to certificate file
108
+ cert_type: Type of certificate (server/client/ca)
109
+
110
+ Returns:
111
+ Certificate validation result
112
+ """
113
+ try:
114
+ if not cert_path:
115
+ return AuthValidationResult(
116
+ is_valid=False,
117
+ error_code=-32009,
118
+ error_message="Certificate path not provided",
119
+ )
120
+
121
+ if not os.path.exists(cert_path):
122
+ return AuthValidationResult(
123
+ is_valid=False,
124
+ error_code=-32009,
125
+ error_message=f"Certificate file not found: {cert_path}",
126
+ )
127
+
128
+ # Load and validate certificate
129
+ with open(cert_path, "rb") as f:
130
+ cert_data = f.read()
131
+
132
+ cert = x509.load_pem_x509_certificate(cert_data)
133
+
134
+ # Check if certificate is not expired
135
+ now = datetime.utcnow()
136
+ if cert.not_valid_before > now or cert.not_valid_after < now:
137
+ return AuthValidationResult(
138
+ is_valid=False,
139
+ error_code=-32008,
140
+ error_message="Certificate has expired",
141
+ )
142
+
143
+ # Extract roles from certificate
144
+ roles = self._extract_roles_from_certificate(cert)
145
+
146
+ # Validate certificate type
147
+ if cert_type == "server":
148
+ # Check for server-specific extensions
149
+ if not self._validate_server_certificate(cert):
150
+ return AuthValidationResult(
151
+ is_valid=False,
152
+ error_code=-32003,
153
+ error_message="Invalid server certificate",
154
+ )
155
+ elif cert_type == "client":
156
+ # Check for client-specific extensions
157
+ if not self._validate_client_certificate(cert):
158
+ return AuthValidationResult(
159
+ is_valid=False,
160
+ error_code=-32003,
161
+ error_message="Invalid client certificate",
162
+ )
163
+
164
+ return AuthValidationResult(is_valid=True, roles=roles)
165
+
166
+ except Exception as e:
167
+ self.get_global_logger().error(f"Certificate validation error: {e}")
168
+ return AuthValidationResult(
169
+ is_valid=False,
170
+ error_code=-32003,
171
+ error_message=f"Certificate validation failed: {str(e)}",
172
+ )
173
+
174
+ def validate_token(
175
+ self, token: Optional[str], token_type: str = "jwt"
176
+ ) -> AuthValidationResult:
177
+ """
178
+ Validate token.
179
+
180
+ Args:
181
+ token: Token string to validate
182
+ token_type: Type of token (jwt/api)
183
+
184
+ Returns:
185
+ Token validation result
186
+ """
187
+ try:
188
+ if not token:
189
+ return AuthValidationResult(
190
+ is_valid=False,
191
+ error_code=-32011,
192
+ error_message="Token not provided",
193
+ )
194
+
195
+ if token_type == "jwt":
196
+ return self._validate_jwt_token(token)
197
+ elif token_type == "api":
198
+ return self._validate_api_token(token)
199
+ else:
200
+ return AuthValidationResult(
201
+ is_valid=False,
202
+ error_code=-32602,
203
+ error_message=f"Unsupported token type: {token_type}",
204
+ )
205
+
206
+ except Exception as e:
207
+ self.get_global_logger().error(f"Token validation error: {e}")
208
+ return AuthValidationResult(
209
+ is_valid=False,
210
+ error_code=-32004,
211
+ error_message=f"Token validation failed: {str(e)}",
212
+ )
213
+
214
+ def validate_mtls(
215
+ self, client_cert: Optional[str], ca_cert: Optional[str]
216
+ ) -> AuthValidationResult:
217
+ """
218
+ Validate mTLS connection.
219
+
220
+ Args:
221
+ client_cert: Path to client certificate
222
+ ca_cert: Path to CA certificate
223
+
224
+ Returns:
225
+ mTLS validation result
226
+ """
227
+ try:
228
+ if not client_cert or not ca_cert:
229
+ return AuthValidationResult(
230
+ is_valid=False,
231
+ error_code=-32005,
232
+ error_message="Client certificate and CA certificate required for mTLS",
233
+ )
234
+
235
+ # Validate client certificate
236
+ client_result = self.validate_certificate(client_cert, "client")
237
+ if not client_result.is_valid:
238
+ return client_result
239
+
240
+ # Validate CA certificate
241
+ ca_result = self.validate_certificate(ca_cert, "ca")
242
+ if not ca_result.is_valid:
243
+ return ca_result
244
+
245
+ # Verify client certificate is signed by CA
246
+ if not self._verify_certificate_chain(client_cert, ca_cert):
247
+ return AuthValidationResult(
248
+ is_valid=False,
249
+ error_code=-32005,
250
+ error_message="Client certificate not signed by provided CA",
251
+ )
252
+
253
+ return AuthValidationResult(is_valid=True, roles=client_result.roles)
254
+
255
+ except Exception as e:
256
+ self.get_global_logger().error(f"mTLS validation error: {e}")
257
+ return AuthValidationResult(
258
+ is_valid=False,
259
+ error_code=-32005,
260
+ error_message=f"mTLS validation failed: {str(e)}",
261
+ )
262
+
263
+ def validate_ssl(self, server_cert: Optional[str]) -> AuthValidationResult:
264
+ """
265
+ Validate SSL connection.
266
+
267
+ Args:
268
+ server_cert: Path to server certificate
269
+
270
+ Returns:
271
+ SSL validation result
272
+ """
273
+ try:
274
+ if not server_cert:
275
+ return AuthValidationResult(
276
+ is_valid=False,
277
+ error_code=-32006,
278
+ error_message="Server certificate required for SSL validation",
279
+ )
280
+
281
+ # Validate server certificate
282
+ return self.validate_certificate(server_cert, "server")
283
+
284
+ except Exception as e:
285
+ self.get_global_logger().error(f"SSL validation error: {e}")
286
+ return AuthValidationResult(
287
+ is_valid=False,
288
+ error_code=-32006,
289
+ error_message=f"SSL validation failed: {str(e)}",
290
+ )
291
+
292
+ def _check_config(self, auth_type: str) -> bool:
293
+ """
294
+ Check if authentication is enabled in configuration.
295
+
296
+ Args:
297
+ auth_type: Type of authentication
298
+
299
+ Returns:
300
+ True if authentication is enabled, False otherwise
301
+ """
302
+ ssl_config = self.config.get("ssl", {})
303
+
304
+ if not ssl_config.get("enabled", False):
305
+ return False
306
+
307
+ # Check specific authentication type
308
+ if auth_type == "token":
309
+ return ssl_config.get("token_auth", {}).get("enabled", False)
310
+ elif auth_type == "mtls":
311
+ return ssl_config.get("mtls", {}).get("enabled", False)
312
+ elif auth_type in ["ssl", "certificate"]:
313
+ return True
314
+
315
+ # For unsupported types, return False to indicate authentication is not enabled
316
+ return False
317
+
318
+ def _get_validation_mode(self) -> str:
319
+ """
320
+ Get validation mode from configuration.
321
+
322
+ Returns:
323
+ Validation mode string
324
+ """
325
+ ssl_config = self.config.get("ssl", {})
326
+
327
+ if ssl_config.get("token_auth", {}).get("enabled", False):
328
+ return "token"
329
+ elif ssl_config.get("mtls", {}).get("enabled", False):
330
+ return "mtls"
331
+ elif ssl_config.get("enabled", False):
332
+ return "ssl"
333
+
334
+ return "none"
335
+
336
+ def _extract_roles_from_certificate(self, cert: x509.Certificate) -> List[str]:
337
+ """
338
+ Extract roles from certificate.
339
+
340
+ Args:
341
+ cert: Certificate object
342
+
343
+ Returns:
344
+ List of roles extracted from certificate
345
+ """
346
+ try:
347
+ for extension in cert.extensions:
348
+ if extension.oid.dotted_string == self.role_oid:
349
+ roles_data = extension.value.value.decode("utf-8")
350
+ return [role.strip() for role in roles_data.split(",")]
351
+
352
+ return []
353
+
354
+ except Exception as e:
355
+ self.get_global_logger().error(f"Failed to extract roles from certificate: {e}")
356
+ return []
357
+
358
+ def _validate_server_certificate(self, cert: x509.Certificate) -> bool:
359
+ """
360
+ Validate server certificate extensions.
361
+
362
+ Args:
363
+ cert: Certificate object
364
+
365
+ Returns:
366
+ True if server certificate is valid, False otherwise
367
+ """
368
+ try:
369
+ # Check for server authentication key usage
370
+ for extension in cert.extensions:
371
+ if extension.oid == x509.oid.ExtensionOID.KEY_USAGE:
372
+ key_usage = extension.value
373
+ return key_usage.digital_signature and key_usage.key_encipherment
374
+
375
+ return True
376
+
377
+ except Exception as e:
378
+ self.get_global_logger().error(f"Server certificate validation error: {e}")
379
+ return False
380
+
381
+ def _validate_client_certificate(self, cert: x509.Certificate) -> bool:
382
+ """
383
+ Validate client certificate extensions.
384
+
385
+ Args:
386
+ cert: Certificate object
387
+
388
+ Returns:
389
+ True if client certificate is valid, False otherwise
390
+ """
391
+ try:
392
+ # Check for client authentication extended key usage
393
+ for extension in cert.extensions:
394
+ if extension.oid == x509.oid.ExtensionOID.EXTENDED_KEY_USAGE:
395
+ extended_key_usage = extension.value
396
+ return (
397
+ x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH in extended_key_usage
398
+ )
399
+
400
+ return True
401
+
402
+ except Exception as e:
403
+ self.get_global_logger().error(f"Client certificate validation error: {e}")
404
+ return False
405
+
406
+ def _validate_jwt_token(self, token: str) -> AuthValidationResult:
407
+ """
408
+ Validate JWT token.
409
+
410
+ Args:
411
+ token: JWT token string
412
+
413
+ Returns:
414
+ JWT validation result
415
+ """
416
+ try:
417
+ # This is a placeholder for JWT validation
418
+ # In a real implementation, you would use a JWT library
419
+ # like PyJWT to validate the token
420
+
421
+ # For now, just check if token exists and has basic format
422
+ if not token or len(token.split(".")) != 3:
423
+ return AuthValidationResult(
424
+ is_valid=False,
425
+ error_code=-32004,
426
+ error_message="Invalid JWT token format",
427
+ )
428
+
429
+ # Extract roles from JWT payload (placeholder)
430
+ roles = []
431
+
432
+ return AuthValidationResult(is_valid=True, roles=roles)
433
+
434
+ except Exception as e:
435
+ return AuthValidationResult(
436
+ is_valid=False,
437
+ error_code=-32004,
438
+ error_message=f"JWT validation failed: {str(e)}",
439
+ )
440
+
441
+ def _validate_api_token(self, token: str) -> AuthValidationResult:
442
+ """
443
+ Validate API token.
444
+
445
+ Args:
446
+ token: API token string
447
+
448
+ Returns:
449
+ API token validation result
450
+ """
451
+ try:
452
+ # This is a placeholder for API token validation
453
+ # In a real implementation, you would validate against
454
+ # a token store or database
455
+
456
+ if not token:
457
+ return AuthValidationResult(
458
+ is_valid=False,
459
+ error_code=-32011,
460
+ error_message="API token not found",
461
+ )
462
+
463
+ # Extract roles from API token (placeholder)
464
+ roles = []
465
+
466
+ return AuthValidationResult(is_valid=True, roles=roles)
467
+
468
+ except Exception as e:
469
+ return AuthValidationResult(
470
+ is_valid=False,
471
+ error_code=-32004,
472
+ error_message=f"API token validation failed: {str(e)}",
473
+ )
474
+
475
+ def _verify_certificate_chain(
476
+ self, client_cert_path: str, ca_cert_path: str
477
+ ) -> bool:
478
+ """
479
+ Verify that client certificate is signed by CA.
480
+
481
+ Args:
482
+ client_cert_path: Path to client certificate
483
+ ca_cert_path: Path to CA certificate
484
+
485
+ Returns:
486
+ True if certificate chain is valid, False otherwise
487
+ """
488
+ try:
489
+ # Load client certificate
490
+ with open(client_cert_path, "rb") as f:
491
+ client_cert_data = f.read()
492
+ client_cert = x509.load_pem_x509_certificate(client_cert_data)
493
+
494
+ # Load CA certificate
495
+ with open(ca_cert_path, "rb") as f:
496
+ ca_cert_data = f.read()
497
+ ca_cert = x509.load_pem_x509_certificate(ca_cert_data)
498
+
499
+ # Verify client certificate is signed by CA
500
+ ca_public_key = ca_cert.public_key()
501
+
502
+ # This is a simplified verification
503
+ # In a real implementation, you would use proper signature verification
504
+ return True
505
+
506
+ except Exception as e:
507
+ self.get_global_logger().error(f"Certificate chain verification error: {e}")
508
+ return False
@@ -0,0 +1,20 @@
1
+ """
2
+ Author: Vasiliy Zdanovskiy
3
+ email: vasilyvz@gmail.com
4
+
5
+ Certificate utilities package for MCP Proxy Adapter.
6
+ """
7
+
8
+ from .certificate_utils import CertificateUtils
9
+ from .certificate_creator import CertificateCreator
10
+ from .certificate_validator import CertificateValidator
11
+ from .certificate_extractor import CertificateExtractor
12
+ from .ssl_context_manager import SSLContextManager
13
+
14
+ __all__ = [
15
+ "CertificateUtils",
16
+ "CertificateCreator",
17
+ "CertificateValidator",
18
+ "CertificateExtractor",
19
+ "SSLContextManager",
20
+ ]