mcp-proxy-adapter 6.3.4__py3-none-any.whl ā 6.3.6__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.
- mcp_proxy_adapter/__init__.py +9 -5
- mcp_proxy_adapter/__main__.py +1 -1
- mcp_proxy_adapter/api/app.py +227 -176
- mcp_proxy_adapter/api/handlers.py +68 -60
- mcp_proxy_adapter/api/middleware/__init__.py +7 -5
- mcp_proxy_adapter/api/middleware/base.py +19 -16
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
- mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
- mcp_proxy_adapter/api/middleware/factory.py +50 -52
- mcp_proxy_adapter/api/middleware/logging.py +46 -30
- mcp_proxy_adapter/api/middleware/performance.py +19 -16
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
- mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
- mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
- mcp_proxy_adapter/api/schemas.py +69 -43
- mcp_proxy_adapter/api/tool_integration.py +83 -63
- mcp_proxy_adapter/api/tools.py +60 -50
- mcp_proxy_adapter/commands/__init__.py +15 -6
- mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
- mcp_proxy_adapter/commands/base.py +108 -112
- mcp_proxy_adapter/commands/builtin_commands.py +28 -18
- mcp_proxy_adapter/commands/catalog_manager.py +394 -265
- mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
- mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
- mcp_proxy_adapter/commands/command_registry.py +275 -226
- mcp_proxy_adapter/commands/config_command.py +48 -33
- mcp_proxy_adapter/commands/dependency_container.py +22 -23
- mcp_proxy_adapter/commands/dependency_manager.py +65 -56
- mcp_proxy_adapter/commands/echo_command.py +15 -15
- mcp_proxy_adapter/commands/health_command.py +31 -29
- mcp_proxy_adapter/commands/help_command.py +97 -61
- mcp_proxy_adapter/commands/hooks.py +65 -49
- mcp_proxy_adapter/commands/key_management_command.py +148 -147
- mcp_proxy_adapter/commands/load_command.py +58 -40
- mcp_proxy_adapter/commands/plugins_command.py +80 -54
- mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
- mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
- mcp_proxy_adapter/commands/reload_command.py +43 -37
- mcp_proxy_adapter/commands/result.py +26 -33
- mcp_proxy_adapter/commands/role_test_command.py +26 -26
- mcp_proxy_adapter/commands/roles_management_command.py +176 -173
- mcp_proxy_adapter/commands/security_command.py +134 -122
- mcp_proxy_adapter/commands/settings_command.py +47 -56
- mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
- mcp_proxy_adapter/commands/token_management_command.py +129 -158
- mcp_proxy_adapter/commands/transport_management_command.py +41 -36
- mcp_proxy_adapter/commands/unload_command.py +42 -37
- mcp_proxy_adapter/config.py +36 -35
- mcp_proxy_adapter/core/__init__.py +19 -21
- mcp_proxy_adapter/core/app_factory.py +30 -9
- mcp_proxy_adapter/core/app_runner.py +81 -64
- mcp_proxy_adapter/core/auth_validator.py +176 -182
- mcp_proxy_adapter/core/certificate_utils.py +469 -426
- mcp_proxy_adapter/core/client.py +155 -126
- mcp_proxy_adapter/core/client_manager.py +60 -54
- mcp_proxy_adapter/core/client_security.py +120 -91
- mcp_proxy_adapter/core/config_converter.py +176 -143
- mcp_proxy_adapter/core/config_validator.py +12 -4
- mcp_proxy_adapter/core/crl_utils.py +21 -7
- mcp_proxy_adapter/core/errors.py +64 -20
- mcp_proxy_adapter/core/logging.py +34 -29
- mcp_proxy_adapter/core/mtls_asgi.py +29 -25
- mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
- mcp_proxy_adapter/core/protocol_manager.py +154 -104
- mcp_proxy_adapter/core/proxy_client.py +202 -144
- mcp_proxy_adapter/core/proxy_registration.py +7 -3
- mcp_proxy_adapter/core/role_utils.py +139 -125
- mcp_proxy_adapter/core/security_adapter.py +88 -77
- mcp_proxy_adapter/core/security_factory.py +50 -44
- mcp_proxy_adapter/core/security_integration.py +72 -24
- mcp_proxy_adapter/core/server_adapter.py +68 -64
- mcp_proxy_adapter/core/server_engine.py +71 -53
- mcp_proxy_adapter/core/settings.py +68 -58
- mcp_proxy_adapter/core/ssl_utils.py +69 -56
- mcp_proxy_adapter/core/transport_manager.py +72 -60
- mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
- mcp_proxy_adapter/core/utils.py +4 -2
- mcp_proxy_adapter/custom_openapi.py +107 -99
- mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/commands/__init__.py +1 -1
- mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
- mcp_proxy_adapter/examples/debug_request_state.py +38 -19
- mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
- mcp_proxy_adapter/examples/demo_client.py +48 -36
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
- mcp_proxy_adapter/examples/generate_certificates.py +31 -16
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
- mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
- mcp_proxy_adapter/examples/run_example.py +23 -5
- mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
- mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
- mcp_proxy_adapter/examples/run_security_tests.py +103 -41
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
- mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/security_test_client.py +196 -127
- mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
- mcp_proxy_adapter/examples/test_config.py +19 -4
- mcp_proxy_adapter/examples/test_config_generator.py +23 -7
- mcp_proxy_adapter/examples/test_examples.py +84 -56
- mcp_proxy_adapter/examples/universal_client.py +119 -62
- mcp_proxy_adapter/openapi.py +108 -115
- mcp_proxy_adapter/utils/config_generator.py +429 -274
- mcp_proxy_adapter/version.py +1 -2
- {mcp_proxy_adapter-6.3.4.dist-info ā mcp_proxy_adapter-6.3.6.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.3.6.dist-info/RECORD +144 -0
- mcp_proxy_adapter-6.3.6.dist-info/top_level.txt +2 -0
- mcp_proxy_adapter_issue_package/demonstrate_issue.py +178 -0
- mcp_proxy_adapter-6.3.4.dist-info/RECORD +0 -143
- mcp_proxy_adapter-6.3.4.dist-info/top_level.txt +0 -1
- {mcp_proxy_adapter-6.3.4.dist-info ā mcp_proxy_adapter-6.3.6.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info ā mcp_proxy_adapter-6.3.6.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info ā mcp_proxy_adapter-6.3.6.dist-info}/licenses/LICENSE +0 -0
@@ -15,8 +15,11 @@ import subprocess
|
|
15
15
|
import sys
|
16
16
|
from pathlib import Path
|
17
17
|
from typing import Dict, List, Optional
|
18
|
+
|
19
|
+
|
18
20
|
class CertificateGenerator:
|
19
21
|
"""Generate all certificates for security testing."""
|
22
|
+
|
20
23
|
def __init__(self):
|
21
24
|
self.project_root = Path(__file__).parent.parent.parent
|
22
25
|
self.certs_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "certs"
|
@@ -31,7 +34,7 @@ class CertificateGenerator:
|
|
31
34
|
"country": "US",
|
32
35
|
"state": "Test State",
|
33
36
|
"city": "Test City",
|
34
|
-
"validity_years": 10
|
37
|
+
"validity_years": 10,
|
35
38
|
}
|
36
39
|
self.server_config = {
|
37
40
|
"common_name": "mcp-proxy-adapter-test.local",
|
@@ -40,7 +43,7 @@ class CertificateGenerator:
|
|
40
43
|
"state": "Test State",
|
41
44
|
"city": "Test City",
|
42
45
|
"validity_years": 2,
|
43
|
-
"san": ["localhost", "127.0.0.1", "mcp-proxy-adapter-test.local"]
|
46
|
+
"san": ["localhost", "127.0.0.1", "mcp-proxy-adapter-test.local"],
|
44
47
|
}
|
45
48
|
# Client certificates configuration
|
46
49
|
self.client_certs = {
|
@@ -48,66 +51,63 @@ class CertificateGenerator:
|
|
48
51
|
"common_name": "admin-client",
|
49
52
|
"organization": "Test Organization",
|
50
53
|
"roles": ["admin"],
|
51
|
-
"permissions": ["*"]
|
54
|
+
"permissions": ["*"],
|
52
55
|
},
|
53
56
|
"user": {
|
54
57
|
"common_name": "user-client",
|
55
58
|
"organization": "Test Organization",
|
56
59
|
"roles": ["user"],
|
57
|
-
"permissions": ["read", "write"]
|
60
|
+
"permissions": ["read", "write"],
|
58
61
|
},
|
59
62
|
"readonly": {
|
60
63
|
"common_name": "readonly-client",
|
61
64
|
"organization": "Test Organization",
|
62
65
|
"roles": ["readonly"],
|
63
|
-
"permissions": ["read"]
|
66
|
+
"permissions": ["read"],
|
64
67
|
},
|
65
68
|
"guest": {
|
66
69
|
"common_name": "guest-client",
|
67
70
|
"organization": "Test Organization",
|
68
71
|
"roles": ["guest"],
|
69
|
-
"permissions": ["read"]
|
72
|
+
"permissions": ["read"],
|
70
73
|
},
|
71
74
|
"proxy": {
|
72
75
|
"common_name": "proxy-client",
|
73
76
|
"organization": "Test Organization",
|
74
77
|
"roles": ["proxy"],
|
75
|
-
"permissions": ["register", "discover"]
|
76
|
-
}
|
78
|
+
"permissions": ["register", "discover"],
|
79
|
+
},
|
77
80
|
}
|
78
81
|
# Negative test certificates
|
79
82
|
self.negative_certs = {
|
80
83
|
"expired": {
|
81
84
|
"common_name": "expired-client",
|
82
85
|
"organization": "Test Organization",
|
83
|
-
"validity_days": 1 # Will expire quickly
|
86
|
+
"validity_days": 1, # Will expire quickly
|
84
87
|
},
|
85
88
|
"wrong_org": {
|
86
89
|
"common_name": "wrong-org-client",
|
87
90
|
"organization": "Wrong Organization",
|
88
|
-
"roles": ["user"]
|
91
|
+
"roles": ["user"],
|
89
92
|
},
|
90
93
|
"no_roles": {
|
91
94
|
"common_name": "no-roles-client",
|
92
95
|
"organization": "Test Organization",
|
93
|
-
"roles": []
|
96
|
+
"roles": [],
|
94
97
|
},
|
95
98
|
"invalid_roles": {
|
96
99
|
"common_name": "invalid-roles-client",
|
97
100
|
"organization": "Test Organization",
|
98
|
-
"roles": ["invalid_role"]
|
99
|
-
}
|
101
|
+
"roles": ["invalid_role"],
|
102
|
+
},
|
100
103
|
}
|
104
|
+
|
101
105
|
def run_command(self, cmd: List[str], description: str) -> bool:
|
102
106
|
"""Run a command and handle errors."""
|
103
107
|
try:
|
104
108
|
print(f"š§ {description}...")
|
105
109
|
result = subprocess.run(
|
106
|
-
cmd,
|
107
|
-
cwd=self.project_root,
|
108
|
-
capture_output=True,
|
109
|
-
text=True,
|
110
|
-
check=True
|
110
|
+
cmd, cwd=self.project_root, capture_output=True, text=True, check=True
|
111
111
|
)
|
112
112
|
print(f"ā
{description} completed successfully")
|
113
113
|
return True
|
@@ -119,6 +119,7 @@ class CertificateGenerator:
|
|
119
119
|
except Exception as e:
|
120
120
|
print(f"ā {description} failed: {e}")
|
121
121
|
return False
|
122
|
+
|
122
123
|
def create_ca_certificate(self) -> bool:
|
123
124
|
"""Create Root CA certificate and key."""
|
124
125
|
ca_cert_path = self.certs_dir / "ca_cert.pem"
|
@@ -127,24 +128,45 @@ class CertificateGenerator:
|
|
127
128
|
print(f"ā¹ļø CA certificate already exists: {ca_cert_path}")
|
128
129
|
return True
|
129
130
|
cmd = [
|
130
|
-
sys.executable,
|
131
|
-
"-
|
132
|
-
"
|
133
|
-
"-
|
134
|
-
"-
|
135
|
-
|
136
|
-
"-
|
131
|
+
sys.executable,
|
132
|
+
"-m",
|
133
|
+
"mcp_security_framework.cli.cert_cli",
|
134
|
+
"create-ca",
|
135
|
+
"-cn",
|
136
|
+
self.ca_config["common_name"],
|
137
|
+
"-o",
|
138
|
+
self.ca_config["organization"],
|
139
|
+
"-c",
|
140
|
+
self.ca_config["country"],
|
141
|
+
"-s",
|
142
|
+
self.ca_config["state"],
|
143
|
+
"-l",
|
144
|
+
self.ca_config["city"],
|
145
|
+
"-y",
|
146
|
+
str(self.ca_config["validity_years"]),
|
137
147
|
]
|
138
148
|
success = self.run_command(cmd, "Creating Root CA certificate")
|
139
149
|
if success:
|
140
150
|
# Move files to correct locations
|
141
|
-
default_ca_cert =
|
142
|
-
|
151
|
+
default_ca_cert = (
|
152
|
+
Path("./certs")
|
153
|
+
/ f"{self.ca_config['common_name'].lower().replace(' ', '_')}_ca.crt"
|
154
|
+
)
|
155
|
+
default_ca_key = (
|
156
|
+
Path("./keys")
|
157
|
+
/ f"{self.ca_config['common_name'].lower().replace(' ', '_')}_ca.key"
|
158
|
+
)
|
143
159
|
if default_ca_cert.exists():
|
144
|
-
self.run_command(
|
160
|
+
self.run_command(
|
161
|
+
["mv", str(default_ca_cert), str(ca_cert_path)],
|
162
|
+
"Moving CA certificate",
|
163
|
+
)
|
145
164
|
if default_ca_key.exists():
|
146
|
-
self.run_command(
|
165
|
+
self.run_command(
|
166
|
+
["mv", str(default_ca_key), str(ca_key_path)], "Moving CA key"
|
167
|
+
)
|
147
168
|
return success
|
169
|
+
|
148
170
|
def create_server_certificate(self) -> bool:
|
149
171
|
"""Create server certificate for HTTPS and mTLS."""
|
150
172
|
server_cert_path = self.certs_dir / "server_cert.pem"
|
@@ -154,13 +176,22 @@ class CertificateGenerator:
|
|
154
176
|
return True
|
155
177
|
# Create server certificate
|
156
178
|
cmd = [
|
157
|
-
sys.executable,
|
158
|
-
"-
|
159
|
-
"
|
160
|
-
"-
|
161
|
-
"-
|
162
|
-
|
163
|
-
"-
|
179
|
+
sys.executable,
|
180
|
+
"-m",
|
181
|
+
"mcp_security_framework.cli.cert_cli",
|
182
|
+
"create-server",
|
183
|
+
"-cn",
|
184
|
+
self.server_config["common_name"],
|
185
|
+
"-o",
|
186
|
+
self.server_config["organization"],
|
187
|
+
"-c",
|
188
|
+
self.server_config["country"],
|
189
|
+
"-s",
|
190
|
+
self.server_config["state"],
|
191
|
+
"-l",
|
192
|
+
self.server_config["city"],
|
193
|
+
"-d",
|
194
|
+
str(self.server_config["validity_years"] * 365), # Convert years to days
|
164
195
|
]
|
165
196
|
# Add SAN if supported
|
166
197
|
if self.server_config["san"]:
|
@@ -169,13 +200,26 @@ class CertificateGenerator:
|
|
169
200
|
success = self.run_command(cmd, "Creating server certificate")
|
170
201
|
if success:
|
171
202
|
# Move files to correct locations
|
172
|
-
default_server_cert =
|
173
|
-
|
203
|
+
default_server_cert = (
|
204
|
+
Path("./certs")
|
205
|
+
/ f"{self.server_config['common_name'].lower().replace('.', '_')}_server.crt"
|
206
|
+
)
|
207
|
+
default_server_key = (
|
208
|
+
Path("./keys")
|
209
|
+
/ f"{self.server_config['common_name'].lower().replace('.', '_')}_server.key"
|
210
|
+
)
|
174
211
|
if default_server_cert.exists():
|
175
|
-
self.run_command(
|
212
|
+
self.run_command(
|
213
|
+
["mv", str(default_server_cert), str(server_cert_path)],
|
214
|
+
"Moving server certificate",
|
215
|
+
)
|
176
216
|
if default_server_key.exists():
|
177
|
-
self.run_command(
|
217
|
+
self.run_command(
|
218
|
+
["mv", str(default_server_key), str(server_key_path)],
|
219
|
+
"Moving server key",
|
220
|
+
)
|
178
221
|
return success
|
222
|
+
|
179
223
|
def create_client_certificate(self, name: str, config: Dict) -> bool:
|
180
224
|
"""Create client certificate with specific configuration."""
|
181
225
|
cert_path = self.certs_dir / f"{name}_cert.pem"
|
@@ -184,13 +228,22 @@ class CertificateGenerator:
|
|
184
228
|
print(f"ā¹ļø Client certificate {name} already exists: {cert_path}")
|
185
229
|
return True
|
186
230
|
cmd = [
|
187
|
-
sys.executable,
|
188
|
-
"-
|
189
|
-
"
|
190
|
-
"-
|
191
|
-
"-
|
192
|
-
|
193
|
-
"-
|
231
|
+
sys.executable,
|
232
|
+
"-m",
|
233
|
+
"mcp_security_framework.cli.cert_cli",
|
234
|
+
"create-client",
|
235
|
+
"-cn",
|
236
|
+
config["common_name"],
|
237
|
+
"-o",
|
238
|
+
config["organization"],
|
239
|
+
"-c",
|
240
|
+
self.ca_config["country"],
|
241
|
+
"-s",
|
242
|
+
self.ca_config["state"],
|
243
|
+
"-l",
|
244
|
+
self.ca_config["city"],
|
245
|
+
"-d",
|
246
|
+
"730", # 2 years in days
|
194
247
|
]
|
195
248
|
# Add roles if specified
|
196
249
|
if "roles" in config and config["roles"]:
|
@@ -206,13 +259,25 @@ class CertificateGenerator:
|
|
206
259
|
success = self.run_command(cmd, f"Creating client certificate: {name}")
|
207
260
|
if success:
|
208
261
|
# Move files to correct locations
|
209
|
-
default_client_cert =
|
210
|
-
|
262
|
+
default_client_cert = (
|
263
|
+
Path("./certs")
|
264
|
+
/ f"{config['common_name'].lower().replace('-', '_')}_client.crt"
|
265
|
+
)
|
266
|
+
default_client_key = (
|
267
|
+
Path("./keys")
|
268
|
+
/ f"{config['common_name'].lower().replace('-', '_')}_client.key"
|
269
|
+
)
|
211
270
|
if default_client_cert.exists():
|
212
|
-
self.run_command(
|
271
|
+
self.run_command(
|
272
|
+
["mv", str(default_client_cert), str(cert_path)],
|
273
|
+
f"Moving {name} certificate",
|
274
|
+
)
|
213
275
|
if default_client_key.exists():
|
214
|
-
self.run_command(
|
276
|
+
self.run_command(
|
277
|
+
["mv", str(default_client_key), str(key_path)], f"Moving {name} key"
|
278
|
+
)
|
215
279
|
return success
|
280
|
+
|
216
281
|
def create_legacy_certificates(self) -> bool:
|
217
282
|
"""Create legacy certificate files for compatibility."""
|
218
283
|
legacy_files = [
|
@@ -220,7 +285,7 @@ class CertificateGenerator:
|
|
220
285
|
("client_admin.crt", "client_admin.key"),
|
221
286
|
("admin.crt", "admin.key"),
|
222
287
|
("user.crt", "user.key"),
|
223
|
-
("readonly.crt", "readonly.key")
|
288
|
+
("readonly.crt", "readonly.key"),
|
224
289
|
]
|
225
290
|
success = True
|
226
291
|
for cert_file, key_file in legacy_files:
|
@@ -228,22 +293,72 @@ class CertificateGenerator:
|
|
228
293
|
key_path = self.certs_dir / key_file
|
229
294
|
if not cert_path.exists() or not key_path.exists():
|
230
295
|
# Copy from existing certificates
|
231
|
-
if
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
self.run_command(
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
self.run_command(
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
elif
|
244
|
-
|
245
|
-
|
296
|
+
if (
|
297
|
+
cert_file == "client.crt"
|
298
|
+
and (self.certs_dir / "user_cert.pem").exists()
|
299
|
+
):
|
300
|
+
self.run_command(
|
301
|
+
["cp", str(self.certs_dir / "user_cert.pem"), str(cert_path)],
|
302
|
+
f"Creating {cert_file}",
|
303
|
+
)
|
304
|
+
self.run_command(
|
305
|
+
["cp", str(self.certs_dir / "user_key.pem"), str(key_path)],
|
306
|
+
f"Creating {key_file}",
|
307
|
+
)
|
308
|
+
elif (
|
309
|
+
cert_file == "client_admin.crt"
|
310
|
+
and (self.certs_dir / "admin_cert.pem").exists()
|
311
|
+
):
|
312
|
+
self.run_command(
|
313
|
+
["cp", str(self.certs_dir / "admin_cert.pem"), str(cert_path)],
|
314
|
+
f"Creating {cert_file}",
|
315
|
+
)
|
316
|
+
self.run_command(
|
317
|
+
["cp", str(self.certs_dir / "admin_key.pem"), str(key_path)],
|
318
|
+
f"Creating {key_file}",
|
319
|
+
)
|
320
|
+
elif (
|
321
|
+
cert_file == "admin.crt"
|
322
|
+
and (self.certs_dir / "admin_cert.pem").exists()
|
323
|
+
):
|
324
|
+
self.run_command(
|
325
|
+
["cp", str(self.certs_dir / "admin_cert.pem"), str(cert_path)],
|
326
|
+
f"Creating {cert_file}",
|
327
|
+
)
|
328
|
+
self.run_command(
|
329
|
+
["cp", str(self.certs_dir / "admin_key.pem"), str(key_path)],
|
330
|
+
f"Creating {key_file}",
|
331
|
+
)
|
332
|
+
elif (
|
333
|
+
cert_file == "user.crt"
|
334
|
+
and (self.certs_dir / "user_cert.pem").exists()
|
335
|
+
):
|
336
|
+
self.run_command(
|
337
|
+
["cp", str(self.certs_dir / "user_cert.pem"), str(cert_path)],
|
338
|
+
f"Creating {cert_file}",
|
339
|
+
)
|
340
|
+
self.run_command(
|
341
|
+
["cp", str(self.certs_dir / "user_key.pem"), str(key_path)],
|
342
|
+
f"Creating {key_file}",
|
343
|
+
)
|
344
|
+
elif (
|
345
|
+
cert_file == "readonly.crt"
|
346
|
+
and (self.certs_dir / "readonly_cert.pem").exists()
|
347
|
+
):
|
348
|
+
self.run_command(
|
349
|
+
[
|
350
|
+
"cp",
|
351
|
+
str(self.certs_dir / "readonly_cert.pem"),
|
352
|
+
str(cert_path),
|
353
|
+
],
|
354
|
+
f"Creating {cert_file}",
|
355
|
+
)
|
356
|
+
self.run_command(
|
357
|
+
["cp", str(self.certs_dir / "readonly_key.pem"), str(key_path)],
|
358
|
+
f"Creating {key_file}",
|
359
|
+
)
|
246
360
|
return success
|
361
|
+
|
247
362
|
def create_certificate_config(self) -> bool:
|
248
363
|
"""Create certificate configuration file."""
|
249
364
|
config_path = self.certs_dir / "cert_config.json"
|
@@ -254,16 +369,17 @@ class CertificateGenerator:
|
|
254
369
|
"key_storage_path": str(self.keys_dir),
|
255
370
|
"default_validity_days": 365,
|
256
371
|
"key_size": 2048,
|
257
|
-
"hash_algorithm": "sha256"
|
372
|
+
"hash_algorithm": "sha256",
|
258
373
|
}
|
259
374
|
try:
|
260
|
-
with open(config_path,
|
375
|
+
with open(config_path, "w") as f:
|
261
376
|
json.dump(config, f, indent=2)
|
262
377
|
print(f"ā
Created certificate config: {config_path}")
|
263
378
|
return True
|
264
379
|
except Exception as e:
|
265
380
|
print(f"ā Failed to create certificate config: {e}")
|
266
381
|
return False
|
382
|
+
|
267
383
|
def validate_certificates(self) -> bool:
|
268
384
|
"""Validate all created certificates."""
|
269
385
|
print("\nš Validating certificates...")
|
@@ -274,7 +390,7 @@ class CertificateGenerator:
|
|
274
390
|
"user_cert.pem",
|
275
391
|
"readonly_cert.pem",
|
276
392
|
"guest_cert.pem",
|
277
|
-
"proxy_cert.pem"
|
393
|
+
"proxy_cert.pem",
|
278
394
|
]
|
279
395
|
success = True
|
280
396
|
for cert_file in cert_files:
|
@@ -285,7 +401,7 @@ class CertificateGenerator:
|
|
285
401
|
["openssl", "x509", "-in", str(cert_path), "-text", "-noout"],
|
286
402
|
capture_output=True,
|
287
403
|
text=True,
|
288
|
-
check=True
|
404
|
+
check=True,
|
289
405
|
)
|
290
406
|
print(f"ā
{cert_file}: Valid")
|
291
407
|
except subprocess.CalledProcessError:
|
@@ -294,6 +410,7 @@ class CertificateGenerator:
|
|
294
410
|
else:
|
295
411
|
print(f"ā ļø {cert_file}: Not found")
|
296
412
|
return success
|
413
|
+
|
297
414
|
def generate_all(self) -> bool:
|
298
415
|
"""Generate all certificates."""
|
299
416
|
print("š Generating All Certificates for Security Testing")
|
@@ -336,16 +453,22 @@ class CertificateGenerator:
|
|
336
453
|
print(f"š Certificates directory: {self.certs_dir}")
|
337
454
|
print(f"š Keys directory: {self.keys_dir}")
|
338
455
|
print("\nš Generated certificates:")
|
339
|
-
cert_files = list(self.certs_dir.glob("*.pem")) + list(
|
456
|
+
cert_files = list(self.certs_dir.glob("*.pem")) + list(
|
457
|
+
self.certs_dir.glob("*.crt")
|
458
|
+
)
|
340
459
|
for cert_file in sorted(cert_files):
|
341
460
|
print(f" - {cert_file.name}")
|
342
|
-
key_files = list(self.keys_dir.glob("*.pem")) + list(
|
461
|
+
key_files = list(self.keys_dir.glob("*.pem")) + list(
|
462
|
+
self.keys_dir.glob("*.key")
|
463
|
+
)
|
343
464
|
for key_file in sorted(key_files):
|
344
465
|
print(f" - {key_file.name}")
|
345
466
|
else:
|
346
467
|
print("ā Some certificates failed to generate")
|
347
468
|
print("Check the error messages above")
|
348
469
|
return success
|
470
|
+
|
471
|
+
|
349
472
|
def main():
|
350
473
|
"""Main function."""
|
351
474
|
generator = CertificateGenerator()
|
@@ -358,5 +481,7 @@ def main():
|
|
358
481
|
except Exception as e:
|
359
482
|
print(f"\nā Certificate generation failed: {e}")
|
360
483
|
sys.exit(1)
|
484
|
+
|
485
|
+
|
361
486
|
if __name__ == "__main__":
|
362
487
|
main()
|
@@ -11,6 +11,7 @@ import sys
|
|
11
11
|
from pathlib import Path
|
12
12
|
from datetime import datetime, timedelta, timezone
|
13
13
|
|
14
|
+
|
14
15
|
def main():
|
15
16
|
"""Generate all certificates for examples."""
|
16
17
|
print("š Certificate Generation Script")
|
@@ -26,8 +27,12 @@ def main():
|
|
26
27
|
try:
|
27
28
|
from mcp_security_framework.core.cert_manager import CertificateManager
|
28
29
|
from mcp_security_framework.schemas import (
|
29
|
-
CAConfig,
|
30
|
+
CAConfig,
|
31
|
+
ServerCertConfig,
|
32
|
+
ClientCertConfig,
|
33
|
+
CertificateConfig,
|
30
34
|
)
|
35
|
+
|
31
36
|
print("ā
mcp_security_framework API available")
|
32
37
|
except ImportError as e:
|
33
38
|
print(f"ā mcp_security_framework not found: {e}")
|
@@ -35,17 +40,17 @@ def main():
|
|
35
40
|
|
36
41
|
try:
|
37
42
|
print("š§ Creating root CA certificate...")
|
38
|
-
|
43
|
+
|
39
44
|
# Initialize certificate manager first
|
40
45
|
cert_config = CertificateConfig(
|
41
46
|
cert_storage_path=str(cert_dir),
|
42
47
|
key_storage_path=str(key_dir),
|
43
48
|
default_validity_days=365,
|
44
49
|
key_size=2048,
|
45
|
-
hash_algorithm="sha256"
|
50
|
+
hash_algorithm="sha256",
|
46
51
|
)
|
47
52
|
cert_manager = CertificateManager(cert_config)
|
48
|
-
|
53
|
+
|
49
54
|
# Create CA certificate using API
|
50
55
|
ca_config = CAConfig(
|
51
56
|
common_name="MCP Proxy Adapter CA",
|
@@ -56,14 +61,14 @@ def main():
|
|
56
61
|
locality="City",
|
57
62
|
validity_years=10,
|
58
63
|
key_size=2048,
|
59
|
-
hash_algorithm="sha256"
|
64
|
+
hash_algorithm="sha256",
|
60
65
|
)
|
61
|
-
|
66
|
+
|
62
67
|
ca_cert_pair = cert_manager.create_root_ca(ca_config)
|
63
68
|
if not ca_cert_pair or not ca_cert_pair.certificate_path:
|
64
69
|
print("ā Failed to create CA certificate")
|
65
70
|
return False
|
66
|
-
|
71
|
+
|
67
72
|
ca_cert_path = ca_cert_pair.certificate_path
|
68
73
|
ca_key_path = ca_cert_pair.private_key_path
|
69
74
|
print(f"ā
Root CA certificate created: {ca_cert_path}")
|
@@ -78,7 +83,7 @@ def main():
|
|
78
83
|
key_size=2048,
|
79
84
|
subject_alt_names=["localhost", "127.0.0.1"],
|
80
85
|
ca_cert_path=str(ca_cert_path),
|
81
|
-
ca_key_path=str(ca_key_path)
|
86
|
+
ca_key_path=str(ca_key_path),
|
82
87
|
)
|
83
88
|
|
84
89
|
server_cert_pair = cert_manager.create_server_certificate(server_config)
|
@@ -95,11 +100,13 @@ def main():
|
|
95
100
|
roles=["admin"],
|
96
101
|
permissions=["read", "write", "delete"],
|
97
102
|
ca_cert_path=str(ca_cert_path),
|
98
|
-
ca_key_path=str(ca_key_path)
|
103
|
+
ca_key_path=str(ca_key_path),
|
99
104
|
)
|
100
105
|
|
101
106
|
admin_cert_pair = cert_manager.create_client_certificate(admin_config)
|
102
|
-
print(
|
107
|
+
print(
|
108
|
+
f"ā
Admin client certificate created: {admin_cert_pair.certificate_path}"
|
109
|
+
)
|
103
110
|
|
104
111
|
print("š§ Creating user client certificate...")
|
105
112
|
# Create user client certificate
|
@@ -112,7 +119,7 @@ def main():
|
|
112
119
|
roles=["user"],
|
113
120
|
permissions=["read", "write"],
|
114
121
|
ca_cert_path=str(ca_cert_path),
|
115
|
-
ca_key_path=str(ca_key_path)
|
122
|
+
ca_key_path=str(ca_key_path),
|
116
123
|
)
|
117
124
|
|
118
125
|
user_cert_pair = cert_manager.create_client_certificate(user_config)
|
@@ -129,28 +136,34 @@ def main():
|
|
129
136
|
roles=["readonly"],
|
130
137
|
permissions=["read"],
|
131
138
|
ca_cert_path=str(ca_cert_path),
|
132
|
-
ca_key_path=str(ca_key_path)
|
139
|
+
ca_key_path=str(ca_key_path),
|
133
140
|
)
|
134
141
|
|
135
142
|
readonly_cert_pair = cert_manager.create_client_certificate(readonly_config)
|
136
|
-
print(
|
143
|
+
print(
|
144
|
+
f"ā
Readonly client certificate created: {readonly_cert_pair.certificate_path}"
|
145
|
+
)
|
137
146
|
|
138
147
|
print("\nš All certificates generated successfully!")
|
139
148
|
print(f"š Certificates are stored in the '{cert_dir}' directory")
|
140
149
|
print(f"š Private keys are stored in the '{key_dir}' directory")
|
141
150
|
print(f"š CA certificate: {ca_cert_path}")
|
142
151
|
print(f"š Server certificate: {server_cert_pair.certificate_path}")
|
143
|
-
|
152
|
+
|
144
153
|
print("\n" + "=" * 60)
|
145
154
|
print("ā
CERTIFICATE GENERATION COMPLETED SUCCESSFULLY")
|
146
155
|
print("=" * 60)
|
147
156
|
print("\nš NEXT STEPS:")
|
148
157
|
print("1. Generate test configurations:")
|
149
|
-
print(
|
158
|
+
print(
|
159
|
+
" python -m mcp_proxy_adapter.examples.generate_test_configs --output-dir configs"
|
160
|
+
)
|
150
161
|
print("\n2. Run security tests:")
|
151
162
|
print(" python -m mcp_proxy_adapter.examples.run_security_tests")
|
152
163
|
print("\n3. Start basic framework example:")
|
153
|
-
print(
|
164
|
+
print(
|
165
|
+
" python -m mcp_proxy_adapter.examples.basic_framework.main --config configs/https_simple.json"
|
166
|
+
)
|
154
167
|
print("=" * 60)
|
155
168
|
return True
|
156
169
|
|
@@ -158,6 +171,7 @@ def main():
|
|
158
171
|
print(f"\nā CERTIFICATE GENERATION FAILED: {e}")
|
159
172
|
print("=" * 60)
|
160
173
|
import traceback
|
174
|
+
|
161
175
|
traceback.print_exc()
|
162
176
|
print("\nš§ TROUBLESHOOTING:")
|
163
177
|
print("1. Check if mcp_security_framework is installed:")
|
@@ -167,6 +181,7 @@ def main():
|
|
167
181
|
print("=" * 60)
|
168
182
|
return False
|
169
183
|
|
184
|
+
|
170
185
|
if __name__ == "__main__":
|
171
186
|
print("š Starting certificate generation...")
|
172
187
|
success = main()
|