mcp-proxy-adapter 4.1.1__py3-none-any.whl → 6.1.0__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 (253) hide show
  1. mcp_proxy_adapter/__main__.py +12 -0
  2. mcp_proxy_adapter/api/app.py +254 -33
  3. mcp_proxy_adapter/api/handlers.py +32 -6
  4. mcp_proxy_adapter/api/middleware/__init__.py +36 -30
  5. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
  6. mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
  7. mcp_proxy_adapter/api/middleware/factory.py +243 -0
  8. mcp_proxy_adapter/api/middleware/logging.py +32 -6
  9. mcp_proxy_adapter/api/middleware/protocol_middleware.py +135 -0
  10. mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
  11. mcp_proxy_adapter/api/middleware/unified_security.py +152 -0
  12. mcp_proxy_adapter/api/middleware/user_info_middleware.py +83 -0
  13. mcp_proxy_adapter/commands/__init__.py +19 -4
  14. mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
  15. mcp_proxy_adapter/commands/base.py +66 -32
  16. mcp_proxy_adapter/commands/builtin_commands.py +95 -0
  17. mcp_proxy_adapter/commands/catalog_manager.py +838 -0
  18. mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
  19. mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
  20. mcp_proxy_adapter/commands/command_registry.py +711 -354
  21. mcp_proxy_adapter/commands/dependency_manager.py +245 -0
  22. mcp_proxy_adapter/commands/echo_command.py +81 -0
  23. mcp_proxy_adapter/commands/health_command.py +7 -0
  24. mcp_proxy_adapter/commands/help_command.py +21 -14
  25. mcp_proxy_adapter/commands/hooks.py +200 -167
  26. mcp_proxy_adapter/commands/key_management_command.py +506 -0
  27. mcp_proxy_adapter/commands/load_command.py +176 -0
  28. mcp_proxy_adapter/commands/plugins_command.py +235 -0
  29. mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
  30. mcp_proxy_adapter/commands/proxy_registration_command.py +409 -0
  31. mcp_proxy_adapter/commands/reload_command.py +48 -50
  32. mcp_proxy_adapter/commands/result.py +1 -0
  33. mcp_proxy_adapter/commands/role_test_command.py +141 -0
  34. mcp_proxy_adapter/commands/roles_management_command.py +697 -0
  35. mcp_proxy_adapter/commands/security_command.py +488 -0
  36. mcp_proxy_adapter/commands/ssl_setup_command.py +483 -0
  37. mcp_proxy_adapter/commands/token_management_command.py +529 -0
  38. mcp_proxy_adapter/commands/transport_management_command.py +144 -0
  39. mcp_proxy_adapter/commands/unload_command.py +158 -0
  40. mcp_proxy_adapter/config.py +159 -2
  41. mcp_proxy_adapter/core/app_factory.py +326 -0
  42. mcp_proxy_adapter/core/auth_validator.py +606 -0
  43. mcp_proxy_adapter/core/certificate_utils.py +827 -0
  44. mcp_proxy_adapter/core/client_security.py +384 -0
  45. mcp_proxy_adapter/core/config_converter.py +405 -0
  46. mcp_proxy_adapter/core/config_validator.py +218 -0
  47. mcp_proxy_adapter/core/logging.py +19 -3
  48. mcp_proxy_adapter/core/mtls_asgi.py +156 -0
  49. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  50. mcp_proxy_adapter/core/protocol_manager.py +235 -0
  51. mcp_proxy_adapter/core/proxy_client.py +602 -0
  52. mcp_proxy_adapter/core/proxy_registration.py +522 -0
  53. mcp_proxy_adapter/core/role_utils.py +426 -0
  54. mcp_proxy_adapter/core/security_adapter.py +370 -0
  55. mcp_proxy_adapter/core/security_factory.py +239 -0
  56. mcp_proxy_adapter/core/security_integration.py +277 -0
  57. mcp_proxy_adapter/core/server_adapter.py +345 -0
  58. mcp_proxy_adapter/core/server_engine.py +364 -0
  59. mcp_proxy_adapter/core/settings.py +1 -0
  60. mcp_proxy_adapter/core/ssl_utils.py +233 -0
  61. mcp_proxy_adapter/core/transport_manager.py +292 -0
  62. mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
  63. mcp_proxy_adapter/custom_openapi.py +22 -11
  64. mcp_proxy_adapter/examples/README.md +230 -97
  65. mcp_proxy_adapter/examples/README_EN.md +258 -0
  66. mcp_proxy_adapter/examples/SECURITY_TESTING.md +455 -0
  67. mcp_proxy_adapter/examples/__pycache__/security_configurations.cpython-312.pyc +0 -0
  68. mcp_proxy_adapter/examples/__pycache__/security_test_client.cpython-312.pyc +0 -0
  69. mcp_proxy_adapter/examples/basic_framework/configs/http_auth.json +37 -0
  70. mcp_proxy_adapter/examples/basic_framework/configs/http_simple.json +23 -0
  71. mcp_proxy_adapter/examples/basic_framework/configs/https_auth.json +39 -0
  72. mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +25 -0
  73. mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +39 -0
  74. mcp_proxy_adapter/examples/basic_framework/configs/mtls_with_roles.json +45 -0
  75. mcp_proxy_adapter/examples/basic_framework/main.py +63 -0
  76. mcp_proxy_adapter/examples/basic_framework/roles.json +21 -0
  77. mcp_proxy_adapter/examples/cert_config.json +9 -0
  78. mcp_proxy_adapter/examples/certs/admin.crt +32 -0
  79. mcp_proxy_adapter/examples/certs/admin.key +52 -0
  80. mcp_proxy_adapter/examples/certs/admin_cert.pem +21 -0
  81. mcp_proxy_adapter/examples/certs/admin_key.pem +28 -0
  82. mcp_proxy_adapter/examples/certs/ca_cert.pem +23 -0
  83. mcp_proxy_adapter/examples/certs/ca_cert.srl +1 -0
  84. mcp_proxy_adapter/examples/certs/ca_key.pem +28 -0
  85. mcp_proxy_adapter/examples/certs/cert_config.json +9 -0
  86. mcp_proxy_adapter/examples/certs/client.crt +32 -0
  87. mcp_proxy_adapter/examples/certs/client.key +52 -0
  88. mcp_proxy_adapter/examples/certs/client_admin.crt +32 -0
  89. mcp_proxy_adapter/examples/certs/client_admin.key +52 -0
  90. mcp_proxy_adapter/examples/certs/client_user.crt +32 -0
  91. mcp_proxy_adapter/examples/certs/client_user.key +52 -0
  92. mcp_proxy_adapter/examples/certs/guest_cert.pem +21 -0
  93. mcp_proxy_adapter/examples/certs/guest_key.pem +28 -0
  94. mcp_proxy_adapter/examples/certs/mcp_proxy_adapter_ca_ca.crt +23 -0
  95. mcp_proxy_adapter/examples/certs/proxy_cert.pem +21 -0
  96. mcp_proxy_adapter/examples/certs/proxy_key.pem +28 -0
  97. mcp_proxy_adapter/examples/certs/readonly.crt +32 -0
  98. mcp_proxy_adapter/examples/certs/readonly.key +52 -0
  99. mcp_proxy_adapter/examples/certs/readonly_cert.pem +21 -0
  100. mcp_proxy_adapter/examples/certs/readonly_key.pem +28 -0
  101. mcp_proxy_adapter/examples/certs/server.crt +32 -0
  102. mcp_proxy_adapter/examples/certs/server.key +52 -0
  103. mcp_proxy_adapter/examples/certs/server_cert.pem +32 -0
  104. mcp_proxy_adapter/examples/certs/server_key.pem +52 -0
  105. mcp_proxy_adapter/examples/certs/test_ca_ca.crt +20 -0
  106. mcp_proxy_adapter/examples/certs/user.crt +32 -0
  107. mcp_proxy_adapter/examples/certs/user.key +52 -0
  108. mcp_proxy_adapter/examples/certs/user_cert.pem +21 -0
  109. mcp_proxy_adapter/examples/certs/user_key.pem +28 -0
  110. mcp_proxy_adapter/examples/client_configs/api_key_client.json +13 -0
  111. mcp_proxy_adapter/examples/client_configs/basic_auth_client.json +13 -0
  112. mcp_proxy_adapter/examples/client_configs/certificate_client.json +22 -0
  113. mcp_proxy_adapter/examples/client_configs/jwt_client.json +15 -0
  114. mcp_proxy_adapter/examples/client_configs/no_auth_client.json +9 -0
  115. mcp_proxy_adapter/examples/commands/__init__.py +1 -0
  116. mcp_proxy_adapter/examples/create_certificates_simple.py +307 -0
  117. mcp_proxy_adapter/examples/debug_request_state.py +144 -0
  118. mcp_proxy_adapter/examples/debug_role_chain.py +205 -0
  119. mcp_proxy_adapter/examples/demo_client.py +341 -0
  120. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +99 -0
  121. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +106 -0
  122. mcp_proxy_adapter/examples/full_application/configs/http_auth.json +37 -0
  123. mcp_proxy_adapter/examples/full_application/configs/http_simple.json +23 -0
  124. mcp_proxy_adapter/examples/full_application/configs/https_auth.json +39 -0
  125. mcp_proxy_adapter/examples/full_application/configs/https_simple.json +25 -0
  126. mcp_proxy_adapter/examples/full_application/configs/mtls_no_roles.json +39 -0
  127. mcp_proxy_adapter/examples/full_application/configs/mtls_with_roles.json +45 -0
  128. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +97 -0
  129. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +95 -0
  130. mcp_proxy_adapter/examples/full_application/main.py +138 -0
  131. mcp_proxy_adapter/examples/full_application/roles.json +21 -0
  132. mcp_proxy_adapter/examples/generate_all_certificates.py +429 -0
  133. mcp_proxy_adapter/examples/generate_certificates.py +121 -0
  134. mcp_proxy_adapter/examples/keys/ca_key.pem +28 -0
  135. mcp_proxy_adapter/examples/keys/mcp_proxy_adapter_ca_ca.key +28 -0
  136. mcp_proxy_adapter/examples/keys/test_ca_ca.key +28 -0
  137. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log +220 -0
  138. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.1 +1 -0
  139. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.2 +1 -0
  140. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.3 +1 -0
  141. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.4 +1 -0
  142. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.5 +1 -0
  143. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log +220 -0
  144. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.1 +1 -0
  145. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.2 +1 -0
  146. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.3 +1 -0
  147. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.4 +1 -0
  148. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.5 +1 -0
  149. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log +2 -0
  150. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.1 +1 -0
  151. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.2 +1 -0
  152. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.3 +1 -0
  153. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.4 +1 -0
  154. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.5 +1 -0
  155. mcp_proxy_adapter/examples/proxy_registration_example.py +401 -0
  156. mcp_proxy_adapter/examples/roles.json +38 -0
  157. mcp_proxy_adapter/examples/run_example.py +81 -0
  158. mcp_proxy_adapter/examples/run_security_tests.py +326 -0
  159. mcp_proxy_adapter/examples/run_security_tests_fixed.py +300 -0
  160. mcp_proxy_adapter/examples/security_test_client.py +743 -0
  161. mcp_proxy_adapter/examples/server_configs/config_basic_http.json +204 -0
  162. mcp_proxy_adapter/examples/server_configs/config_http_token.json +238 -0
  163. mcp_proxy_adapter/examples/server_configs/config_https.json +215 -0
  164. mcp_proxy_adapter/examples/server_configs/config_https_token.json +231 -0
  165. mcp_proxy_adapter/examples/server_configs/config_mtls.json +215 -0
  166. mcp_proxy_adapter/examples/server_configs/config_proxy_registration.json +250 -0
  167. mcp_proxy_adapter/examples/server_configs/config_simple.json +46 -0
  168. mcp_proxy_adapter/examples/server_configs/roles.json +38 -0
  169. mcp_proxy_adapter/examples/test_examples.py +344 -0
  170. mcp_proxy_adapter/examples/universal_client.py +628 -0
  171. mcp_proxy_adapter/main.py +186 -0
  172. mcp_proxy_adapter/utils/config_generator.py +639 -0
  173. mcp_proxy_adapter/version.py +2 -1
  174. mcp_proxy_adapter-6.1.0.dist-info/METADATA +205 -0
  175. mcp_proxy_adapter-6.1.0.dist-info/RECORD +193 -0
  176. mcp_proxy_adapter-6.1.0.dist-info/entry_points.txt +2 -0
  177. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.1.0.dist-info}/licenses/LICENSE +2 -2
  178. mcp_proxy_adapter/api/middleware/auth.py +0 -146
  179. mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
  180. mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
  181. mcp_proxy_adapter/examples/__init__.py +0 -7
  182. mcp_proxy_adapter/examples/basic_server/README.md +0 -60
  183. mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
  184. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
  185. mcp_proxy_adapter/examples/basic_server/config.json +0 -35
  186. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
  187. mcp_proxy_adapter/examples/basic_server/server.py +0 -103
  188. mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
  189. mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
  190. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -250
  191. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
  192. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
  193. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
  194. mcp_proxy_adapter/examples/custom_commands/config.json +0 -35
  195. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
  196. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
  197. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
  198. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
  199. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
  200. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
  201. mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
  202. mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
  203. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
  204. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
  205. mcp_proxy_adapter/examples/custom_commands/server.py +0 -228
  206. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
  207. mcp_proxy_adapter/examples/deployment/README.md +0 -49
  208. mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
  209. mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
  210. mcp_proxy_adapter/examples/deployment/config.json +0 -29
  211. mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
  212. mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
  213. mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
  214. mcp_proxy_adapter/examples/deployment/run.sh +0 -43
  215. mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
  216. mcp_proxy_adapter/schemas/base_schema.json +0 -114
  217. mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
  218. mcp_proxy_adapter/tests/__init__.py +0 -0
  219. mcp_proxy_adapter/tests/api/__init__.py +0 -3
  220. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
  221. mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
  222. mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
  223. mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
  224. mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
  225. mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
  226. mcp_proxy_adapter/tests/commands/__init__.py +0 -3
  227. mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
  228. mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
  229. mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
  230. mcp_proxy_adapter/tests/conftest.py +0 -131
  231. mcp_proxy_adapter/tests/functional/__init__.py +0 -3
  232. mcp_proxy_adapter/tests/functional/test_api.py +0 -253
  233. mcp_proxy_adapter/tests/integration/__init__.py +0 -3
  234. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
  235. mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
  236. mcp_proxy_adapter/tests/performance/__init__.py +0 -3
  237. mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
  238. mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
  239. mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
  240. mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
  241. mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
  242. mcp_proxy_adapter/tests/test_base_command.py +0 -123
  243. mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
  244. mcp_proxy_adapter/tests/test_command_registry.py +0 -281
  245. mcp_proxy_adapter/tests/test_config.py +0 -127
  246. mcp_proxy_adapter/tests/test_utils.py +0 -65
  247. mcp_proxy_adapter/tests/unit/__init__.py +0 -3
  248. mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
  249. mcp_proxy_adapter/tests/unit/test_config.py +0 -217
  250. mcp_proxy_adapter-4.1.1.dist-info/METADATA +0 -200
  251. mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
  252. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.1.0.dist-info}/WHEEL +0 -0
  253. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simple Certificate Creation Script
