mcp-proxy-adapter 6.0.0__py3-none-any.whl → 6.1.1__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 (264) hide show
  1. mcp_proxy_adapter/api/app.py +174 -80
  2. mcp_proxy_adapter/api/handlers.py +16 -5
  3. mcp_proxy_adapter/api/middleware/__init__.py +9 -4
  4. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
  5. mcp_proxy_adapter/api/middleware/factory.py +36 -12
  6. mcp_proxy_adapter/api/middleware/protocol_middleware.py +32 -13
  7. mcp_proxy_adapter/api/middleware/unified_security.py +160 -0
  8. mcp_proxy_adapter/api/middleware/user_info_middleware.py +83 -0
  9. mcp_proxy_adapter/commands/__init__.py +7 -1
  10. mcp_proxy_adapter/commands/base.py +7 -4
  11. mcp_proxy_adapter/commands/builtin_commands.py +8 -2
  12. mcp_proxy_adapter/commands/command_registry.py +8 -0
  13. mcp_proxy_adapter/commands/echo_command.py +81 -0
  14. mcp_proxy_adapter/commands/help_command.py +21 -14
  15. mcp_proxy_adapter/commands/proxy_registration_command.py +326 -185
  16. mcp_proxy_adapter/commands/role_test_command.py +141 -0
  17. mcp_proxy_adapter/commands/security_command.py +488 -0
  18. mcp_proxy_adapter/commands/ssl_setup_command.py +2 -2
  19. mcp_proxy_adapter/commands/token_management_command.py +1 -1
  20. mcp_proxy_adapter/config.py +81 -21
  21. mcp_proxy_adapter/core/app_factory.py +326 -0
  22. mcp_proxy_adapter/core/client_security.py +384 -0
  23. mcp_proxy_adapter/core/logging.py +8 -3
  24. mcp_proxy_adapter/core/mtls_asgi.py +156 -0
  25. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  26. mcp_proxy_adapter/core/protocol_manager.py +139 -8
  27. mcp_proxy_adapter/core/proxy_client.py +602 -0
  28. mcp_proxy_adapter/core/proxy_registration.py +299 -47
  29. mcp_proxy_adapter/core/security_adapter.py +12 -15
  30. mcp_proxy_adapter/core/security_integration.py +285 -0
  31. mcp_proxy_adapter/core/server_adapter.py +345 -0
  32. mcp_proxy_adapter/core/server_engine.py +364 -0
  33. mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
  34. mcp_proxy_adapter/docs/EN/TROUBLESHOOTING.md +285 -0
  35. mcp_proxy_adapter/docs/RU/TROUBLESHOOTING.md +285 -0
  36. mcp_proxy_adapter/examples/README.md +230 -97
  37. mcp_proxy_adapter/examples/README_EN.md +258 -0
  38. mcp_proxy_adapter/examples/SECURITY_TESTING.md +455 -0
  39. mcp_proxy_adapter/examples/basic_framework/configs/http_auth.json +37 -0
  40. mcp_proxy_adapter/examples/basic_framework/configs/http_simple.json +23 -0
  41. mcp_proxy_adapter/examples/basic_framework/configs/https_auth.json +43 -0
  42. mcp_proxy_adapter/examples/basic_framework/configs/https_no_protocol_middleware.json +36 -0
  43. mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +29 -0
  44. mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_protocol_middleware.json +34 -0
  45. mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +39 -0
  46. mcp_proxy_adapter/examples/basic_framework/configs/mtls_simple.json +35 -0
  47. mcp_proxy_adapter/examples/basic_framework/configs/mtls_with_roles.json +45 -0
  48. mcp_proxy_adapter/examples/basic_framework/main.py +63 -0
  49. mcp_proxy_adapter/examples/basic_framework/roles.json +21 -0
  50. mcp_proxy_adapter/examples/cert_config.json +9 -0
  51. mcp_proxy_adapter/examples/certs/admin.crt +32 -0
  52. mcp_proxy_adapter/examples/certs/admin.key +52 -0
  53. mcp_proxy_adapter/examples/certs/admin_cert.pem +21 -0
  54. mcp_proxy_adapter/examples/certs/admin_key.pem +28 -0
  55. mcp_proxy_adapter/examples/certs/ca_cert.pem +23 -0
  56. mcp_proxy_adapter/examples/certs/ca_cert.srl +1 -0
  57. mcp_proxy_adapter/examples/certs/ca_key.pem +28 -0
  58. mcp_proxy_adapter/examples/certs/cert_config.json +9 -0
  59. mcp_proxy_adapter/examples/certs/client.crt +32 -0
  60. mcp_proxy_adapter/examples/certs/client.key +52 -0
  61. mcp_proxy_adapter/examples/certs/client_admin.crt +32 -0
  62. mcp_proxy_adapter/examples/certs/client_admin.key +52 -0
  63. mcp_proxy_adapter/examples/certs/client_user.crt +32 -0
  64. mcp_proxy_adapter/examples/certs/client_user.key +52 -0
  65. mcp_proxy_adapter/examples/certs/guest_cert.pem +21 -0
  66. mcp_proxy_adapter/examples/certs/guest_key.pem +28 -0
  67. mcp_proxy_adapter/examples/certs/mcp_proxy_adapter_ca_ca.crt +23 -0
  68. mcp_proxy_adapter/examples/certs/proxy_cert.pem +21 -0
  69. mcp_proxy_adapter/examples/certs/proxy_key.pem +28 -0
  70. mcp_proxy_adapter/examples/certs/readonly.crt +32 -0
  71. mcp_proxy_adapter/examples/certs/readonly.key +52 -0
  72. mcp_proxy_adapter/examples/certs/readonly_cert.pem +21 -0
  73. mcp_proxy_adapter/examples/certs/readonly_key.pem +28 -0
  74. mcp_proxy_adapter/examples/certs/server.crt +32 -0
  75. mcp_proxy_adapter/examples/certs/server.key +52 -0
  76. mcp_proxy_adapter/examples/certs/server_cert.pem +32 -0
  77. mcp_proxy_adapter/examples/certs/server_key.pem +52 -0
  78. mcp_proxy_adapter/examples/certs/test_ca_ca.crt +20 -0
  79. mcp_proxy_adapter/examples/certs/user.crt +32 -0
  80. mcp_proxy_adapter/examples/certs/user.key +52 -0
  81. mcp_proxy_adapter/examples/certs/user_cert.pem +21 -0
  82. mcp_proxy_adapter/examples/certs/user_key.pem +28 -0
  83. mcp_proxy_adapter/examples/client_configs/api_key_client.json +13 -0
  84. mcp_proxy_adapter/examples/client_configs/basic_auth_client.json +13 -0
  85. mcp_proxy_adapter/examples/client_configs/certificate_client.json +22 -0
  86. mcp_proxy_adapter/examples/client_configs/jwt_client.json +15 -0
  87. mcp_proxy_adapter/examples/client_configs/no_auth_client.json +9 -0
  88. mcp_proxy_adapter/examples/commands/__init__.py +1 -0
  89. mcp_proxy_adapter/examples/create_certificates_simple.py +307 -0
  90. mcp_proxy_adapter/examples/debug_request_state.py +144 -0
  91. mcp_proxy_adapter/examples/debug_role_chain.py +205 -0
  92. mcp_proxy_adapter/examples/demo_client.py +341 -0
  93. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +99 -0
  94. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +106 -0
  95. mcp_proxy_adapter/examples/full_application/configs/http_auth.json +37 -0
  96. mcp_proxy_adapter/examples/full_application/configs/http_simple.json +23 -0
  97. mcp_proxy_adapter/examples/full_application/configs/https_auth.json +39 -0
  98. mcp_proxy_adapter/examples/full_application/configs/https_simple.json +25 -0
  99. mcp_proxy_adapter/examples/full_application/configs/mtls_no_roles.json +39 -0
  100. mcp_proxy_adapter/examples/full_application/configs/mtls_with_roles.json +45 -0
  101. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +97 -0
  102. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +95 -0
  103. mcp_proxy_adapter/examples/full_application/main.py +138 -0
  104. mcp_proxy_adapter/examples/full_application/roles.json +21 -0
  105. mcp_proxy_adapter/examples/generate_all_certificates.py +429 -0
  106. mcp_proxy_adapter/examples/generate_certificates.py +121 -0
  107. mcp_proxy_adapter/examples/keys/ca_key.pem +28 -0
  108. mcp_proxy_adapter/examples/keys/mcp_proxy_adapter_ca_ca.key +28 -0
  109. mcp_proxy_adapter/examples/keys/test_ca_ca.key +28 -0
  110. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log +220 -0
  111. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.1 +1 -0
  112. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.2 +1 -0
  113. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.3 +1 -0
  114. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.4 +1 -0
  115. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.5 +1 -0
  116. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log +220 -0
  117. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.1 +1 -0
  118. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.2 +1 -0
  119. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.3 +1 -0
  120. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.4 +1 -0
  121. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.5 +1 -0
  122. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log +2 -0
  123. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.1 +1 -0
  124. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.2 +1 -0
  125. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.3 +1 -0
  126. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.4 +1 -0
  127. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.5 +1 -0
  128. mcp_proxy_adapter/examples/proxy_registration_example.py +401 -0
  129. mcp_proxy_adapter/examples/roles.json +38 -0
  130. mcp_proxy_adapter/examples/run_example.py +81 -0
  131. mcp_proxy_adapter/examples/run_security_tests.py +326 -0
  132. mcp_proxy_adapter/examples/run_security_tests_fixed.py +300 -0
  133. mcp_proxy_adapter/examples/security_test_client.py +743 -0
  134. mcp_proxy_adapter/examples/server_configs/config_basic_http.json +204 -0
  135. mcp_proxy_adapter/examples/server_configs/config_http_token.json +238 -0
  136. mcp_proxy_adapter/examples/server_configs/config_https.json +215 -0
  137. mcp_proxy_adapter/examples/server_configs/config_https_token.json +231 -0
  138. mcp_proxy_adapter/examples/server_configs/config_mtls.json +215 -0
  139. mcp_proxy_adapter/examples/server_configs/config_proxy_registration.json +250 -0
  140. mcp_proxy_adapter/examples/server_configs/config_simple.json +46 -0
  141. mcp_proxy_adapter/examples/server_configs/roles.json +38 -0
  142. mcp_proxy_adapter/examples/test_config_generator.py +110 -0
  143. mcp_proxy_adapter/examples/test_examples.py +344 -0
  144. mcp_proxy_adapter/examples/universal_client.py +628 -0
  145. mcp_proxy_adapter/main.py +21 -10
  146. mcp_proxy_adapter/utils/config_generator.py +727 -0
  147. mcp_proxy_adapter/version.py +5 -2
  148. mcp_proxy_adapter-6.1.1.dist-info/METADATA +205 -0
  149. mcp_proxy_adapter-6.1.1.dist-info/RECORD +197 -0
  150. mcp_proxy_adapter-6.1.1.dist-info/entry_points.txt +2 -0
  151. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.1.dist-info}/licenses/LICENSE +2 -2
  152. mcp_proxy_adapter/api/middleware/auth.py +0 -146
  153. mcp_proxy_adapter/api/middleware/auth_adapter.py +0 -235
  154. mcp_proxy_adapter/api/middleware/mtls_adapter.py +0 -305
  155. mcp_proxy_adapter/api/middleware/mtls_middleware.py +0 -296
  156. mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
  157. mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +0 -241
  158. mcp_proxy_adapter/api/middleware/roles_adapter.py +0 -365
  159. mcp_proxy_adapter/api/middleware/roles_middleware.py +0 -381
  160. mcp_proxy_adapter/api/middleware/security.py +0 -376
  161. mcp_proxy_adapter/api/middleware/token_auth_middleware.py +0 -261
  162. mcp_proxy_adapter/examples/__init__.py +0 -7
  163. mcp_proxy_adapter/examples/basic_server/README.md +0 -60
  164. mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
  165. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
  166. mcp_proxy_adapter/examples/basic_server/config.json +0 -70
  167. mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +0 -54
  168. mcp_proxy_adapter/examples/basic_server/config_http.json +0 -70
  169. mcp_proxy_adapter/examples/basic_server/config_http_only.json +0 -52
  170. mcp_proxy_adapter/examples/basic_server/config_https.json +0 -58
  171. mcp_proxy_adapter/examples/basic_server/config_mtls.json +0 -58
  172. mcp_proxy_adapter/examples/basic_server/config_ssl.json +0 -46
  173. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
  174. mcp_proxy_adapter/examples/basic_server/server.py +0 -114
  175. mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
  176. mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
  177. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -566
  178. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
  179. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
  180. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
  181. mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +0 -105
  182. mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +0 -129
  183. mcp_proxy_adapter/examples/custom_commands/config.json +0 -118
  184. mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +0 -46
  185. mcp_proxy_adapter/examples/custom_commands/config_https_only.json +0 -46
  186. mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +0 -33
  187. mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +0 -46
  188. mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +0 -33
  189. mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +0 -33
  190. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
  191. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
  192. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
  193. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
  194. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
  195. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
  196. mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
  197. mcp_proxy_adapter/examples/custom_commands/full_help_response.json +0 -1
  198. mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +0 -629
  199. mcp_proxy_adapter/examples/custom_commands/get_openapi.py +0 -103
  200. mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
  201. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
  202. mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +0 -129
  203. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
  204. mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +0 -278
  205. mcp_proxy_adapter/examples/custom_commands/server.py +0 -252
  206. mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +0 -75
  207. mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +0 -299
  208. mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +0 -278
  209. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
  210. mcp_proxy_adapter/examples/custom_commands/test_openapi.py +0 -27
  211. mcp_proxy_adapter/examples/custom_commands/test_registry.py +0 -23
  212. mcp_proxy_adapter/examples/custom_commands/test_simple.py +0 -19
  213. mcp_proxy_adapter/examples/custom_project_example/README.md +0 -103
  214. mcp_proxy_adapter/examples/custom_project_example/README_EN.md +0 -103
  215. mcp_proxy_adapter/examples/deployment/README.md +0 -49
  216. mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
  217. mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
  218. mcp_proxy_adapter/examples/deployment/config.json +0 -29
  219. mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
  220. mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
  221. mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
  222. mcp_proxy_adapter/examples/deployment/run.sh +0 -43
  223. mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
  224. mcp_proxy_adapter/examples/simple_custom_commands/README.md +0 -149
  225. mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +0 -149
  226. mcp_proxy_adapter/schemas/base_schema.json +0 -114
  227. mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
  228. mcp_proxy_adapter/schemas/roles_schema.json +0 -162
  229. mcp_proxy_adapter/tests/__init__.py +0 -0
  230. mcp_proxy_adapter/tests/api/__init__.py +0 -3
  231. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
  232. mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
  233. mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
  234. mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
  235. mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
  236. mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
  237. mcp_proxy_adapter/tests/commands/__init__.py +0 -3
  238. mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
  239. mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
  240. mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
  241. mcp_proxy_adapter/tests/conftest.py +0 -131
  242. mcp_proxy_adapter/tests/functional/__init__.py +0 -3
  243. mcp_proxy_adapter/tests/functional/test_api.py +0 -253
  244. mcp_proxy_adapter/tests/integration/__init__.py +0 -3
  245. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
  246. mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
  247. mcp_proxy_adapter/tests/performance/__init__.py +0 -3
  248. mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
  249. mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
  250. mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
  251. mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
  252. mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
  253. mcp_proxy_adapter/tests/test_base_command.py +0 -123
  254. mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
  255. mcp_proxy_adapter/tests/test_command_registry.py +0 -281
  256. mcp_proxy_adapter/tests/test_config.py +0 -127
  257. mcp_proxy_adapter/tests/test_utils.py +0 -65
  258. mcp_proxy_adapter/tests/unit/__init__.py +0 -3
  259. mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
  260. mcp_proxy_adapter/tests/unit/test_config.py +0 -270
  261. mcp_proxy_adapter-6.0.0.dist-info/METADATA +0 -201
  262. mcp_proxy_adapter-6.0.0.dist-info/RECORD +0 -179
  263. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.1.dist-info}/WHEEL +0 -0
  264. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,429 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Generate All Certificates for Security Testing
