mcp-proxy-adapter 6.0.0__py3-none-any.whl → 6.0.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 (212) hide show
  1. mcp_proxy_adapter/__main__.py +27 -7
  2. mcp_proxy_adapter/api/app.py +209 -79
  3. mcp_proxy_adapter/api/handlers.py +16 -5
  4. mcp_proxy_adapter/api/middleware/__init__.py +14 -9
  5. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
  6. mcp_proxy_adapter/api/middleware/factory.py +36 -12
  7. mcp_proxy_adapter/api/middleware/protocol_middleware.py +84 -18
  8. mcp_proxy_adapter/api/middleware/unified_security.py +197 -0
  9. mcp_proxy_adapter/api/middleware/user_info_middleware.py +158 -0
  10. mcp_proxy_adapter/commands/__init__.py +7 -1
  11. mcp_proxy_adapter/commands/base.py +7 -4
  12. mcp_proxy_adapter/commands/builtin_commands.py +8 -2
  13. mcp_proxy_adapter/commands/command_registry.py +8 -0
  14. mcp_proxy_adapter/commands/echo_command.py +81 -0
  15. mcp_proxy_adapter/commands/health_command.py +1 -1
  16. mcp_proxy_adapter/commands/help_command.py +21 -14
  17. mcp_proxy_adapter/commands/proxy_registration_command.py +326 -185
  18. mcp_proxy_adapter/commands/role_test_command.py +141 -0
  19. mcp_proxy_adapter/commands/security_command.py +488 -0
  20. mcp_proxy_adapter/commands/ssl_setup_command.py +234 -351
  21. mcp_proxy_adapter/commands/token_management_command.py +1 -1
  22. mcp_proxy_adapter/config.py +323 -40
  23. mcp_proxy_adapter/core/app_factory.py +410 -0
  24. mcp_proxy_adapter/core/app_runner.py +272 -0
  25. mcp_proxy_adapter/core/certificate_utils.py +291 -73
  26. mcp_proxy_adapter/core/client.py +574 -0
  27. mcp_proxy_adapter/core/client_manager.py +284 -0
  28. mcp_proxy_adapter/core/client_security.py +384 -0
  29. mcp_proxy_adapter/core/logging.py +8 -3
  30. mcp_proxy_adapter/core/mtls_asgi.py +156 -0
  31. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  32. mcp_proxy_adapter/core/protocol_manager.py +169 -10
  33. mcp_proxy_adapter/core/proxy_client.py +602 -0
  34. mcp_proxy_adapter/core/proxy_registration.py +299 -47
  35. mcp_proxy_adapter/core/security_adapter.py +12 -15
  36. mcp_proxy_adapter/core/security_integration.py +286 -0
  37. mcp_proxy_adapter/core/server_adapter.py +282 -0
  38. mcp_proxy_adapter/core/server_engine.py +270 -0
  39. mcp_proxy_adapter/core/ssl_utils.py +13 -12
  40. mcp_proxy_adapter/core/transport_manager.py +5 -5
  41. mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
  42. mcp_proxy_adapter/examples/__init__.py +13 -4
  43. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  44. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  45. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  46. mcp_proxy_adapter/examples/basic_framework/main.py +44 -0
  47. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  48. mcp_proxy_adapter/examples/create_certificates_simple.py +550 -0
  49. mcp_proxy_adapter/examples/debug_request_state.py +112 -0
  50. mcp_proxy_adapter/examples/debug_role_chain.py +158 -0
  51. mcp_proxy_adapter/examples/demo_client.py +275 -0
  52. mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
  53. mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
  54. mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
  55. mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
  56. mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
  57. mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
  58. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
  59. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  60. mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
  61. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
  62. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  63. mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
  64. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
  65. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  66. mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
  67. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +80 -0
  68. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  69. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
  70. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +75 -0
  71. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  72. mcp_proxy_adapter/examples/full_application/main.py +173 -0
  73. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
  74. mcp_proxy_adapter/examples/generate_all_certificates.py +362 -0
  75. mcp_proxy_adapter/examples/generate_certificates.py +177 -0
  76. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
  77. mcp_proxy_adapter/examples/generate_test_configs.py +331 -0
  78. mcp_proxy_adapter/examples/proxy_registration_example.py +334 -0
  79. mcp_proxy_adapter/examples/run_example.py +59 -0
  80. mcp_proxy_adapter/examples/run_full_test_suite.py +318 -0
  81. mcp_proxy_adapter/examples/run_proxy_server.py +146 -0
  82. mcp_proxy_adapter/examples/run_security_tests.py +544 -0
  83. mcp_proxy_adapter/examples/run_security_tests_fixed.py +247 -0
  84. mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
  85. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
  86. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
  87. mcp_proxy_adapter/examples/security_test_client.py +782 -0
  88. mcp_proxy_adapter/examples/setup_test_environment.py +328 -0
  89. mcp_proxy_adapter/examples/test_config.py +148 -0
  90. mcp_proxy_adapter/examples/test_config_generator.py +86 -0
  91. mcp_proxy_adapter/examples/test_examples.py +281 -0
  92. mcp_proxy_adapter/examples/universal_client.py +620 -0
  93. mcp_proxy_adapter/main.py +66 -148
  94. mcp_proxy_adapter/utils/config_generator.py +1008 -0
  95. mcp_proxy_adapter/version.py +5 -2
  96. mcp_proxy_adapter-6.0.1.dist-info/METADATA +679 -0
  97. mcp_proxy_adapter-6.0.1.dist-info/RECORD +140 -0
  98. mcp_proxy_adapter-6.0.1.dist-info/entry_points.txt +2 -0
  99. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/licenses/LICENSE +2 -2
  100. mcp_proxy_adapter/api/middleware/auth.py +0 -146
  101. mcp_proxy_adapter/api/middleware/auth_adapter.py +0 -235
  102. mcp_proxy_adapter/api/middleware/mtls_adapter.py +0 -305
  103. mcp_proxy_adapter/api/middleware/mtls_middleware.py +0 -296
  104. mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
  105. mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +0 -241
  106. mcp_proxy_adapter/api/middleware/roles_adapter.py +0 -365
  107. mcp_proxy_adapter/api/middleware/roles_middleware.py +0 -381
  108. mcp_proxy_adapter/api/middleware/security.py +0 -376
  109. mcp_proxy_adapter/api/middleware/token_auth_middleware.py +0 -261
  110. mcp_proxy_adapter/examples/README.md +0 -124
  111. mcp_proxy_adapter/examples/basic_server/README.md +0 -60
  112. mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
  113. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
  114. mcp_proxy_adapter/examples/basic_server/config.json +0 -70
  115. mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +0 -54
  116. mcp_proxy_adapter/examples/basic_server/config_http.json +0 -70
  117. mcp_proxy_adapter/examples/basic_server/config_http_only.json +0 -52
  118. mcp_proxy_adapter/examples/basic_server/config_https.json +0 -58
  119. mcp_proxy_adapter/examples/basic_server/config_mtls.json +0 -58
  120. mcp_proxy_adapter/examples/basic_server/config_ssl.json +0 -46
  121. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
  122. mcp_proxy_adapter/examples/basic_server/server.py +0 -114
  123. mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
  124. mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
  125. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -566
  126. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
  127. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
  128. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
  129. mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +0 -105
  130. mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +0 -129
  131. mcp_proxy_adapter/examples/custom_commands/config.json +0 -118
  132. mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +0 -46
  133. mcp_proxy_adapter/examples/custom_commands/config_https_only.json +0 -46
  134. mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +0 -33
  135. mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +0 -46
  136. mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +0 -33
  137. mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +0 -33
  138. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
  139. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
  140. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
  141. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
  142. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
  143. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
  144. mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
  145. mcp_proxy_adapter/examples/custom_commands/full_help_response.json +0 -1
  146. mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +0 -629
  147. mcp_proxy_adapter/examples/custom_commands/get_openapi.py +0 -103
  148. mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
  149. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
  150. mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +0 -129
  151. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
  152. mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +0 -278
  153. mcp_proxy_adapter/examples/custom_commands/server.py +0 -252
  154. mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +0 -75
  155. mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +0 -299
  156. mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +0 -278
  157. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
  158. mcp_proxy_adapter/examples/custom_commands/test_openapi.py +0 -27
  159. mcp_proxy_adapter/examples/custom_commands/test_registry.py +0 -23
  160. mcp_proxy_adapter/examples/custom_commands/test_simple.py +0 -19
  161. mcp_proxy_adapter/examples/custom_project_example/README.md +0 -103
  162. mcp_proxy_adapter/examples/custom_project_example/README_EN.md +0 -103
  163. mcp_proxy_adapter/examples/deployment/README.md +0 -49
  164. mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
  165. mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
  166. mcp_proxy_adapter/examples/deployment/config.json +0 -29
  167. mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
  168. mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
  169. mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
  170. mcp_proxy_adapter/examples/deployment/run.sh +0 -43
  171. mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
  172. mcp_proxy_adapter/examples/simple_custom_commands/README.md +0 -149
  173. mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +0 -149
  174. mcp_proxy_adapter/schemas/base_schema.json +0 -114
  175. mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
  176. mcp_proxy_adapter/schemas/roles_schema.json +0 -162
  177. mcp_proxy_adapter/tests/__init__.py +0 -0
  178. mcp_proxy_adapter/tests/api/__init__.py +0 -3
  179. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
  180. mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
  181. mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
  182. mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
  183. mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
  184. mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
  185. mcp_proxy_adapter/tests/commands/__init__.py +0 -3
  186. mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
  187. mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
  188. mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
  189. mcp_proxy_adapter/tests/conftest.py +0 -131
  190. mcp_proxy_adapter/tests/functional/__init__.py +0 -3
  191. mcp_proxy_adapter/tests/functional/test_api.py +0 -253
  192. mcp_proxy_adapter/tests/integration/__init__.py +0 -3
  193. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
  194. mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
  195. mcp_proxy_adapter/tests/performance/__init__.py +0 -3
  196. mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
  197. mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
  198. mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
  199. mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
  200. mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
  201. mcp_proxy_adapter/tests/test_base_command.py +0 -123
  202. mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
  203. mcp_proxy_adapter/tests/test_command_registry.py +0 -281
  204. mcp_proxy_adapter/tests/test_config.py +0 -127
  205. mcp_proxy_adapter/tests/test_utils.py +0 -65
  206. mcp_proxy_adapter/tests/unit/__init__.py +0 -3
  207. mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
  208. mcp_proxy_adapter/tests/unit/test_config.py +0 -270
  209. mcp_proxy_adapter-6.0.0.dist-info/METADATA +0 -201
  210. mcp_proxy_adapter-6.0.0.dist-info/RECORD +0 -179
  211. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/WHEEL +0 -0
  212. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,362 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Generate All Certificates for Security Testing