4
+
5
+ This script creates basic certificates for testing using OpenSSL directly.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ import os
12
+ import subprocess
13
+ import sys
14
+ from pathlib import Path
15
+
16
+
17
+ class SimpleCertificateCreator:
18
+ """Create certificates using OpenSSL directly."""
19
+
20
+ def __init__(self):
21
+ self.project_root = Path(__file__).parent.parent.parent
22
+ self.certs_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "certs"
23
+ self.keys_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "keys"
24
+
25
+ # Create directories
26
+ self.certs_dir.mkdir(parents=True, exist_ok=True)
27
+ self.keys_dir.mkdir(parents=True, exist_ok=True)
28
+
29
+ def run_command(self, cmd: list, description: str) -> bool:
30
+ """Run a command and handle errors."""
31
+ try:
32
+ print(f"🔧 {description}...")
33
+ result = subprocess.run(
34
+ cmd,
35
+ cwd=self.project_root,
36
+ capture_output=True,
37
+ text=True,
38
+ check=True
39
+ )
40
+ print(f"✅ {description} completed successfully")
41
+ return True
42
+ except subprocess.CalledProcessError as e:
43
+ print(f"❌ {description} failed:")
44
+ print(f" Command: {' '.join(cmd)}")
45
+ print(f" Error: {e.stderr}")
46
+ return False
47
+ except Exception as e:
48
+ print(f"❌ {description} failed: {e}")
49
+ return False
50
+
51
+ def create_ca_certificate(self) -> bool:
52
+ """Create CA certificate using OpenSSL."""
53
+ ca_cert_path = self.certs_dir / "ca_cert.pem"
54
+ ca_key_path = self.keys_dir / "ca_key.pem"
55
+
56
+ if ca_cert_path.exists() and ca_key_path.exists():
57
+ print(f"ℹ️ CA certificate already exists: {ca_cert_path}")
58
+ return True
59
+
60
+ # Create CA private key
61
+ key_cmd = [
62
+ "openssl", "genrsa", "-out", str(ca_key_path), "2048"
63
+ ]
64
+ if not self.run_command(key_cmd, "Creating CA private key"):
65
+ return False
66
+
67
+ # Create CA certificate
68
+ cert_cmd = [
69
+ "openssl", "req", "-new", "-x509", "-days", "3650",
70
+ "-key", str(ca_key_path),
71
+ "-out", str(ca_cert_path),
72
+ "-subj", "/C=US/ST=Test State/L=Test City/O=Test Organization/CN=MCP Proxy Adapter Test CA"
73
+ ]
74
+ return self.run_command(cert_cmd, "Creating CA certificate")
75
+
76
+ def create_server_certificate(self) -> bool:
77
+ """Create server certificate using OpenSSL."""
78
+ server_cert_path = self.certs_dir / "server_cert.pem"
79
+ server_key_path = self.certs_dir / "server_key.pem"
80
+
81
+ if server_cert_path.exists() and server_key_path.exists():
82
+ print(f"ℹ️ Server certificate already exists: {server_cert_path}")
83
+ return True
84
+
85
+ # Create server private key
86
+ key_cmd = [
87
+ "openssl", "genrsa", "-out", str(server_key_path), "2048"
88
+ ]
89
+ if not self.run_command(key_cmd, "Creating server private key"):
90
+ return False
91
+
92
+ # Create server certificate signing request
93
+ csr_path = self.certs_dir / "server.csr"
94
+ csr_cmd = [
95
+ "openssl", "req", "-new",
96
+ "-key", str(server_key_path),
97
+ "-out", str(csr_path),
98
+ "-subj", "/C=US/ST=Test State/L=Test City/O=Test Organization/CN=localhost"
99
+ ]
100
+ if not self.run_command(csr_cmd, "Creating server CSR"):
101
+ return False
102
+
103
+ # Create server certificate
104
+ cert_cmd = [
105
+ "openssl", "x509", "-req", "-days", "730",
106
+ "-in", str(csr_path),
107
+ "-CA", str(self.certs_dir / "ca_cert.pem"),
108
+ "-CAkey", str(self.keys_dir / "ca_key.pem"),
109
+ "-CAcreateserial",
110
+ "-out", str(server_cert_path)
111
+ ]
112
+ success = self.run_command(cert_cmd, "Creating server certificate")
113
+
114
+ # Clean up CSR
115
+ if csr_path.exists():
116
+ csr_path.unlink()
117
+
118
+ return success
119
+
120
+ def create_client_certificate(self, name: str, common_name: str) -> bool:
121
+ """Create client certificate using OpenSSL."""
122
+ cert_path = self.certs_dir / f"{name}_cert.pem"
123
+ key_path = self.certs_dir / f"{name}_key.pem"
124
+
125
+ if cert_path.exists() and key_path.exists():
126
+ print(f"ℹ️ Client certificate {name} already exists: {cert_path}")
127
+ return True
128
+
129
+ # Create client private key
130
+ key_cmd = [
131
+ "openssl", "genrsa", "-out", str(key_path), "2048"
132
+ ]
133
+ if not self.run_command(key_cmd, f"Creating {name} private key"):
134
+ return False
135
+
136
+ # Create client certificate signing request
137
+ csr_path = self.certs_dir / f"{name}.csr"
138
+ csr_cmd = [
139
+ "openssl", "req", "-new",
140
+ "-key", str(key_path),
141
+ "-out", str(csr_path),
142
+ "-subj", f"/C=US/ST=Test State/L=Test City/O=Test Organization/CN={common_name}"
143
+ ]
144
+ if not self.run_command(csr_cmd, f"Creating {name} CSR"):
145
+ return False
146
+
147
+ # Create client certificate
148
+ cert_cmd = [
149
+ "openssl", "x509", "-req", "-days", "730",
150
+ "-in", str(csr_path),
151
+ "-CA", str(self.certs_dir / "ca_cert.pem"),
152
+ "-CAkey", str(self.keys_dir / "ca_key.pem"),
153
+ "-CAcreateserial",
154
+ "-out", str(cert_path)
155
+ ]
156
+ success = self.run_command(cert_cmd, f"Creating {name} certificate")
157
+
158
+ # Clean up CSR
159
+ if csr_path.exists():
160
+ csr_path.unlink()
161
+
162
+ return success
163
+
164
+ def create_legacy_certificates(self) -> bool:
165
+ """Create legacy certificate files for compatibility."""
166
+ legacy_files = [
167
+ ("client.crt", "client.key", "client"),
168
+ ("client_admin.crt", "client_admin.key", "admin"),
169
+ ("admin.crt", "admin.key", "admin"),
170
+ ("user.crt", "user.key", "user"),
171
+ ("readonly.crt", "readonly.key", "readonly")
172
+ ]
173
+
174
+ success = True
175
+ for cert_file, key_file, source_name in legacy_files:
176
+ cert_path = self.certs_dir / cert_file
177
+ key_path = self.certs_dir / key_file
178
+
179
+ if not cert_path.exists() or not key_path.exists():
180
+ source_cert = self.certs_dir / f"{source_name}_cert.pem"
181
+ source_key = self.certs_dir / f"{source_name}_key.pem"
182
+
183
+ if source_cert.exists() and source_key.exists():
184
+ self.run_command(["cp", str(source_cert), str(cert_path)], f"Creating {cert_file}")
185
+ self.run_command(["cp", str(source_key), str(key_path)], f"Creating {key_file}")
186
+ else:
187
+ print(f"⚠️ Source certificate {source_name} not found for {cert_file}")
188
+ success = False
189
+
190
+ return success
191
+
192
+ def validate_certificates(self) -> bool:
193
+ """Validate all created certificates."""
194
+ print("\n🔍 Validating certificates...")
195
+
196
+ cert_files = [
197
+ "ca_cert.pem",
198
+ "server_cert.pem",
199
+ "admin_cert.pem",
200
+ "user_cert.pem",
201
+ "readonly_cert.pem",
202
+ "guest_cert.pem",
203
+ "proxy_cert.pem"
204
+ ]
205
+
206
+ success = True
207
+ for cert_file in cert_files:
208
+ cert_path = self.certs_dir / cert_file
209
+ if cert_path.exists():
210
+ try:
211
+ result = subprocess.run(
212
+ ["openssl", "x509", "-in", str(cert_path), "-text", "-noout"],
213
+ capture_output=True,
214
+ text=True,
215
+ check=True
216
+ )
217
+ print(f"✅ {cert_file}: Valid")
218
+ except subprocess.CalledProcessError:
219
+ print(f"❌ {cert_file}: Invalid")
220
+ success = False
221
+ else:
222
+ print(f"⚠️ {cert_file}: Not found")
223
+
224
+ return success
225
+
226
+ def create_all(self) -> bool:
227
+ """Create all certificates."""
228
+ print("🔐 Creating All Certificates for Security Testing")
229
+ print("=" * 60)
230
+
231
+ success = True
232
+
233
+ # 1. Create CA certificate
234
+ if not self.create_ca_certificate():
235
+ success = False
236
+ print("❌ Cannot continue without CA certificate")
237
+ return False
238
+
239
+ # 2. Create server certificate
240
+ if not self.create_server_certificate():
241
+ success = False
242
+
243
+ # 3. Create client certificates
244
+ print("\n👥 Creating client certificates...")
245
+ client_certs = [
246
+ ("admin", "admin-client"),
247
+ ("user", "user-client"),
248
+ ("readonly", "readonly-client"),
249
+ ("guest", "guest-client"),
250
+ ("proxy", "proxy-client")
251
+ ]
252
+
253
+ for name, common_name in client_certs:
254
+ if not self.create_client_certificate(name, common_name):
255
+ success = False
256
+
257
+ # 4. Create legacy certificates
258
+ print("\n🔄 Creating legacy certificates...")
259
+ if not self.create_legacy_certificates():
260
+ success = False
261
+
262
+ # 5. Validate certificates
263
+ if not self.validate_certificates():
264
+ success = False
265
+
266
+ # Print summary
267
+ print("\n" + "=" * 60)
268
+ print("📊 CERTIFICATE CREATION SUMMARY")
269
+ print("=" * 60)
270
+
271
+ if success:
272
+ print("✅ All certificates created successfully!")
273
+ print(f"📁 Certificates directory: {self.certs_dir}")
274
+ print(f"🔑 Keys directory: {self.keys_dir}")
275
+ print("\n📋 Created certificates:")
276
+
277
+ cert_files = list(self.certs_dir.glob("*.pem")) + list(self.certs_dir.glob("*.crt"))
278
+ for cert_file in sorted(cert_files):
279
+ print(f" - {cert_file.name}")
280
+
281
+ key_files = list(self.keys_dir.glob("*.pem")) + list(self.keys_dir.glob("*.key"))
282
+ for key_file in sorted(key_files):
283
+ print(f" - {key_file.name}")
284
+ else:
285
+ print("❌ Some certificates failed to create")
286
+ print("Check the error messages above")
287
+
288
+ return success
289
+
290
+
291
+ def main():
292
+ """Main function."""
293
+ creator = SimpleCertificateCreator()
294
+
295
+ try:
296
+ success = creator.create_all()
297
+ sys.exit(0 if success else 1)
298
+ except KeyboardInterrupt:
299
+ print("\n⚠️ Certificate creation interrupted by user")
300
+ sys.exit(1)
301
+ except Exception as e:
302
+ print(f"\n❌ Certificate creation failed: {e}")
303
+ sys.exit(1)
304
+
305
+
306
+ if __name__ == "__main__":
307
+ main()
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Debug Request State - Проверка request.state
4
+
5
+ Этот скрипт проверяет, как middleware устанавливает информацию о пользователе в request.state.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ import asyncio
12
+ import json
13
+ import sys
14
+ from pathlib import Path
15
+
16
+ # Add project root to path
17
+ project_root = Path(__file__).parent.parent.parent
18
+ sys.path.insert(0, str(project_root))
19
+
20
+ from fastapi import FastAPI, Request
21
+ from fastapi.testclient import TestClient
22
+ from mcp_proxy_adapter.api.app import create_app
23
+
24
+
25
+ async def debug_request_state():
26
+ """Debug request state handling."""
27
+
28
+ print("🔍 ОТЛАДКА REQUEST.STATE")
29
+ print("=" * 50)
30
+
31
+ # Create test app with proper configuration
32
+ config_path = project_root / "mcp_proxy_adapter" / "examples" / "server_configs" / "config_http_token.json"
33
+
34
+ with open(config_path) as f:
35
+ config = json.load(f)
36
+
37
+ # Override global config for testing
38
+ import mcp_proxy_adapter.config
39
+ mcp_proxy_adapter.config.config = config
40
+
41
+ app = create_app(config)
42
+ client = TestClient(app)
43
+
44
+ print("📋 1. ТЕСТИРОВАНИЕ БЕЗ АУТЕНТИФИКАЦИИ")
45
+ print("-" * 30)
46
+
47
+ # Test without authentication
48
+ response = client.post("/cmd", json={
49
+ "jsonrpc": "2.0",
50
+ "method": "echo",
51
+ "params": {"message": "test"},
52
+ "id": 1
53
+ })
54
+
55
+ print(f"Status: {response.status_code}")
56
+ print(f"Response: {response.json()}")
57
+
58
+ print("\n📋 2. ТЕСТИРОВАНИЕ С ADMIN ТОКЕНОМ")
59
+ print("-" * 30)
60
+
61
+ # Test with admin token
62
+ response = client.post("/cmd",
63
+ json={
64
+ "jsonrpc": "2.0",
65
+ "method": "echo",
66
+ "params": {"message": "test"},
67
+ "id": 1
68
+ },
69
+ headers={"X-API-Key": "test-token-123"}
70
+ )
71
+
72
+ print(f"Status: {response.status_code}")
73
+ print(f"Response: {response.json()}")
74
+
75
+ print("\n📋 3. ТЕСТИРОВАНИЕ С USER ТОКЕНОМ")
76
+ print("-" * 30)
77
+
78
+ # Test with user token
79
+ response = client.post("/cmd",
80
+ json={
81
+ "jsonrpc": "2.0",
82
+ "method": "echo",
83
+ "params": {"message": "test"},
84
+ "id": 1
85
+ },
86
+ headers={"X-API-Key": "user-token-456"}
87
+ )
88
+
89
+ print(f"Status: {response.status_code}")
90
+ print(f"Response: {response.json()}")
91
+
92
+ print("\n📋 4. ТЕСТИРОВАНИЕ С READONLY ТОКЕНОМ")
93
+ print("-" * 30)
94
+
95
+ # Test with readonly token
96
+ response = client.post("/cmd",
97
+ json={
98
+ "jsonrpc": "2.0",
99
+ "method": "echo",
100
+ "params": {"message": "test"},
101
+ "id": 1
102
+ },
103
+ headers={"X-API-Key": "readonly-token-123"}
104
+ )
105
+
106
+ print(f"Status: {response.status_code}")
107
+ print(f"Response: {response.json()}")
108
+
109
+ print("\n📋 5. ТЕСТИРОВАНИЕ ROLE_TEST КОМАНДЫ")
110
+ print("-" * 30)
111
+
112
+ # Test role_test command with readonly token
113
+ response = client.post("/cmd",
114
+ json={
115
+ "jsonrpc": "2.0",
116
+ "method": "role_test",
117
+ "params": {"action": "write"},
118
+ "id": 1
119
+ },
120
+ headers={"X-API-Key": "readonly-token-123"}
121
+ )
122
+
123
+ print(f"Status: {response.status_code}")
124
+ print(f"Response: {response.json()}")
125
+
126
+ print("\n📋 6. АНАЛИЗ ПРОБЛЕМЫ")
127
+ print("-" * 30)
128
+
129
+ print("🔍 ПРОБЛЕМА: Readonly роль получает доступ к командам")
130
+ print("\n📋 ВОЗМОЖНЫЕ ПРИЧИНЫ:")
131
+ print("1. Framework middleware не устанавливает user info в request.state")
132
+ print("2. Нет проверки прав на уровне middleware")
133
+ print("3. Команды не проверяют права доступа")
134
+ print("4. Интеграция между middleware и командами не работает")
135
+
136
+ print("\n📋 РЕКОМЕНДАЦИИ:")
137
+ print("1. Добавить CommandPermissionMiddleware")
138
+ print("2. Убедиться, что framework middleware устанавливает user info")
139
+ print("3. Добавить проверку прав в команды")
140
+ print("4. Проверить интеграцию middleware")
141
+
142
+
143
+ if __name__ == "__main__":
144
+ asyncio.run(debug_request_state())
@@ -0,0 +1,205 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Debug Role Chain - Анализ цепочки блокировки ролей
4
+
5
+ Этот скрипт анализирует всю цепочку от аутентификации до блокировки доступа.
6
+
7
+ Author: Vasiliy Zdanovskiy
8
+ email: vasilyvz@gmail.com
9
+ """
10
+
11
+ import asyncio
12
+ import json
13
+ import sys
14
+ from pathlib import Path
15
+
16
+ # Add project root to path
17
+ project_root = Path(__file__).parent.parent.parent
18
+ sys.path.insert(0, str(project_root))
19
+
20
+ from mcp_security_framework import SecurityManager, AuthManager, PermissionManager
21
+ from mcp_security_framework.schemas.config import SecurityConfig, AuthConfig, PermissionConfig
22
+
23
+
24
+ async def debug_role_chain():
25
+ """Debug the complete role chain from authentication to blocking."""
26
+
27
+ print("🔍 АНАЛИЗ ЦЕПОЧКИ БЛОКИРОВКИ РОЛЕЙ")
28
+ print("=" * 60)
29
+
30
+ # Load configuration
31
+ config_path = project_root / "mcp_proxy_adapter" / "examples" / "server_configs" / "config_http_token.json"
32
+
33
+ with open(config_path) as f:
34
+ config = json.load(f)
35
+
36
+ security_config = config.get("security", {})
37
+
38
+ print("📋 1. КОНФИГУРАЦИЯ API КЛЮЧЕЙ")
39
+ print("-" * 30)
40
+ api_keys = security_config.get("auth", {}).get("api_keys", {})
41
+ for key, value in api_keys.items():
42
+ print(f" {key}: {value}")
43
+
44
+ print("\n📋 2. КОНФИГУРАЦИЯ РОЛЕЙ")
45
+ print("-" * 30)
46
+ roles_config = security_config.get("permissions", {}).get("roles", {})
47
+ for role, permissions in roles_config.items():
48
+ print(f" {role}: {permissions}")
49
+
50
+ print("\n📋 3. СОЗДАНИЕ КОМПОНЕНТОВ БЕЗОПАСНОСТИ")
51
+ print("-" * 30)
52
+
53
+ # Create permission config
54
+ perm_config = PermissionConfig(
55
+ roles_file=str(project_root / "mcp_proxy_adapter" / "examples" / "server_configs" / "roles.json"),
56
+ default_role="guest",
57
+ admin_role="admin",
58
+ role_hierarchy=security_config.get("permissions", {}).get("role_hierarchy", {}),
59
+ permission_cache_enabled=True,
60
+ permission_cache_ttl=300,
61
+ wildcard_permissions=False,
62
+ strict_mode=True,
63
+ roles=roles_config
64
+ )
65
+
66
+ # Create auth config
67
+ auth_config = AuthConfig(
68
+ enabled=security_config.get("auth", {}).get("enabled", True),
69
+ methods=security_config.get("auth", {}).get("methods", ["api_key"]),
70
+ api_keys=api_keys,
71
+ user_roles=security_config.get("auth", {}).get("user_roles", {}),
72
+ jwt_secret=security_config.get("auth", {}).get("jwt_secret"),
73
+ jwt_algorithm=security_config.get("auth", {}).get("jwt_algorithm", "HS256"),
74
+ jwt_expiry_hours=security_config.get("auth", {}).get("jwt_expiry_hours", 24),
75
+ certificate_auth=security_config.get("auth", {}).get("certificate_auth", False),
76
+ certificate_roles_oid=security_config.get("auth", {}).get("certificate_roles_oid"),
77
+ certificate_permissions_oid=security_config.get("auth", {}).get("certificate_permissions_oid"),
78
+ basic_auth=security_config.get("auth", {}).get("basic_auth", False),
79
+ oauth2_config=security_config.get("auth", {}).get("oauth2_config"),
80
+ public_paths=security_config.get("auth", {}).get("public_paths", [])
81
+ )
82
+
83
+ # Create security config
84
+ security_config_obj = SecurityConfig(
85
+ auth=auth_config,
86
+ permissions=perm_config
87
+ )
88
+
89
+ print("✅ Конфигурации созданы")
90
+
91
+ print("\n📋 4. ИНИЦИАЛИЗАЦИЯ МЕНЕДЖЕРОВ")
92
+ print("-" * 30)
93
+
94
+ # Initialize managers
95
+ permission_manager = PermissionManager(perm_config)
96
+ auth_manager = AuthManager(auth_config, permission_manager)
97
+ security_manager = SecurityManager(security_config_obj)
98
+
99
+ print("✅ Менеджеры инициализированы")
100
+
101
+ print("\n📋 5. ТЕСТИРОВАНИЕ АУТЕНТИФИКАЦИИ")
102
+ print("-" * 30)
103
+
104
+ # Test authentication with different tokens
105
+ test_tokens = {
106
+ "admin": "test-token-123",
107
+ "user": "user-token-456",
108
+ "readonly": "readonly-token-123",
109
+ "invalid": "invalid-token-999"
110
+ }
111
+
112
+ auth_results = {}
113
+
114
+ for role, token in test_tokens.items():
115
+ print(f"\n🔐 Тестирование токена для роли '{role}': {token}")
116
+
117
+ try:
118
+ result = auth_manager.authenticate_api_key(token)
119
+ auth_results[role] = result
120
+
121
+ print(f" ✅ Аутентификация: {'УСПЕШНА' if result.is_valid else 'НЕУДАЧНА'}")
122
+ if result.is_valid:
123
+ print(f" 👤 Пользователь: {result.username}")
124
+ print(f" 🏷️ Роли: {result.roles}")
125
+ print(f" 🔑 Метод: {result.auth_method}")
126
+ else:
127
+ print(f" ❌ Ошибка: {result.error_message}")
128
+
129
+ except Exception as e:
130
+ print(f" ❌ Исключение: {e}")
131
+ auth_results[role] = None
132
+
133
+ print("\n📋 6. ТЕСТИРОВАНИЕ ПРАВ ДОСТУПА")
134
+ print("-" * 30)
135
+
136
+ # Test permissions for different actions
137
+ test_actions = ["read", "write", "manage", "delete"]
138
+
139
+ for role, auth_result in auth_results.items():
140
+ if auth_result and auth_result.is_valid:
141
+ print(f"\n🔒 Тестирование прав для роли '{role}' (роли: {auth_result.roles})")
142
+
143
+ for action in test_actions:
144
+ try:
145
+ # Check permissions using permission manager
146
+ validation_result = permission_manager.validate_access(
147
+ auth_result.roles,
148
+ [action]
149
+ )
150
+
151
+ status = "✅ РАЗРЕШЕНО" if validation_result.is_valid else "❌ ЗАБЛОКИРОВАНО"
152
+ print(f" {action}: {status}")
153
+
154
+ if not validation_result.is_valid:
155
+ print(f" 📝 Причина: {validation_result.error_message}")
156
+ print(f" 🎯 Эффективные права: {validation_result.effective_permissions}")
157
+ print(f" ❌ Отсутствующие права: {validation_result.missing_permissions}")
158
+
159
+ except Exception as e:
160
+ print(f" {action}: ❌ ОШИБКА - {e}")
161
+
162
+ print("\n📋 7. ТЕСТИРОВАНИЕ ПОЛНОЙ ЦЕПОЧКИ")
163
+ print("-" * 30)
164
+
165
+ # Test complete request validation
166
+ for role, token in test_tokens.items():
167
+ print(f"\n🔄 Полная цепочка для роли '{role}'")
168
+
169
+ request_data = {
170
+ "api_key": token,
171
+ "required_permissions": ["write"],
172
+ "client_ip": "127.0.0.1"
173
+ }
174
+
175
+ try:
176
+ result = security_manager.validate_request(request_data)
177
+
178
+ status = "✅ УСПЕШНО" if result.is_valid else "❌ ЗАБЛОКИРОВАНО"
179
+ print(f" Результат: {status}")
180
+
181
+ if not result.is_valid:
182
+ print(f" 📝 Причина: {result.error_message}")
183
+
184
+ except Exception as e:
185
+ print(f" ❌ ОШИБКА: {e}")
186
+
187
+ print("\n📋 8. АНАЛИЗ ПРОБЛЕМЫ")
188
+ print("-" * 30)
189
+
190
+ print("🔍 ПРОБЛЕМА: Readonly роль получает доступ к write операциям")
191
+ print("\n📋 ВОЗМОЖНЫЕ ПРИЧИНЫ:")
192
+ print("1. Middleware не передает информацию о пользователе в request.state")
193
+ print("2. Framework middleware не блокирует доступ на уровне middleware")
194
+ print("3. Команда role_test не получает правильный контекст пользователя")
195
+ print("4. Интеграция между middleware и командами не работает")
196
+
197
+ print("\n📋 РЕКОМЕНДАЦИИ:")
198
+ print("1. Проверить, как framework middleware устанавливает user info")
199
+ print("2. Добавить проверку прав на уровне middleware")
200
+ print("3. Убедиться, что request.state содержит user info")
201
+ print("4. Проверить интеграцию между middleware и командами")
202
+
203
+
204
+ if __name__ == "__main__":
205
+ asyncio.run(debug_role_chain())