mcp-proxy-adapter 6.9.43__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.
Files changed (242) 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 +355 -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 +266 -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 +35 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +74 -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 +128 -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 +388 -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 +116 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +100 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +380 -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 +190 -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 +13 -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 +264 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +81 -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 +313 -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.43.dist-info/METADATA +739 -0
  239. mcp_proxy_adapter-6.9.43.dist-info/RECORD +242 -0
  240. mcp_proxy_adapter-6.9.43.dist-info/WHEEL +5 -0
  241. mcp_proxy_adapter-6.9.43.dist-info/entry_points.txt +12 -0
  242. mcp_proxy_adapter-6.9.43.dist-info/top_level.txt +1 -0
@@ -0,0 +1,343 @@
1
+ """
2
+ Security Adapter for mcp_security_framework integration.
3
+
4
+ This module provides an adapter layer between mcp_proxy_adapter and mcp_security_framework,
5
+ handling configuration conversion and request validation.
6
+ """
7
+
8
+ import json
9
+ import logging
10
+ from typing import Dict, Any, Optional
11
+
12
+ # Import mcp_security_framework components
13
+ try:
14
+ from mcp_security_framework import SecurityManager, SecurityConfig
15
+ from mcp_security_framework.schemas.config import (
16
+ AuthConfig,
17
+ SSLConfig,
18
+ PermissionConfig,
19
+ RateLimitConfig,
20
+ )
21
+
22
+ # Note: SecurityRequest and SecurityResult are not available in current version
23
+ SECURITY_FRAMEWORK_AVAILABLE = True
24
+ except ImportError as e:
25
+ # NO FALLBACK! mcp_security_framework is REQUIRED
26
+ raise RuntimeError(
27
+ f"CRITICAL: mcp_security_framework is required but not available: {e}. "
28
+ "Install it with: pip install mcp_security_framework>=1.2.8"
29
+ ) from e
30
+
31
+ from mcp_proxy_adapter.core.logging import get_global_logger
32
+
33
+
34
+ class SecurityAdapter:
35
+ """
36
+ Adapter for integrating with mcp_security_framework.
37
+
38
+ Provides methods to convert mcp_proxy_adapter configuration to SecurityConfig
39
+ and handle request validation through the security framework.
40
+ """
41
+
42
+ def __init__(self, config: Dict[str, Any]):
43
+ """
44
+ Initialize security adapter.
45
+
46
+ Args:
47
+ config: mcp_proxy_adapter configuration dictionary
48
+ """
49
+ self.config = config
50
+ self.security_manager = None
51
+
52
+ if SECURITY_FRAMEWORK_AVAILABLE:
53
+ self.security_manager = self._create_security_manager()
54
+ get_global_logger().info("Security adapter initialized with mcp_security_framework")
55
+ else:
56
+ get_global_logger().warning("mcp_security_framework not available, using fallback mode")
57
+
58
+ def _create_security_manager(self) -> Optional[SecurityManager]:
59
+ """
60
+ Create SecurityManager from mcp_proxy_adapter configuration.
61
+
62
+ Returns:
63
+ SecurityManager instance or None if framework not available
64
+ """
65
+ if not SECURITY_FRAMEWORK_AVAILABLE:
66
+ return None
67
+
68
+ try:
69
+ security_config = self._convert_config()
70
+ return SecurityManager(security_config)
71
+ except Exception as e:
72
+ get_global_logger().error(f"Failed to create SecurityManager: {e}")
73
+ return None
74
+
75
+ def _convert_config(self) -> SecurityConfig:
76
+ """
77
+ Convert mcp_proxy_adapter configuration to SecurityConfig.
78
+
79
+ Returns:
80
+ SecurityConfig instance
81
+ """
82
+ # Get security configuration section
83
+ security_config = self.config.get("security", {})
84
+
85
+ # Convert auth configuration
86
+ auth_config = self._convert_auth_config(security_config)
87
+
88
+ # Convert SSL configuration
89
+ ssl_config = self._convert_ssl_config(security_config)
90
+
91
+ # Convert permissions configuration
92
+ permission_config = self._convert_permission_config(security_config)
93
+
94
+ # Convert rate limit configuration
95
+ rate_limit_config = self._convert_rate_limit_config(security_config)
96
+
97
+ return SecurityConfig(
98
+ auth=auth_config,
99
+ ssl=ssl_config,
100
+ permissions=permission_config,
101
+ rate_limit=rate_limit_config,
102
+ )
103
+
104
+ def _convert_auth_config(self, security_config: Dict[str, Any]) -> AuthConfig:
105
+ """
106
+ Convert authentication configuration.
107
+
108
+ Args:
109
+ security_config: Security configuration section
110
+
111
+ Returns:
112
+ AuthConfig instance
113
+ """
114
+ auth_config = security_config.get("auth", {})
115
+
116
+ # Get authentication methods
117
+ methods = auth_config.get("methods", ["api_key"])
118
+
119
+ # Get API keys from legacy config if not in security section
120
+ api_keys = auth_config.get("api_keys", {})
121
+ if not api_keys:
122
+ # Try to get from legacy SSL config
123
+ legacy_ssl = self.config.get("ssl", {})
124
+ if "api_keys" in legacy_ssl:
125
+ api_keys = legacy_ssl["api_keys"]
126
+
127
+ return AuthConfig(
128
+ enabled=auth_config.get("enabled", True),
129
+ methods=methods,
130
+ api_keys=api_keys,
131
+ jwt_secret=auth_config.get("jwt_secret", ""),
132
+ jwt_algorithm=auth_config.get("jwt_algorithm", "HS256"),
133
+ )
134
+
135
+ def _convert_ssl_config(self, security_config: Dict[str, Any]) -> SSLConfig:
136
+ """
137
+ Convert SSL configuration.
138
+
139
+ Args:
140
+ security_config: Security configuration section
141
+
142
+ Returns:
143
+ SSLConfig instance
144
+ """
145
+ ssl_config = security_config.get("ssl", {})
146
+
147
+ # Fallback to legacy SSL config if not in security section
148
+ if not ssl_config:
149
+ ssl_config = self.config.get("ssl", {})
150
+
151
+ return SSLConfig(
152
+ enabled=ssl_config.get("enabled", False),
153
+ cert_file=ssl_config.get("cert_file"),
154
+ key_file=ssl_config.get("key_file"),
155
+ ca_cert=ssl_config.get("ca_cert"),
156
+ min_tls_version=ssl_config.get("min_tls_version", "TLSv1.2"),
157
+ verify_client=ssl_config.get("verify_client", False),
158
+ client_cert_required=ssl_config.get("client_cert_required", False),
159
+ )
160
+
161
+ def _convert_permission_config(
162
+ self, security_config: Dict[str, Any]
163
+ ) -> PermissionConfig:
164
+ """
165
+ Convert permissions configuration.
166
+
167
+ Args:
168
+ security_config: Security configuration section
169
+
170
+ Returns:
171
+ PermissionConfig instance
172
+ """
173
+ permission_config = security_config.get("permissions", {})
174
+
175
+ # Fallback to legacy roles config if not in security section
176
+ if not permission_config:
177
+ roles_config = self.config.get("roles", {})
178
+ permission_config = {
179
+ "enabled": roles_config.get("enabled", True),
180
+ "roles_file": roles_config.get("config_file", "roles.json"),
181
+ "default_role": "user",
182
+ }
183
+
184
+ return PermissionConfig(
185
+ enabled=permission_config.get("enabled", True),
186
+ roles_file=permission_config.get("roles_file", "roles.json"),
187
+ default_role=permission_config.get("default_role", "user"),
188
+ deny_by_default=permission_config.get("deny_by_default", True),
189
+ )
190
+
191
+ def _convert_rate_limit_config(
192
+ self, security_config: Dict[str, Any]
193
+ ) -> RateLimitConfig:
194
+ """
195
+ Convert rate limit configuration.
196
+
197
+ Args:
198
+ security_config: Security configuration section
199
+
200
+ Returns:
201
+ RateLimitConfig instance
202
+ """
203
+ rate_limit_config = security_config.get("rate_limit", {})
204
+
205
+ return RateLimitConfig(
206
+ enabled=rate_limit_config.get("enabled", True),
207
+ requests_per_minute=rate_limit_config.get("requests_per_minute", 60),
208
+ requests_per_hour=rate_limit_config.get("requests_per_hour", 1000),
209
+ burst_limit=rate_limit_config.get("burst_limit", 10),
210
+ by_ip=rate_limit_config.get("by_ip", True),
211
+ by_user=rate_limit_config.get("by_user", True),
212
+ )
213
+
214
+ def validate_request(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
215
+ """
216
+ Validate request through mcp_security_framework.
217
+
218
+ Args:
219
+ request_data: Request data dictionary
220
+
221
+ Returns:
222
+ Validation result dictionary
223
+ """
224
+ get_global_logger().debug(f"Security manager available: {self.security_manager is not None}")
225
+ if not self.security_manager:
226
+ # Fallback validation when framework is not available
227
+ get_global_logger().debug("Using fallback validation")
228
+ return self._fallback_validation(request_data)
229
+
230
+ try:
231
+ # Convert request data to SecurityRequest
232
+ security_request = self._create_security_request(request_data)
233
+
234
+ # Validate through security framework
235
+ result = self.security_manager.validate_request(security_request)
236
+
237
+ return result.to_dict()
238
+
239
+ except Exception as e:
240
+ get_global_logger().error(f"Security validation failed: {e}")
241
+ return {
242
+ "is_valid": False,
243
+ "error_code": -32603,
244
+ "error_message": f"Security validation error: {str(e)}",
245
+ "roles": [],
246
+ "user_id": None,
247
+ }
248
+
249
+ def _create_security_request(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
250
+ """
251
+ Create request data for security validation.
252
+
253
+ Args:
254
+ request_data: Request data dictionary
255
+
256
+ Returns:
257
+ Request data dictionary for security validation
258
+ """
259
+ return {
260
+ "method": request_data.get("method", "GET"),
261
+ "path": request_data.get("path", "/"),
262
+ "headers": request_data.get("headers", {}),
263
+ "query_params": request_data.get("query_params", {}),
264
+ "client_ip": request_data.get("client_ip", "unknown"),
265
+ "body": request_data.get("body", {}),
266
+ }
267
+
268
+ def _fallback_validation(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
269
+ """
270
+ Fallback validation when mcp_security_framework is not available.
271
+
272
+ Args:
273
+ request_data: Request data dictionary
274
+
275
+ Returns:
276
+ Validation result dictionary
277
+ """
278
+ # Simple API key validation as fallback
279
+ headers = request_data.get("headers", {})
280
+ query_params = request_data.get("query_params", {})
281
+ body = request_data.get("body", {})
282
+
283
+ # Check for API key in headers (FastAPI converts headers to lowercase)
284
+ api_key = headers.get("x-api-key") or headers.get("X-API-Key")
285
+ get_global_logger().debug(f"API key from headers: {api_key}")
286
+
287
+ # Check for API key in query parameters
288
+ if not api_key:
289
+ api_key = query_params.get("api_key")
290
+ get_global_logger().debug(f"API key from query params: {api_key}")
291
+
292
+ # Check for API key in JSON-RPC body
293
+ if not api_key and isinstance(body, dict):
294
+ api_key = body.get("params", {}).get("api_key")
295
+ get_global_logger().debug(f"API key from body: {api_key}")
296
+
297
+ # Get API keys from config
298
+ api_keys = self._get_api_keys()
299
+ get_global_logger().debug(f"Available API keys: {list(api_keys.keys())}")
300
+
301
+ if api_key and api_key in api_keys:
302
+ return {
303
+ "is_valid": True,
304
+ "error_code": None,
305
+ "error_message": None,
306
+ "roles": ["user"],
307
+ "user_id": api_keys[api_key],
308
+ }
309
+ else:
310
+ return {
311
+ "is_valid": False,
312
+ "error_code": -32000,
313
+ "error_message": "API key not provided or invalid",
314
+ "roles": [],
315
+ "user_id": None,
316
+ }
317
+
318
+ def _get_api_keys(self) -> Dict[str, str]:
319
+ """
320
+ Get API keys from configuration.
321
+
322
+ Returns:
323
+ Dictionary mapping API keys to usernames
324
+ """
325
+ # Try security config first
326
+ security_config = self.config.get("security", {})
327
+ auth_config = security_config.get("auth", {})
328
+ api_keys = auth_config.get("api_keys", {})
329
+
330
+ get_global_logger().debug(f"Security config: {security_config}")
331
+ get_global_logger().debug(f"Auth config: {auth_config}")
332
+ get_global_logger().debug(f"API keys from security config: {api_keys}")
333
+
334
+ # Fallback to legacy SSL config
335
+ if not api_keys:
336
+ ssl_config = self.config.get("ssl", {})
337
+ api_keys = ssl_config.get("api_keys", {})
338
+ get_global_logger().debug(f"API keys from SSL config: {api_keys}")
339
+
340
+ get_global_logger().info(f"Total API keys loaded: {len(api_keys)}")
341
+ return api_keys
342
+
343
+
@@ -0,0 +1,96 @@
1
+ """
2
+ Security Factory for creating security components.
3
+
4
+ This module provides factory methods for creating security adapters, managers,
5
+ and middleware components with proper configuration and error handling.
6
+ """
7
+
8
+ import logging
9
+ from typing import Dict, Any
10
+
11
+ from mcp_proxy_adapter.core.logging import get_global_logger
12
+ from .security_adapter import SecurityAdapter
13
+
14
+
15
+ class SecurityFactory:
16
+ """
17
+ Factory for creating security components.
18
+
19
+ Provides static methods to create security adapters, managers,
20
+ and middleware components with proper configuration handling.
21
+ """
22
+
23
+ @staticmethod
24
+ def create_security_adapter(config: Dict[str, Any]) -> SecurityAdapter:
25
+ """
26
+ Create SecurityAdapter from configuration.
27
+
28
+ Args:
29
+ config: mcp_proxy_adapter configuration dictionary
30
+
31
+ Returns:
32
+ SecurityAdapter instance
33
+ """
34
+ try:
35
+ adapter = SecurityAdapter(config)
36
+ get_global_logger().info("Security adapter created successfully")
37
+ return adapter
38
+ except Exception as e:
39
+ get_global_logger().error(f"Failed to create security adapter: {e}")
40
+ raise
41
+
42
+ @staticmethod
43
+
44
+ @staticmethod
45
+ def create_middleware(config: Dict[str, Any], framework: str = "fastapi"):
46
+ """
47
+ Create framework-specific security middleware.
48
+
49
+ Args:
50
+ config: mcp_proxy_adapter configuration dictionary
51
+ framework: Framework type (fastapi, flask, etc.)
52
+
53
+ Returns:
54
+ Middleware instance or None if creation failed
55
+ """
56
+ try:
57
+ adapter = SecurityFactory.create_security_adapter(config)
58
+ middleware = adapter.create_middleware(framework)
59
+
60
+ if middleware:
61
+ get_global_logger().info(f"Security middleware created for {framework}")
62
+ else:
63
+ get_global_logger().warning(f"Failed to create security middleware for {framework}")
64
+
65
+ return middleware
66
+
67
+ except Exception as e:
68
+ get_global_logger().error(f"Failed to create security middleware: {e}")
69
+ return None
70
+
71
+ @staticmethod
72
+
73
+ @staticmethod
74
+
75
+ @staticmethod
76
+
77
+ @staticmethod
78
+
79
+ @staticmethod
80
+ def _deep_merge(base_dict: Dict[str, Any], update_dict: Dict[str, Any]) -> None:
81
+ """
82
+ Deep merge two dictionaries.
83
+
84
+ Args:
85
+ base_dict: Base dictionary to update
86
+ update_dict: Dictionary with updates
87
+ """
88
+ for key, value in update_dict.items():
89
+ if (
90
+ key in base_dict
91
+ and isinstance(base_dict[key], dict)
92
+ and isinstance(value, dict)
93
+ ):
94
+ SecurityFactory._deep_merge(base_dict[key], value)
95
+ else:
96
+ base_dict[key] = value