4
+ This script generates all necessary certificates for comprehensive security testing:
5
+ - Root CA certificate and key
6
+ - Server certificates for HTTPS and mTLS
7
+ - Client certificates for different roles (admin, user, readonly, etc.)
8
+ - Test certificates for negative scenarios
9
+ Author: Vasiliy Zdanovskiy
10
+ email: vasilyvz@gmail.com
11
+ """
12
+ import json
13
+ import os
14
+ import subprocess
15
+ import sys
16
+ from pathlib import Path
17
+ from typing import Dict, List, Optional
18
+ class CertificateGenerator:
19
+ """Generate all certificates for security testing."""
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
+ # Create directories if they don't exist
25
+ self.certs_dir.mkdir(parents=True, exist_ok=True)
26
+ self.keys_dir.mkdir(parents=True, exist_ok=True)
27
+ # Certificate configuration
28
+ self.ca_config = {
29
+ "common_name": "MCP Proxy Adapter Test CA",
30
+ "organization": "Test Organization",
31
+ "country": "US",
32
+ "state": "Test State",
33
+ "city": "Test City",
34
+ "validity_years": 10
35
+ }
36
+ self.server_config = {
37
+ "common_name": "mcp-proxy-adapter-test.local",
38
+ "organization": "Test Organization",
39
+ "country": "US",
40
+ "state": "Test State",
41
+ "city": "Test City",
42
+ "validity_years": 2,
43
+ "san": ["localhost", "127.0.0.1", "mcp-proxy-adapter-test.local"]
44
+ }
45
+ # Client certificates configuration
46
+ self.client_certs = {
47
+ "admin": {
48
+ "common_name": "admin-client",
49
+ "organization": "Test Organization",
50
+ "roles": ["admin"],
51
+ "permissions": ["*"]
52
+ },
53
+ "user": {
54
+ "common_name": "user-client",
55
+ "organization": "Test Organization",
56
+ "roles": ["user"],
57
+ "permissions": ["read", "write"]
58
+ },
59
+ "readonly": {
60
+ "common_name": "readonly-client",
61
+ "organization": "Test Organization",
62
+ "roles": ["readonly"],
63
+ "permissions": ["read"]
64
+ },
65
+ "guest": {
66
+ "common_name": "guest-client",
67
+ "organization": "Test Organization",
68
+ "roles": ["guest"],
69
+ "permissions": ["read"]
70
+ },
71
+ "proxy": {
72
+ "common_name": "proxy-client",
73
+ "organization": "Test Organization",
74
+ "roles": ["proxy"],
75
+ "permissions": ["register", "discover"]
76
+ }
77
+ }
78
+ # Negative test certificates
79
+ self.negative_certs = {
80
+ "expired": {
81
+ "common_name": "expired-client",
82
+ "organization": "Test Organization",
83
+ "validity_days": 1 # Will expire quickly
84
+ },
85
+ "wrong_org": {
86
+ "common_name": "wrong-org-client",
87
+ "organization": "Wrong Organization",
88
+ "roles": ["user"]
89
+ },
90
+ "no_roles": {
91
+ "common_name": "no-roles-client",
92
+ "organization": "Test Organization",
93
+ "roles": []
94
+ },
95
+ "invalid_roles": {
96
+ "common_name": "invalid-roles-client",
97
+ "organization": "Test Organization",
98
+ "roles": ["invalid_role"]
99
+ }
100
+ }
101
+ def run_command(self, cmd: List[str], description: str) -> bool:
102
+ """Run a command and handle errors."""
103
+ try:
104
+ print(f"🔧 {description}...")
105
+ result = subprocess.run(
106
+ cmd,
107
+ cwd=self.project_root,
108
+ capture_output=True,
109
+ text=True,
110
+ check=True
111
+ )
112
+ print(f"✅ {description} completed successfully")
113
+ return True
114
+ except subprocess.CalledProcessError as e:
115
+ print(f"❌ {description} failed:")
116
+ print(f" Command: {' '.join(cmd)}")
117
+ print(f" Error: {e.stderr}")
118
+ return False
119
+ except Exception as e:
120
+ print(f"❌ {description} failed: {e}")
121
+ return False
122
+ def create_ca_certificate(self) -> bool:
123
+ """Create Root CA certificate and key."""
124
+ ca_cert_path = self.certs_dir / "ca_cert.pem"
125
+ ca_key_path = self.keys_dir / "ca_key.pem"
126
+ if ca_cert_path.exists() and ca_key_path.exists():
127
+ print(f"ℹ️ CA certificate already exists: {ca_cert_path}")
128
+ return True
129
+ cmd = [
130
+ sys.executable, "-m", "mcp_security_framework.cli.cert_cli", "create-ca",
131
+ "-cn", self.ca_config["common_name"],
132
+ "-o", self.ca_config["organization"],
133
+ "-c", self.ca_config["country"],
134
+ "-s", self.ca_config["state"],
135
+ "-l", self.ca_config["city"],
136
+ "-y", str(self.ca_config["validity_years"])
137
+ ]
138
+ success = self.run_command(cmd, "Creating Root CA certificate")
139
+ if success:
140
+ # Move files to correct locations
141
+ default_ca_cert = Path("./certs") / f"{self.ca_config['common_name'].lower().replace(' ', '_')}_ca.crt"
142
+ default_ca_key = Path("./keys") / f"{self.ca_config['common_name'].lower().replace(' ', '_')}_ca.key"
143
+ if default_ca_cert.exists():
144
+ self.run_command(["mv", str(default_ca_cert), str(ca_cert_path)], "Moving CA certificate")
145
+ if default_ca_key.exists():
146
+ self.run_command(["mv", str(default_ca_key), str(ca_key_path)], "Moving CA key")
147
+ return success
148
+ def create_server_certificate(self) -> bool:
149
+ """Create server certificate for HTTPS and mTLS."""
150
+ server_cert_path = self.certs_dir / "server_cert.pem"
151
+ server_key_path = self.certs_dir / "server_key.pem"
152
+ if server_cert_path.exists() and server_key_path.exists():
153
+ print(f"ℹ️ Server certificate already exists: {server_cert_path}")
154
+ return True
155
+ # Create server certificate
156
+ cmd = [
157
+ sys.executable, "-m", "mcp_security_framework.cli.cert_cli", "create-server",
158
+ "-cn", self.server_config["common_name"],
159
+ "-o", self.server_config["organization"],
160
+ "-c", self.server_config["country"],
161
+ "-s", self.server_config["state"],
162
+ "-l", self.server_config["city"],
163
+ "-d", str(self.server_config["validity_years"] * 365) # Convert years to days
164
+ ]
165
+ # Add SAN if supported
166
+ if self.server_config["san"]:
167
+ for san in self.server_config["san"]:
168
+ cmd.extend(["--san", san])
169
+ success = self.run_command(cmd, "Creating server certificate")
170
+ if success:
171
+ # Move files to correct locations
172
+ default_server_cert = Path("./certs") / f"{self.server_config['common_name'].lower().replace('.', '_')}_server.crt"
173
+ default_server_key = Path("./keys") / f"{self.server_config['common_name'].lower().replace('.', '_')}_server.key"
174
+ if default_server_cert.exists():
175
+ self.run_command(["mv", str(default_server_cert), str(server_cert_path)], "Moving server certificate")
176
+ if default_server_key.exists():
177
+ self.run_command(["mv", str(default_server_key), str(server_key_path)], "Moving server key")
178
+ return success
179
+ def create_client_certificate(self, name: str, config: Dict) -> bool:
180
+ """Create client certificate with specific configuration."""
181
+ cert_path = self.certs_dir / f"{name}_cert.pem"
182
+ key_path = self.certs_dir / f"{name}_key.pem"
183
+ if cert_path.exists() and key_path.exists():
184
+ print(f"ℹ️ Client certificate {name} already exists: {cert_path}")
185
+ return True
186
+ cmd = [
187
+ sys.executable, "-m", "mcp_security_framework.cli.cert_cli", "create-client",
188
+ "-cn", config["common_name"],
189
+ "-o", config["organization"],
190
+ "-c", self.ca_config["country"],
191
+ "-s", self.ca_config["state"],
192
+ "-l", self.ca_config["city"],
193
+ "-d", "730" # 2 years in days
194
+ ]
195
+ # Add roles if specified
196
+ if "roles" in config and config["roles"]:
197
+ for role in config["roles"]:
198
+ cmd.extend(["--roles", role])
199
+ # Add permissions if specified
200
+ if "permissions" in config and config["permissions"]:
201
+ for permission in config["permissions"]:
202
+ cmd.extend(["--permissions", permission])
203
+ # Add custom validity for negative tests
204
+ if "validity_days" in config:
205
+ cmd[cmd.index("-d") + 1] = str(config["validity_days"])
206
+ success = self.run_command(cmd, f"Creating client certificate: {name}")
207
+ if success:
208
+ # Move files to correct locations
209
+ default_client_cert = Path("./certs") / f"{config['common_name'].lower().replace('-', '_')}_client.crt"
210
+ default_client_key = Path("./keys") / f"{config['common_name'].lower().replace('-', '_')}_client.key"
211
+ if default_client_cert.exists():
212
+ self.run_command(["mv", str(default_client_cert), str(cert_path)], f"Moving {name} certificate")
213
+ if default_client_key.exists():
214
+ self.run_command(["mv", str(default_client_key), str(key_path)], f"Moving {name} key")
215
+ return success
216
+ def create_legacy_certificates(self) -> bool:
217
+ """Create legacy certificate files for compatibility."""
218
+ legacy_files = [
219
+ ("client.crt", "client.key"),
220
+ ("client_admin.crt", "client_admin.key"),
221
+ ("admin.crt", "admin.key"),
222
+ ("user.crt", "user.key"),
223
+ ("readonly.crt", "readonly.key")
224
+ ]
225
+ success = True
226
+ for cert_file, key_file in legacy_files:
227
+ cert_path = self.certs_dir / cert_file
228
+ key_path = self.certs_dir / key_file
229
+ if not cert_path.exists() or not key_path.exists():
230
+ # Copy from existing certificates
231
+ if cert_file == "client.crt" and (self.certs_dir / "user_cert.pem").exists():
232
+ self.run_command(["cp", str(self.certs_dir / "user_cert.pem"), str(cert_path)], f"Creating {cert_file}")
233
+ self.run_command(["cp", str(self.certs_dir / "user_key.pem"), str(key_path)], f"Creating {key_file}")
234
+ elif cert_file == "client_admin.crt" and (self.certs_dir / "admin_cert.pem").exists():
235
+ self.run_command(["cp", str(self.certs_dir / "admin_cert.pem"), str(cert_path)], f"Creating {cert_file}")
236
+ self.run_command(["cp", str(self.certs_dir / "admin_key.pem"), str(key_path)], f"Creating {key_file}")
237
+ elif cert_file == "admin.crt" and (self.certs_dir / "admin_cert.pem").exists():
238
+ self.run_command(["cp", str(self.certs_dir / "admin_cert.pem"), str(cert_path)], f"Creating {cert_file}")
239
+ self.run_command(["cp", str(self.certs_dir / "admin_key.pem"), str(key_path)], f"Creating {key_file}")
240
+ elif cert_file == "user.crt" and (self.certs_dir / "user_cert.pem").exists():
241
+ self.run_command(["cp", str(self.certs_dir / "user_cert.pem"), str(cert_path)], f"Creating {cert_file}")
242
+ self.run_command(["cp", str(self.certs_dir / "user_key.pem"), str(key_path)], f"Creating {key_file}")
243
+ elif cert_file == "readonly.crt" and (self.certs_dir / "readonly_cert.pem").exists():
244
+ self.run_command(["cp", str(self.certs_dir / "readonly_cert.pem"), str(cert_path)], f"Creating {cert_file}")
245
+ self.run_command(["cp", str(self.certs_dir / "readonly_key.pem"), str(key_path)], f"Creating {key_file}")
246
+ return success
247
+ def create_certificate_config(self) -> bool:
248
+ """Create certificate configuration file."""
249
+ config_path = self.certs_dir / "cert_config.json"
250
+ config = {
251
+ "ca_cert_path": str(self.certs_dir / "ca_cert.pem"),
252
+ "ca_key_path": str(self.keys_dir / "ca_key.pem"),
253
+ "cert_storage_path": str(self.certs_dir),
254
+ "key_storage_path": str(self.keys_dir),
255
+ "default_validity_days": 365,
256
+ "key_size": 2048,
257
+ "hash_algorithm": "sha256"
258
+ }
259
+ try:
260
+ with open(config_path, 'w') as f:
261
+ json.dump(config, f, indent=2)
262
+ print(f"✅ Created certificate config: {config_path}")
263
+ return True
264
+ except Exception as e:
265
+ print(f"❌ Failed to create certificate config: {e}")
266
+ return False
267
+ def validate_certificates(self) -> bool:
268
+ """Validate all created certificates."""
269
+ print("\n🔍 Validating certificates...")
270
+ cert_files = [
271
+ "ca_cert.pem",
272
+ "server_cert.pem",
273
+ "admin_cert.pem",
274
+ "user_cert.pem",
275
+ "readonly_cert.pem",
276
+ "guest_cert.pem",
277
+ "proxy_cert.pem"
278
+ ]
279
+ success = True
280
+ for cert_file in cert_files:
281
+ cert_path = self.certs_dir / cert_file
282
+ if cert_path.exists():
283
+ try:
284
+ result = subprocess.run(
285
+ ["openssl", "x509", "-in", str(cert_path), "-text", "-noout"],
286
+ capture_output=True,
287
+ text=True,
288
+ check=True
289
+ )
290
+ print(f"✅ {cert_file}: Valid")
291
+ except subprocess.CalledProcessError:
292
+ print(f"❌ {cert_file}: Invalid")
293
+ success = False
294
+ else:
295
+ print(f"⚠️ {cert_file}: Not found")
296
+ return success
297
+ def generate_all(self) -> bool:
298
+ """Generate all certificates."""
299
+ print("🔐 Generating All Certificates for Security Testing")
300
+ print("=" * 60)
301
+ success = True
302
+ # 1. Create CA certificate
303
+ if not self.create_ca_certificate():
304
+ success = False
305
+ print("❌ Cannot continue without CA certificate")
306
+ return False
307
+ # 2. Create server certificate
308
+ if not self.create_server_certificate():
309
+ success = False
310
+ # 3. Create client certificates for different roles
311
+ print("\n👥 Creating client certificates...")
312
+ for name, config in self.client_certs.items():
313
+ if not self.create_client_certificate(name, config):
314
+ success = False
315
+ # 4. Create negative test certificates
316
+ print("\n🚫 Creating negative test certificates...")
317
+ for name, config in self.negative_certs.items():
318
+ if not self.create_client_certificate(name, config):
319
+ success = False
320
+ # 5. Create legacy certificates for compatibility
321
+ print("\n🔄 Creating legacy certificates...")
322
+ if not self.create_legacy_certificates():
323
+ success = False
324
+ # 6. Create certificate configuration
325
+ if not self.create_certificate_config():
326
+ success = False
327
+ # 7. Validate certificates
328
+ if not self.validate_certificates():
329
+ success = False
330
+ # Print summary
331
+ print("\n" + "=" * 60)
332
+ print("📊 CERTIFICATE GENERATION SUMMARY")
333
+ print("=" * 60)
334
+ if success:
335
+ print("✅ All certificates generated successfully!")
336
+ print(f"📁 Certificates directory: {self.certs_dir}")
337
+ print(f"🔑 Keys directory: {self.keys_dir}")
338
+ print("\n📋 Generated certificates:")
339
+ cert_files = list(self.certs_dir.glob("*.pem")) + list(self.certs_dir.glob("*.crt"))
340
+ for cert_file in sorted(cert_files):
341
+ print(f" - {cert_file.name}")
342
+ key_files = list(self.keys_dir.glob("*.pem")) + list(self.keys_dir.glob("*.key"))
343
+ for key_file in sorted(key_files):
344
+ print(f" - {key_file.name}")
345
+ else:
346
+ print("❌ Some certificates failed to generate")
347
+ print("Check the error messages above")
348
+ return success
349
+ def main():
350
+ """Main function."""
351
+ generator = CertificateGenerator()
352
+ try:
353
+ success = generator.generate_all()
354
+ sys.exit(0 if success else 1)
355
+ except KeyboardInterrupt:
356
+ print("\n⚠️ Certificate generation interrupted by user")
357
+ sys.exit(1)
358
+ except Exception as e:
359
+ print(f"\n❌ Certificate generation failed: {e}")
360
+ sys.exit(1)
361
+ if __name__ == "__main__":
362
+ main()
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Certificate Generation Script
4
+ This script generates all necessary certificates for the examples using
5
+ mcp_security_framework API directly.
6
+ Author: Vasiliy Zdanovskiy
7
+ email: vasilyvz@gmail.com
8
+ """
9
+ import os
10
+ import sys
11
+ from pathlib import Path
12
+ from datetime import datetime, timedelta, timezone
13
+
14
+ def main():
15
+ """Generate all certificates for examples."""
16
+ print("🔐 Certificate Generation Script")
17
+ print("=" * 50)
18
+
19
+ # Create directories
20
+ cert_dir = Path("certs")
21
+ key_dir = Path("keys")
22
+ cert_dir.mkdir(exist_ok=True)
23
+ key_dir.mkdir(exist_ok=True)
24
+
25
+ # Check if mcp_security_framework is available
26
+ try:
27
+ from mcp_security_framework.core.cert_manager import CertificateManager
28
+ from mcp_security_framework.schemas import (
29
+ CAConfig, ServerCertConfig, ClientCertConfig, CertificateConfig
30
+ )
31
+ print("✅ mcp_security_framework API available")
32
+ except ImportError as e:
33
+ print(f"❌ mcp_security_framework not found: {e}")
34
+ return False
35
+
36
+ try:
37
+ print("🔧 Creating root CA certificate...")
38
+
39
+ # Initialize certificate manager first
40
+ cert_config = CertificateConfig(
41
+ cert_storage_path=str(cert_dir),
42
+ key_storage_path=str(key_dir),
43
+ default_validity_days=365,
44
+ key_size=2048,
45
+ hash_algorithm="sha256"
46
+ )
47
+ cert_manager = CertificateManager(cert_config)
48
+
49
+ # Create CA certificate using API
50
+ ca_config = CAConfig(
51
+ common_name="MCP Proxy Adapter CA",
52
+ organization="MCP Proxy Adapter",
53
+ organizational_unit="Development",
54
+ country="US",
55
+ state="State",
56
+ locality="City",
57
+ validity_years=10,
58
+ key_size=2048,
59
+ hash_algorithm="sha256"
60
+ )
61
+
62
+ ca_cert_pair = cert_manager.create_root_ca(ca_config)
63
+ if not ca_cert_pair or not ca_cert_pair.certificate_path:
64
+ print("❌ Failed to create CA certificate")
65
+ return False
66
+
67
+ ca_cert_path = ca_cert_pair.certificate_path
68
+ ca_key_path = ca_cert_pair.private_key_path
69
+ print(f"✅ Root CA certificate created: {ca_cert_path}")
70
+
71
+ print("🔧 Creating server certificate...")
72
+ # Create server certificate
73
+ server_config = ServerCertConfig(
74
+ common_name="localhost",
75
+ organization="MCP Proxy Adapter",
76
+ country="US",
77
+ validity_days=365,
78
+ key_size=2048,
79
+ subject_alt_names=["localhost", "127.0.0.1"],
80
+ ca_cert_path=str(ca_cert_path),
81
+ ca_key_path=str(ca_key_path)
82
+ )
83
+
84
+ server_cert_pair = cert_manager.create_server_certificate(server_config)
85
+ print(f"✅ Server certificate created: {server_cert_pair.certificate_path}")
86
+
87
+ print("🔧 Creating admin client certificate...")
88
+ # Create admin client certificate
89
+ admin_config = ClientCertConfig(
90
+ common_name="admin",
91
+ organization="MCP Proxy Adapter",
92
+ country="US",
93
+ validity_days=365,
94
+ key_size=2048,
95
+ roles=["admin"],
96
+ permissions=["read", "write", "delete"],
97
+ ca_cert_path=str(ca_cert_path),
98
+ ca_key_path=str(ca_key_path)
99
+ )
100
+
101
+ admin_cert_pair = cert_manager.create_client_certificate(admin_config)
102
+ print(f"✅ Admin client certificate created: {admin_cert_pair.certificate_path}")
103
+
104
+ print("🔧 Creating user client certificate...")
105
+ # Create user client certificate
106
+ user_config = ClientCertConfig(
107
+ common_name="user",
108
+ organization="MCP Proxy Adapter",
109
+ country="US",
110
+ validity_days=365,
111
+ key_size=2048,
112
+ roles=["user"],
113
+ permissions=["read", "write"],
114
+ ca_cert_path=str(ca_cert_path),
115
+ ca_key_path=str(ca_key_path)
116
+ )
117
+
118
+ user_cert_pair = cert_manager.create_client_certificate(user_config)
119
+ print(f"✅ User client certificate created: {user_cert_pair.certificate_path}")
120
+
121
+ print("🔧 Creating readonly client certificate...")
122
+ # Create readonly client certificate
123
+ readonly_config = ClientCertConfig(
124
+ common_name="readonly",
125
+ organization="MCP Proxy Adapter",
126
+ country="US",
127
+ validity_days=365,
128
+ key_size=2048,
129
+ roles=["readonly"],
130
+ permissions=["read"],
131
+ ca_cert_path=str(ca_cert_path),
132
+ ca_key_path=str(ca_key_path)
133
+ )
134
+
135
+ readonly_cert_pair = cert_manager.create_client_certificate(readonly_config)
136
+ print(f"✅ Readonly client certificate created: {readonly_cert_pair.certificate_path}")
137
+
138
+ print("\n🎉 All certificates generated successfully!")
139
+ print(f"📁 Certificates are stored in the '{cert_dir}' directory")
140
+ print(f"🔑 Private keys are stored in the '{key_dir}' directory")
141
+ print(f"🔐 CA certificate: {ca_cert_path}")
142
+ print(f"🔐 Server certificate: {server_cert_pair.certificate_path}")
143
+
144
+ print("\n" + "=" * 60)
145
+ print("✅ CERTIFICATE GENERATION COMPLETED SUCCESSFULLY")
146
+ print("=" * 60)
147
+ print("\n📋 NEXT STEPS:")
148
+ print("1. Generate test configurations:")
149
+ print(" python -m mcp_proxy_adapter.examples.generate_test_configs --output-dir configs")
150
+ print("\n2. Run security tests:")
151
+ print(" python -m mcp_proxy_adapter.examples.run_security_tests")
152
+ print("\n3. Start basic framework example:")
153
+ print(" python -m mcp_proxy_adapter.examples.basic_framework.main --config configs/https_simple.json")
154
+ print("=" * 60)
155
+ return True
156
+
157
+ except Exception as e:
158
+ print(f"\n❌ CERTIFICATE GENERATION FAILED: {e}")
159
+ print("=" * 60)
160
+ import traceback
161
+ traceback.print_exc()
162
+ print("\n🔧 TROUBLESHOOTING:")
163
+ print("1. Check if mcp_security_framework is installed:")
164
+ print(" pip install mcp_security_framework")
165
+ print("\n2. Verify write permissions in current directory")
166
+ print("\n3. Check if certs/ and keys/ directories exist")
167
+ print("=" * 60)
168
+ return False
169
+
170
+ if __name__ == "__main__":
171
+ print("🔐 Starting certificate generation...")
172
+ success = main()
173
+ if success:
174
+ print("\n✅ Script completed successfully!")
175
+ else:
176
+ print("\n❌ Script failed with errors!")
177
+ sys.exit(0 if success else 1)