4
+
5
+ This script generates all necessary certificates for comprehensive security testing:
6
+ - Root CA certificate and key
7
+ - Server certificates for HTTPS and mTLS
8
+ - Client certificates for different roles (admin, user, readonly, etc.)
9
+ - Test certificates for negative scenarios
10
+
11
+ Author: Vasiliy Zdanovskiy
12
+ email: vasilyvz@gmail.com
13
+ """
14
+
15
+ import json
16
+ import os
17
+ import subprocess
18
+ import sys
19
+ from pathlib import Path
20
+ from typing import Dict, List, Optional
21
+
22
+
23
+ class CertificateGenerator:
24
+ """Generate all certificates for security testing."""
25
+
26
+ def __init__(self):
27
+ self.project_root = Path(__file__).parent.parent.parent
28
+ self.certs_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "certs"
29
+ self.keys_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "keys"
30
+
31
+ # Create directories if they don't exist
32
+ self.certs_dir.mkdir(parents=True, exist_ok=True)
33
+ self.keys_dir.mkdir(parents=True, exist_ok=True)
34
+
35
+ # Certificate configuration
36
+ self.ca_config = {
37
+ "common_name": "MCP Proxy Adapter Test CA",
38
+ "organization": "Test Organization",
39
+ "country": "US",
40
+ "state": "Test State",
41
+ "city": "Test City",
42
+ "validity_years": 10
43
+ }
44
+
45
+ self.server_config = {
46
+ "common_name": "mcp-proxy-adapter-test.local",
47
+ "organization": "Test Organization",
48
+ "country": "US",
49
+ "state": "Test State",
50
+ "city": "Test City",
51
+ "validity_years": 2,
52
+ "san": ["localhost", "127.0.0.1", "mcp-proxy-adapter-test.local"]
53
+ }
54
+
55
+ # Client certificates configuration
56
+ self.client_certs = {
57
+ "admin": {
58
+ "common_name": "admin-client",
59
+ "organization": "Test Organization",
60
+ "roles": ["admin"],
61
+ "permissions": ["*"]
62
+ },
63
+ "user": {
64
+ "common_name": "user-client",
65
+ "organization": "Test Organization",
66
+ "roles": ["user"],
67
+ "permissions": ["read", "write"]
68
+ },
69
+ "readonly": {
70
+ "common_name": "readonly-client",
71
+ "organization": "Test Organization",
72
+ "roles": ["readonly"],
73
+ "permissions": ["read"]
74
+ },
75
+ "guest": {
76
+ "common_name": "guest-client",
77
+ "organization": "Test Organization",
78
+ "roles": ["guest"],
79
+ "permissions": ["read"]
80
+ },
81
+ "proxy": {
82
+ "common_name": "proxy-client",
83
+ "organization": "Test Organization",
84
+ "roles": ["proxy"],
85
+ "permissions": ["register", "discover"]
86
+ }
87
+ }
88
+
89
+ # Negative test certificates
90
+ self.negative_certs = {
91
+ "expired": {
92
+ "common_name": "expired-client",
93
+ "organization": "Test Organization",
94
+ "validity_days": 1 # Will expire quickly
95
+ },
96
+ "wrong_org": {
97
+ "common_name": "wrong-org-client",
98
+ "organization": "Wrong Organization",
99
+ "roles": ["user"]
100
+ },
101
+ "no_roles": {
102
+ "common_name": "no-roles-client",
103
+ "organization": "Test Organization",
104
+ "roles": []
105
+ },
106
+ "invalid_roles": {
107
+ "common_name": "invalid-roles-client",
108
+ "organization": "Test Organization",
109
+ "roles": ["invalid_role"]
110
+ }
111
+ }
112
+
113
+ def run_command(self, cmd: List[str], description: str) -> bool:
114
+ """Run a command and handle errors."""
115
+ try:
116
+ print(f"šŸ”§ {description}...")
117
+ result = subprocess.run(
118
+ cmd,
119
+ cwd=self.project_root,
120
+ capture_output=True,
121
+ text=True,
122
+ check=True
123
+ )
124
+ print(f"āœ… {description} completed successfully")
125
+ return True
126
+ except subprocess.CalledProcessError as e:
127
+ print(f"āŒ {description} failed:")
128
+ print(f" Command: {' '.join(cmd)}")
129
+ print(f" Error: {e.stderr}")
130
+ return False
131
+ except Exception as e:
132
+ print(f"āŒ {description} failed: {e}")
133
+ return False
134
+
135
+ def create_ca_certificate(self) -> bool:
136
+ """Create Root CA certificate and key."""
137
+ ca_cert_path = self.certs_dir / "ca_cert.pem"
138
+ ca_key_path = self.keys_dir / "ca_key.pem"
139
+
140
+ if ca_cert_path.exists() and ca_key_path.exists():
141
+ print(f"ā„¹ļø CA certificate already exists: {ca_cert_path}")
142
+ return True
143
+
144
+ cmd = [
145
+ sys.executable, "-m", "mcp_security_framework.cli.cert_cli", "create-ca",
146
+ "-cn", self.ca_config["common_name"],
147
+ "-o", self.ca_config["organization"],
148
+ "-c", self.ca_config["country"],
149
+ "-s", self.ca_config["state"],
150
+ "-l", self.ca_config["city"],
151
+ "-y", str(self.ca_config["validity_years"])
152
+ ]
153
+
154
+ success = self.run_command(cmd, "Creating Root CA certificate")
155
+
156
+ if success:
157
+ # Move files to correct locations
158
+ default_ca_cert = Path("./certs") / f"{self.ca_config['common_name'].lower().replace(' ', '_')}_ca.crt"
159
+ default_ca_key = Path("./keys") / f"{self.ca_config['common_name'].lower().replace(' ', '_')}_ca.key"
160
+
161
+ if default_ca_cert.exists():
162
+ self.run_command(["mv", str(default_ca_cert), str(ca_cert_path)], "Moving CA certificate")
163
+ if default_ca_key.exists():
164
+ self.run_command(["mv", str(default_ca_key), str(ca_key_path)], "Moving CA key")
165
+
166
+ return success
167
+
168
+ def create_server_certificate(self) -> bool:
169
+ """Create server certificate for HTTPS and mTLS."""
170
+ server_cert_path = self.certs_dir / "server_cert.pem"
171
+ server_key_path = self.certs_dir / "server_key.pem"
172
+
173
+ if server_cert_path.exists() and server_key_path.exists():
174
+ print(f"ā„¹ļø Server certificate already exists: {server_cert_path}")
175
+ return True
176
+
177
+ # Create server certificate
178
+ cmd = [
179
+ sys.executable, "-m", "mcp_security_framework.cli.cert_cli", "create-server",
180
+ "-cn", self.server_config["common_name"],
181
+ "-o", self.server_config["organization"],
182
+ "-c", self.server_config["country"],
183
+ "-s", self.server_config["state"],
184
+ "-l", self.server_config["city"],
185
+ "-d", str(self.server_config["validity_years"] * 365) # Convert years to days
186
+ ]
187
+
188
+ # Add SAN if supported
189
+ if self.server_config["san"]:
190
+ for san in self.server_config["san"]:
191
+ cmd.extend(["--san", san])
192
+
193
+ success = self.run_command(cmd, "Creating server certificate")
194
+
195
+ if success:
196
+ # Move files to correct locations
197
+ default_server_cert = Path("./certs") / f"{self.server_config['common_name'].lower().replace('.', '_')}_server.crt"
198
+ default_server_key = Path("./keys") / f"{self.server_config['common_name'].lower().replace('.', '_')}_server.key"
199
+
200
+ if default_server_cert.exists():
201
+ self.run_command(["mv", str(default_server_cert), str(server_cert_path)], "Moving server certificate")
202
+ if default_server_key.exists():
203
+ self.run_command(["mv", str(default_server_key), str(server_key_path)], "Moving server key")
204
+
205
+ return success
206
+
207
+ def create_client_certificate(self, name: str, config: Dict) -> bool:
208
+ """Create client certificate with specific configuration."""
209
+ cert_path = self.certs_dir / f"{name}_cert.pem"
210
+ key_path = self.certs_dir / f"{name}_key.pem"
211
+
212
+ if cert_path.exists() and key_path.exists():
213
+ print(f"ā„¹ļø Client certificate {name} already exists: {cert_path}")
214
+ return True
215
+
216
+ cmd = [
217
+ sys.executable, "-m", "mcp_security_framework.cli.cert_cli", "create-client",
218
+ "-cn", config["common_name"],
219
+ "-o", config["organization"],
220
+ "-c", self.ca_config["country"],
221
+ "-s", self.ca_config["state"],
222
+ "-l", self.ca_config["city"],
223
+ "-d", "730" # 2 years in days
224
+ ]
225
+
226
+ # Add roles if specified
227
+ if "roles" in config and config["roles"]:
228
+ for role in config["roles"]:
229
+ cmd.extend(["--roles", role])
230
+
231
+ # Add permissions if specified
232
+ if "permissions" in config and config["permissions"]:
233
+ for permission in config["permissions"]:
234
+ cmd.extend(["--permissions", permission])
235
+
236
+ # Add custom validity for negative tests
237
+ if "validity_days" in config:
238
+ cmd[cmd.index("-d") + 1] = str(config["validity_days"])
239
+
240
+ success = self.run_command(cmd, f"Creating client certificate: {name}")
241
+
242
+ if success:
243
+ # Move files to correct locations
244
+ default_client_cert = Path("./certs") / f"{config['common_name'].lower().replace('-', '_')}_client.crt"
245
+ default_client_key = Path("./keys") / f"{config['common_name'].lower().replace('-', '_')}_client.key"
246
+
247
+ if default_client_cert.exists():
248
+ self.run_command(["mv", str(default_client_cert), str(cert_path)], f"Moving {name} certificate")
249
+ if default_client_key.exists():
250
+ self.run_command(["mv", str(default_client_key), str(key_path)], f"Moving {name} key")
251
+
252
+ return success
253
+
254
+ def create_legacy_certificates(self) -> bool:
255
+ """Create legacy certificate files for compatibility."""
256
+ legacy_files = [
257
+ ("client.crt", "client.key"),
258
+ ("client_admin.crt", "client_admin.key"),
259
+ ("admin.crt", "admin.key"),
260
+ ("user.crt", "user.key"),
261
+ ("readonly.crt", "readonly.key")
262
+ ]
263
+
264
+ success = True
265
+ for cert_file, key_file in legacy_files:
266
+ cert_path = self.certs_dir / cert_file
267
+ key_path = self.certs_dir / key_file
268
+
269
+ if not cert_path.exists() or not key_path.exists():
270
+ # Copy from existing certificates
271
+ if cert_file == "client.crt" and (self.certs_dir / "user_cert.pem").exists():
272
+ self.run_command(["cp", str(self.certs_dir / "user_cert.pem"), str(cert_path)], f"Creating {cert_file}")
273
+ self.run_command(["cp", str(self.certs_dir / "user_key.pem"), str(key_path)], f"Creating {key_file}")
274
+ elif cert_file == "client_admin.crt" and (self.certs_dir / "admin_cert.pem").exists():
275
+ self.run_command(["cp", str(self.certs_dir / "admin_cert.pem"), str(cert_path)], f"Creating {cert_file}")
276
+ self.run_command(["cp", str(self.certs_dir / "admin_key.pem"), str(key_path)], f"Creating {key_file}")
277
+ elif cert_file == "admin.crt" and (self.certs_dir / "admin_cert.pem").exists():
278
+ self.run_command(["cp", str(self.certs_dir / "admin_cert.pem"), str(cert_path)], f"Creating {cert_file}")
279
+ self.run_command(["cp", str(self.certs_dir / "admin_key.pem"), str(key_path)], f"Creating {key_file}")
280
+ elif cert_file == "user.crt" and (self.certs_dir / "user_cert.pem").exists():
281
+ self.run_command(["cp", str(self.certs_dir / "user_cert.pem"), str(cert_path)], f"Creating {cert_file}")
282
+ self.run_command(["cp", str(self.certs_dir / "user_key.pem"), str(key_path)], f"Creating {key_file}")
283
+ elif cert_file == "readonly.crt" and (self.certs_dir / "readonly_cert.pem").exists():
284
+ self.run_command(["cp", str(self.certs_dir / "readonly_cert.pem"), str(cert_path)], f"Creating {cert_file}")
285
+ self.run_command(["cp", str(self.certs_dir / "readonly_key.pem"), str(key_path)], f"Creating {key_file}")
286
+
287
+ return success
288
+
289
+ def create_certificate_config(self) -> bool:
290
+ """Create certificate configuration file."""
291
+ config_path = self.certs_dir / "cert_config.json"
292
+
293
+ config = {
294
+ "ca_cert_path": str(self.certs_dir / "ca_cert.pem"),
295
+ "ca_key_path": str(self.keys_dir / "ca_key.pem"),
296
+ "cert_storage_path": str(self.certs_dir),
297
+ "key_storage_path": str(self.keys_dir),
298
+ "default_validity_days": 365,
299
+ "key_size": 2048,
300
+ "hash_algorithm": "sha256"
301
+ }
302
+
303
+ try:
304
+ with open(config_path, 'w') as f:
305
+ json.dump(config, f, indent=2)
306
+ print(f"āœ… Created certificate config: {config_path}")
307
+ return True
308
+ except Exception as e:
309
+ print(f"āŒ Failed to create certificate config: {e}")
310
+ return False
311
+
312
+ def validate_certificates(self) -> bool:
313
+ """Validate all created certificates."""
314
+ print("\nšŸ” Validating certificates...")
315
+
316
+ cert_files = [
317
+ "ca_cert.pem",
318
+ "server_cert.pem",
319
+ "admin_cert.pem",
320
+ "user_cert.pem",
321
+ "readonly_cert.pem",
322
+ "guest_cert.pem",
323
+ "proxy_cert.pem"
324
+ ]
325
+
326
+ success = True
327
+ for cert_file in cert_files:
328
+ cert_path = self.certs_dir / cert_file
329
+ if cert_path.exists():
330
+ try:
331
+ result = subprocess.run(
332
+ ["openssl", "x509", "-in", str(cert_path), "-text", "-noout"],
333
+ capture_output=True,
334
+ text=True,
335
+ check=True
336
+ )
337
+ print(f"āœ… {cert_file}: Valid")
338
+ except subprocess.CalledProcessError:
339
+ print(f"āŒ {cert_file}: Invalid")
340
+ success = False
341
+ else:
342
+ print(f"āš ļø {cert_file}: Not found")
343
+
344
+ return success
345
+
346
+ def generate_all(self) -> bool:
347
+ """Generate all certificates."""
348
+ print("šŸ” Generating All Certificates for Security Testing")
349
+ print("=" * 60)
350
+
351
+ success = True
352
+
353
+ # 1. Create CA certificate
354
+ if not self.create_ca_certificate():
355
+ success = False
356
+ print("āŒ Cannot continue without CA certificate")
357
+ return False
358
+
359
+ # 2. Create server certificate
360
+ if not self.create_server_certificate():
361
+ success = False
362
+
363
+ # 3. Create client certificates for different roles
364
+ print("\nšŸ‘„ Creating client certificates...")
365
+ for name, config in self.client_certs.items():
366
+ if not self.create_client_certificate(name, config):
367
+ success = False
368
+
369
+ # 4. Create negative test certificates
370
+ print("\n🚫 Creating negative test certificates...")
371
+ for name, config in self.negative_certs.items():
372
+ if not self.create_client_certificate(name, config):
373
+ success = False
374
+
375
+ # 5. Create legacy certificates for compatibility
376
+ print("\nšŸ”„ Creating legacy certificates...")
377
+ if not self.create_legacy_certificates():
378
+ success = False
379
+
380
+ # 6. Create certificate configuration
381
+ if not self.create_certificate_config():
382
+ success = False
383
+
384
+ # 7. Validate certificates
385
+ if not self.validate_certificates():
386
+ success = False
387
+
388
+ # Print summary
389
+ print("\n" + "=" * 60)
390
+ print("šŸ“Š CERTIFICATE GENERATION SUMMARY")
391
+ print("=" * 60)
392
+
393
+ if success:
394
+ print("āœ… All certificates generated successfully!")
395
+ print(f"šŸ“ Certificates directory: {self.certs_dir}")
396
+ print(f"šŸ”‘ Keys directory: {self.keys_dir}")
397
+ print("\nšŸ“‹ Generated certificates:")
398
+
399
+ cert_files = list(self.certs_dir.glob("*.pem")) + list(self.certs_dir.glob("*.crt"))
400
+ for cert_file in sorted(cert_files):
401
+ print(f" - {cert_file.name}")
402
+
403
+ key_files = list(self.keys_dir.glob("*.pem")) + list(self.keys_dir.glob("*.key"))
404
+ for key_file in sorted(key_files):
405
+ print(f" - {key_file.name}")
406
+ else:
407
+ print("āŒ Some certificates failed to generate")
408
+ print("Check the error messages above")
409
+
410
+ return success
411
+
412
+
413
+ def main():
414
+ """Main function."""
415
+ generator = CertificateGenerator()
416
+
417
+ try:
418
+ success = generator.generate_all()
419
+ sys.exit(0 if success else 1)
420
+ except KeyboardInterrupt:
421
+ print("\nāš ļø Certificate generation interrupted by user")
422
+ sys.exit(1)
423
+ except Exception as e:
424
+ print(f"\nāŒ Certificate generation failed: {e}")
425
+ sys.exit(1)
426
+
427
+
428
+ if __name__ == "__main__":
429
+ main()
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Certificate Generation Script
4
+
5
+ This script generates all necessary certificates for the examples using
6
+ mcp_security_framework certificate management tools.
7
+
8
+ Author: Vasiliy Zdanovskiy
9
+ email: vasilyvz@gmail.com
10
+ """
11
+
12
+ import os
13
+ import subprocess
14
+ import sys
15
+ from pathlib import Path
16
+
17
+ def run_command(cmd, description):
18
+ """Run a command and handle errors."""
19
+ print(f"šŸ”§ {description}...")
20
+ try:
21
+ result = subprocess.run(cmd, shell=True, check=True, capture_output=True, text=True)
22
+ print(f"āœ… {description} completed successfully")
23
+ return True
24
+ except subprocess.CalledProcessError as e:
25
+ print(f"āŒ {description} failed: {e}")
26
+ print(f"Error output: {e.stderr}")
27
+ return False
28
+
29
+ def main():
30
+ """Generate all certificates for examples."""
31
+ print("šŸ” Certificate Generation Script")
32
+ print("=" * 50)
33
+
34
+ # Create directories
35
+ cert_dir = Path("certs")
36
+ cert_dir.mkdir(exist_ok=True)
37
+
38
+ # Check if mcp_security_framework is available
39
+ try:
40
+ import mcp_security_framework
41
+ print(f"āœ… mcp_security_framework version {mcp_security_framework.__version__} found")
42
+ except ImportError:
43
+ print("āŒ mcp_security_framework not found")
44
+ return False
45
+
46
+ # Generate CA certificate
47
+ if not run_command(
48
+ "python -m mcp_security_framework.cli.cert_cli create-ca "
49
+ "--common-name 'MCP Proxy Adapter CA' "
50
+ "--organization 'MCP Proxy Adapter' "
51
+ "--country 'US' "
52
+ "--state 'State' "
53
+ "--locality 'City' "
54
+ "--validity-years 10 "
55
+ "--key-size 2048",
56
+ "Creating root CA certificate"
57
+ ):
58
+ return False
59
+
60
+ # Generate server certificate
61
+ if not run_command(
62
+ "python -m mcp_security_framework.cli.cert_cli -c cert_config.json create-server "
63
+ "--common-name 'localhost' "
64
+ "--organization 'MCP Proxy Adapter' "
65
+ "--country 'US' "
66
+ "--validity-days 365 "
67
+ "--key-size 2048",
68
+ "Creating server certificate"
69
+ ):
70
+ return False
71
+
72
+ # Generate admin client certificate
73
+ if not run_command(
74
+ "python -m mcp_security_framework.cli.cert_cli -c cert_config.json create-client "
75
+ "--common-name 'admin' "
76
+ "--organization 'MCP Proxy Adapter' "
77
+ "--country 'US' "
78
+ "--validity-days 365 "
79
+ "--key-size 2048 "
80
+ "--roles 'admin' "
81
+ "--permissions 'read,write,delete'",
82
+ "Creating admin client certificate"
83
+ ):
84
+ return False
85
+
86
+ # Generate user client certificate
87
+ if not run_command(
88
+ "python -m mcp_security_framework.cli.cert_cli -c cert_config.json create-client "
89
+ "--common-name 'user' "
90
+ "--organization 'MCP Proxy Adapter' "
91
+ "--country 'US' "
92
+ "--validity-days 365 "
93
+ "--key-size 2048 "
94
+ "--roles 'user' "
95
+ "--permissions 'read,write'",
96
+ "Creating user client certificate"
97
+ ):
98
+ return False
99
+
100
+ # Generate readonly client certificate
101
+ if not run_command(
102
+ "python -m mcp_security_framework.cli.cert_cli -c cert_config.json create-client "
103
+ "--common-name 'readonly' "
104
+ "--organization 'MCP Proxy Adapter' "
105
+ "--country 'US' "
106
+ "--validity-days 365 "
107
+ "--key-size 2048 "
108
+ "--roles 'readonly' "
109
+ "--permissions 'read'",
110
+ "Creating readonly client certificate"
111
+ ):
112
+ return False
113
+
114
+ print("\nšŸŽ‰ All certificates generated successfully!")
115
+ print("šŸ“ Certificates are stored in the 'certs' directory")
116
+
117
+ return True
118
+
119
+ if __name__ == "__main__":
120
+ success = main()
121
+ sys.exit(0 if success else 1)
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDLlJMRJelqXw2E
3
+ AHQf8KnxSbiqY8Ee2q5G7xjgyamBae4HdOcCoLu4GA7mvSmBZDvj6NuVjdYKhKYH
4
+ TzfT1aXgwx9DZykDB9/ApbPYFO3rndu0c5xxST8iJqtLk5YJ+yM04rCv3miQhdSN
5
+ ZjNlInihC5uoOXrVyUgrgxKjOxhkudW1CIaIgaIlbJcftffUzEtcfYgSMc0J3EZX
6
+ E3fvX+9xqWMWfpcoftWMHZpcbV+1dke68s+i5F+98TEG2JxbmlkXgNq0xRdWpcnV
7
+ osU4sYxfKiKCWN5RUlumx9Xh1Mlw4m/C38ZgM3/DWS+0dAl5r4Q0lObBF0ej54U4
8
+ BVgMMOPJAgMBAAECggEAARkcj/ed4jKADqm39qIkMIZ+xgCCvqlcTkqk3jWIQgfx
9
+ vj2Nr3BxgsUyc2Eq06VYQ1rysERTFrxvbtOpD+3zlppG1WS9jmQg+1eJeE1omSBB
10
+ WqBTBDNqcUM3IlG5+fTOVE8yt8gh1UG7i0W1WkLM1sWKweYJeRS8XGu5EoNTltt9
11
+ SDWsx5fCjHMviYhEiHOkkP62ZjdsrH7qYvoR6AeWAUWODy253cWs/Fzj6OeGk7VO
12
+ qLw7i7geWpzmosevfd+fxVJW0UOKKMGngI8xPeJnpQJDL1Vrb+fUeJ0Hu9LXWR9d
13
+ 6LKoP9gaKvXLA4NmkkX+B0+fBVWTR3rAuYRgxLJeAQKBgQD5N1Dw3ocayMM3RqOq
14
+ l6OkGxd+kssnSJN3yZiOBXHy7923mhAMP2KKTP9z3J/CzjWxfRbLEwKWn3Ft2IzM
15
+ WCbQKFTKRWGJeOg0I2k6DI68x7Wqw5kkc3NogxziWOO67UPgHNWsXFR9H9XzAB5+
16
+ RY7THOrHPIjQIeT2xEHeh/UOgQKBgQDRHz3t0iRt3Qj58RxknbXbTA82FijPF2Xc
17
+ ByzJQNZs2+nYlB+S4MB/XCzMfJdP+FrA8BZ5MOT90TBIqYmIo2mnY6/D9XeGaOti
18
+ H8xV45x0C2RlNXCX9Nn4P+j64fZdHVp2+rirNqvyTKN7fKI/Cbd3TMipJUGe77N4
19
+ 5KmPMCFBSQKBgQDPEDrcJsgyZORuJO8Pana4fxoCPI020oJUYNe0CKooo0ugpQz4
20
+ YCHLrzYAWisTfKn4EmrBx8W6yDdCgU5a6lM1WI06knL7+c1UpKdlZ9Gg4H38qA+x
21
+ zYryJx30os50HXbr2olecEhyveTRxiOP3tNQbRJU/+Lcq4zFy0K/Vk8yAQKBgF7J
22
+ 9H46BH0v9YOlgKMywV23qiVwAetsxaToM6q9kvQg8mxTJ8Shz19rXnsJ9mQvRKOz
23
+ r9wbB5DtIx+siUTAHYHcM611NEpegGMn2q0L0Lzg9Q7THEgkmjBmd6pQhiVKytin
24
+ aNFipKndhzTQF5LPSrPuv/27f3UVXZpsu1bGECzRAoGBAIBAJPYmlt8Mfhhvi9Yg
25
+ OXhlqPT7PjRBu+YaoineS5BNZ9V/23ib7iAOClCxdX+7doHI0VKzMyGJR2xa7Rzl
26
+ /oRInNWGU2UV+mCb6FoYohfHX0OFkelKJOZsyxWUrQ93IipwBTomoQnnrEExSzLh
27
+ r0FGAumOHw6zwjmbFSXRbPvs
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDWjQzvziU+/Y+S
3
+ wXDHXvcG5/ZV3C/R/9JhKZCAJ2g28Dg97Xjf9L8hh+Wzpkj3wDJL2Ho76nMegO5V
4
+ +m/HFVabSA/dn4bxOGqL5v7AXkQrdWRATYMRmGG6lS1NZC6pHRuD/Oun76Jv9aiN
5
+ QyYkLR3iFY8+pQTFhJX2MOO99gmPtAPmy3l3Zu1l2S87TB5Lv8MGuhSuPoNTWzND
6
+ hKP06oX6BCpqmqgkgo0Moy7SaVWAxviyZFjv/SbxUVU1kXqXJpUFoyCHX4ocQqNT
7
+ iGl+M2q0VZm9slhNuisoR7RfAx8eEBcPebOIlqzHBvq3hGgYeWWjnW34OrNwmhx1
8
+ kAPu3CRhAgMBAAECggEACi6y4NAGzSuEMdyDuWKUv2Yo4cBLy1/5yxS0P/DJgw9O
9
+ 4VmGNWgh3g8wuUr4sZFp5wGaI4J9U4Lzohmlo8GBKmjMH/eJ6aQvd6j53tqvyjmN
10
+ uCOK8eh/0uFw6fhe4osixYEuafpMhPBtacQ4aNp0ovM6U33KG9musvrKWYygvYog
11
+ /FUsR/3iUx0FK2Bpa9O7BDNpau7QdBwXyoQAv/BY+lGysdtfwuJOiQdIxg2if15v
12
+ QUgryNV+x6v2mmVV/wiJ/H+3D1Els+BQG5DA3s0IjblEKYKryA6xM5WdSLUCADt4
13
+ gE5V4yJ652iHPGd9X0OZ3wKEz55HJecIW6O8UORQsQKBgQD3uYdVLLMReZxV2tfk
14
+ hoIJ2HEtiJjCmvjnL5fSbLGVTnkCi/S94X02UsKeHnrkzR/QCRzSBKdOkPZXinMZ
15
+ cDYv4z7rNolBMc2Itqq27g5Yxu0NpJ1303QOc3m97O37X8y6r+TYj8frRJrx7iG1
16
+ 9N11j99ZoP9vH2LHcdDubcDL5QKBgQDdt9RYwyFo/vmi8I1KdYBScNXXujf6spPa
17
+ jgeZ3tP8Dkhuf2oABjflK7G4ySIAPl9BDBgc9paY4IcHkgw2YJd5pyYMaCrk4mPg
18
+ NnYCthGIxSzpeqfaFIEavE8/zxeT9jhTh7ScFCFqaUFtzzlzjTzc54MNm5fhc9oq
19
+ 2I4rl9OGzQKBgQCbjSQtl6PZlUNVpdVq6gs9o2tt7BgAGs+wW3I574aS+nOB5eAI
20
+ W08EjXMnVnxUr3kKaK5wMfvcmaoVzhn4Hz3nVApuKBCHn34wGoOX2mOn20F/D57R
21
+ XzXA3UHUwLGu5rjngQtx8NbYJHwm7iC84MUuzOiynyXF4S9ljVJkZQZrAQKBgGOg
22
+ /DlajYPJt1FBeKvxutTQwTasBgWQAyJdWgsJdwY3QNLuTCpwoONIzBZ1wuKLJHBt
23
+ R9ST9b4CfoqnVPeGVeqjclR25ndtR2Xz8vlq6NwlhfXwWMaFGjJyVcYdf8HMDSlz
24
+ vHO6E/3mCDGYwX8sAyJcoaYWuZvkXC+Omev60GEtAoGAeryzTJzl8DHbDKk/3Zvv
25
+ Zo6CbiPh2iBdb6PoPL4cSg/NBDNuHrnWPr/N0RZ5D/cNfA8cv20I1tWBPr+X6r3F
26
+ 2QQKSVt89JqfWJ1Xpj2Nxpnfa3QGFiQFCG5/366rZgASaQsuZNTAVgpbMEpwCjzI
27
+ t0rl84AcRvCvzc67//51jZg=
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDLj3pcpg4owGNK
3
+ +8KT5FbXuGKYH0577+h9RE0KGC9JrJxCn8O1g62lRcpDCQ8IGwPn97wVGfbAG8ei
4
+ iQUfEPNfkaILv+f2j69tZIbhwuuUjfip8Xy4qcMCYTOnoB8ruwpwiKC8VCmWOOG+
5
+ ma59isHAc0WuNhM+UXmkvEh1CnW3IlmRSilkLAdAI0Z+LkJH6Olb8loFsCcIb3kS
6
+ +FXrviS10eUXxntwNmyHV29svqByS+l5vxloatsMpRZWKZVRr9avYEZhtV37Ae/k
7
+ JD5dqGGa4+5iJJiN9FBmxr7FRJ1/w35fFzR9TP2UyBNhMrEGTii2abITzrSS+nid
8
+ jSBj01kxAgMBAAECggEAUGEvAZ+mjqvtaWIBgvGS4yrRb91I2gKxTKmoPBixr4dj
9
+ yqEYoDfHXTAyPoc4sswsHjCCSdjPSSuPCJzPc2V3nKC+mqIkQAWb0Xf1FPepm6b1
10
+ 7nFHfQm30dw9D+9X76YzaJ1izwrywvliFqfLsZIVkN9TwAdlUOHORWD9wY2oTvAi
11
+ JS7PvTCWuqv4JkAIPZz2UIMBSv7ZajFr4Ysa2Sp9MM2kbIA7uE66HoIF7ic7eD6P
12
+ a6vaFQ23oDs/ZkL73L4goD0283E0HZ/RIBXgFTVvS4bOfbU+ShgRuznX9MmTJIXP
13
+ kgIbgOa3gJhvkKvmLsame9QP7nXzLQiystFqa7B6KwKBgQD1u5ztEkt2CQ1EFjMG
14
+ 9A6kCMPsJHn/HFVbQcs2ZEPiZ7ioTamWZDziP0ykzrymNqkBqOcqEpAj6OUKbFpA
15
+ 8Q1sxVkZZrJmlOMT73Hzv0fyS2sRVH7ee4uFjVd67lVoWjKFOu/CAooz82IkI6r0
16
+ qTGaPbCsz0w4U5ka+ZQWw1RQpwKBgQDUEMi7di8YAZYEwiYNDzee+E6JcJ1z/URU
17
+ 29DO+5YIhVHLft6vLWqe5law/oQlKULN6k3FO/zd977DoS0c9ALgKgDuhf46NXSk
18
+ ukboc2Yplt1LtFOlE7JeYuiHacRHwh+j5ToVlcUVZywXmadDpnNLmWqmivqw9th/
19
+ V/0AiOiqZwKBgQC5ORR9IfgdXY9RTgZibF4IyM6dVZVbdQjlw38gXY1Jv/LRcdCt
20
+ mprF0v67j1VlV/gmVyD/doSNfMQAClIxd0EuRsb1PZKlff54DVlwaDMb8DshEfab
21
+ TraJEVPqRnG8OZixEg6cx3tS01abdQMsbcgEwhFFAPAr2N+kFJHKYqtQKwKBgQCs
22
+ U5dK/pb2YxONeleBdUQ1ooHvndvVTZIhgx8Dk94vvmbhfo9muvlRdswruCeaKxVm
23
+ T2gzRrQNjC0wu+D1DjToBDoNmkUk+Bt5YQYODviOA1KBGmB+XKstmCJtJ72gslcT
24
+ 0EqLD9G/ur9RzkLl7nTykhDglT9yXqU/lji6HoczMQKBgAYhRQeD9pjWPw1+I3Em
25
+ ZwKrAWmOsQKjV4oURU2U/QHKuyzH/H5XkKXpJgpCnYU6XRmIGWvoH/SyLvFv4fhC
26
+ SN8NEoT5JuuMrrJP2m0lWen52ATuuBt/PD+9CSkm9lD9zTG0V9V/he0wYXYv5yYA
27
+ 52PiP265yj3oroWvGzUwJxxR
28
+ -----END PRIVATE KEY-----