mcp-proxy-adapter 6.6.1__py3-none-any.whl → 6.6.4__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/api/app.py +61 -55
- mcp_proxy_adapter/commands/command_registry.py +27 -13
- mcp_proxy_adapter/config.py +1 -8
- mcp_proxy_adapter/core/proxy_registration.py +80 -7
- mcp_proxy_adapter/core/server_adapter.py +1 -1
- mcp_proxy_adapter/examples/check_config.py +1 -1
- mcp_proxy_adapter/examples/config_builder.py +13 -19
- mcp_proxy_adapter/examples/{generate_certificates_bugfix.py → generate_certificates.py} +11 -0
- mcp_proxy_adapter/examples/generate_config.py +3 -3
- mcp_proxy_adapter/examples/run_full_test_suite.py +3 -3
- mcp_proxy_adapter/examples/security_test_client.py +6 -5
- mcp_proxy_adapter/examples/test_chk_hostname_automated.py +7 -10
- mcp_proxy_adapter/examples/test_framework_complete.py +269 -0
- mcp_proxy_adapter/examples/test_mcp_server.py +188 -0
- mcp_proxy_adapter/main.py +19 -18
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.6.1.dist-info → mcp_proxy_adapter-6.6.4.dist-info}/METADATA +1 -1
- {mcp_proxy_adapter-6.6.1.dist-info → mcp_proxy_adapter-6.6.4.dist-info}/RECORD +21 -25
- mcp_proxy_adapter/examples/config_builder_simple.py +0 -271
- mcp_proxy_adapter/examples/generate_all_certificates.py +0 -487
- mcp_proxy_adapter/examples/generate_certificates_cli.py +0 -406
- mcp_proxy_adapter/examples/generate_certificates_fixed.py +0 -313
- mcp_proxy_adapter/examples/generate_certificates_framework.py +0 -366
- mcp_proxy_adapter/examples/generate_certificates_openssl.py +0 -391
- {mcp_proxy_adapter-6.6.1.dist-info → mcp_proxy_adapter-6.6.4.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.6.1.dist-info → mcp_proxy_adapter-6.6.4.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.6.1.dist-info → mcp_proxy_adapter-6.6.4.dist-info}/top_level.txt +0 -0
@@ -1,391 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
Generate Certificates Using OpenSSL
|
4
|
-
This script generates all necessary SSL certificates using OpenSSL directly.
|
5
|
-
|
6
|
-
Author: Vasiliy Zdanovskiy
|
7
|
-
email: vasilyvz@gmail.com
|
8
|
-
"""
|
9
|
-
import json
|
10
|
-
import os
|
11
|
-
import subprocess
|
12
|
-
import sys
|
13
|
-
from pathlib import Path
|
14
|
-
from typing import Dict, List, Optional
|
15
|
-
|
16
|
-
# Import required certificates configuration
|
17
|
-
from required_certificates import REQUIRED_CERTIFICATES, get_all_required_certificates
|
18
|
-
|
19
|
-
|
20
|
-
class OpenSSLCertificateGenerator:
|
21
|
-
"""Certificate generator using OpenSSL directly."""
|
22
|
-
|
23
|
-
def __init__(self):
|
24
|
-
"""Initialize the certificate generator."""
|
25
|
-
self.working_dir = Path.cwd()
|
26
|
-
self.certs_dir = self.working_dir / "certs"
|
27
|
-
self.keys_dir = self.working_dir / "keys"
|
28
|
-
|
29
|
-
# Ensure directories exist
|
30
|
-
self.certs_dir.mkdir(exist_ok=True)
|
31
|
-
self.keys_dir.mkdir(exist_ok=True)
|
32
|
-
|
33
|
-
def print_step(self, step: str, description: str):
|
34
|
-
"""Print a formatted step header."""
|
35
|
-
print(f"\n{'=' * 60}")
|
36
|
-
print(f"🔧 STEP {step}: {description}")
|
37
|
-
print(f"{'=' * 60}")
|
38
|
-
|
39
|
-
def print_success(self, message: str):
|
40
|
-
"""Print a success message."""
|
41
|
-
print(f"✅ {message}")
|
42
|
-
|
43
|
-
def print_error(self, message: str):
|
44
|
-
"""Print an error message."""
|
45
|
-
print(f"❌ {message}")
|
46
|
-
|
47
|
-
def print_info(self, message: str):
|
48
|
-
"""Print an info message."""
|
49
|
-
print(f"ℹ️ {message}")
|
50
|
-
|
51
|
-
def check_openssl(self) -> bool:
|
52
|
-
"""Check if OpenSSL is available."""
|
53
|
-
try:
|
54
|
-
result = subprocess.run(["openssl", "version"], capture_output=True, text=True)
|
55
|
-
if result.returncode == 0:
|
56
|
-
self.print_success(f"OpenSSL is available: {result.stdout.strip()}")
|
57
|
-
return True
|
58
|
-
else:
|
59
|
-
self.print_error("OpenSSL is not available")
|
60
|
-
return False
|
61
|
-
except FileNotFoundError:
|
62
|
-
self.print_error("OpenSSL is not installed")
|
63
|
-
return False
|
64
|
-
|
65
|
-
def generate_ca_certificate(self) -> bool:
|
66
|
-
"""Generate CA certificate using OpenSSL."""
|
67
|
-
self.print_step("1", "Generating CA Certificate")
|
68
|
-
|
69
|
-
ca_info = REQUIRED_CERTIFICATES["ca_cert"]
|
70
|
-
|
71
|
-
try:
|
72
|
-
# Check if CA certificate already exists
|
73
|
-
if ca_info["output_cert"].exists() and ca_info["output_key"].exists():
|
74
|
-
self.print_info(f"CA certificate already exists: {ca_info['output_cert']}")
|
75
|
-
return True
|
76
|
-
|
77
|
-
# Generate CA private key
|
78
|
-
key_cmd = [
|
79
|
-
"openssl", "genrsa", "-out", str(ca_info["output_key"]), "2048"
|
80
|
-
]
|
81
|
-
|
82
|
-
self.print_info("Generating CA private key...")
|
83
|
-
result = subprocess.run(key_cmd, capture_output=True, text=True, cwd=self.working_dir)
|
84
|
-
|
85
|
-
if result.returncode != 0:
|
86
|
-
self.print_error(f"Failed to generate CA key: {result.stderr}")
|
87
|
-
return False
|
88
|
-
|
89
|
-
# Generate CA certificate
|
90
|
-
cert_cmd = [
|
91
|
-
"openssl", "req", "-new", "-x509", "-days", str(ca_info["validity_days"]),
|
92
|
-
"-key", str(ca_info["output_key"]), "-out", str(ca_info["output_cert"]),
|
93
|
-
"-subj", f"/C={ca_info['country']}/ST={ca_info['state']}/L={ca_info['city']}/O={ca_info['organization']}/CN={ca_info['common_name']}"
|
94
|
-
]
|
95
|
-
|
96
|
-
self.print_info(f"Generating CA certificate: {ca_info['common_name']}")
|
97
|
-
result = subprocess.run(cert_cmd, capture_output=True, text=True, cwd=self.working_dir)
|
98
|
-
|
99
|
-
if result.returncode == 0:
|
100
|
-
self.print_success(f"CA certificate generated: {ca_info['output_cert']}")
|
101
|
-
return True
|
102
|
-
else:
|
103
|
-
self.print_error(f"Failed to generate CA certificate: {result.stderr}")
|
104
|
-
return False
|
105
|
-
|
106
|
-
except Exception as e:
|
107
|
-
self.print_error(f"Exception during CA certificate generation: {e}")
|
108
|
-
return False
|
109
|
-
|
110
|
-
def generate_server_certificate(self) -> bool:
|
111
|
-
"""Generate server certificate using OpenSSL."""
|
112
|
-
self.print_step("2", "Generating Server Certificate")
|
113
|
-
|
114
|
-
server_info = REQUIRED_CERTIFICATES["server_cert"]
|
115
|
-
|
116
|
-
try:
|
117
|
-
# Check if server certificate already exists
|
118
|
-
if server_info["output_cert"].exists() and server_info["output_key"].exists():
|
119
|
-
self.print_info(f"Server certificate already exists: {server_info['output_cert']}")
|
120
|
-
return True
|
121
|
-
|
122
|
-
# Generate server private key
|
123
|
-
key_cmd = [
|
124
|
-
"openssl", "genrsa", "-out", str(server_info["output_key"]), "2048"
|
125
|
-
]
|
126
|
-
|
127
|
-
self.print_info("Generating server private key...")
|
128
|
-
result = subprocess.run(key_cmd, capture_output=True, text=True, cwd=self.working_dir)
|
129
|
-
|
130
|
-
if result.returncode != 0:
|
131
|
-
self.print_error(f"Failed to generate server key: {result.stderr}")
|
132
|
-
return False
|
133
|
-
|
134
|
-
# Create certificate signing request
|
135
|
-
csr_file = self.certs_dir / "server.csr"
|
136
|
-
csr_cmd = [
|
137
|
-
"openssl", "req", "-new", "-key", str(server_info["output_key"]),
|
138
|
-
"-out", str(csr_file),
|
139
|
-
"-subj", f"/C={server_info['country']}/ST={server_info['state']}/L={server_info['city']}/O={server_info['organization']}/CN={server_info['common_name']}"
|
140
|
-
]
|
141
|
-
|
142
|
-
self.print_info("Creating certificate signing request...")
|
143
|
-
result = subprocess.run(csr_cmd, capture_output=True, text=True, cwd=self.working_dir)
|
144
|
-
|
145
|
-
if result.returncode != 0:
|
146
|
-
self.print_error(f"Failed to create CSR: {result.stderr}")
|
147
|
-
return False
|
148
|
-
|
149
|
-
# Create extensions file for SAN
|
150
|
-
ext_file = self.certs_dir / "server.ext"
|
151
|
-
with open(ext_file, 'w') as f:
|
152
|
-
f.write("authorityKeyIdentifier=keyid,issuer\n")
|
153
|
-
f.write("basicConstraints=CA:FALSE\n")
|
154
|
-
f.write("keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment\n")
|
155
|
-
if "san" in server_info:
|
156
|
-
f.write("subjectAltName = @alt_names\n")
|
157
|
-
f.write("[alt_names]\n")
|
158
|
-
for i, san in enumerate(server_info["san"], 1):
|
159
|
-
if san.startswith("127.") or san.startswith("192.") or san.startswith("10."):
|
160
|
-
f.write(f"IP.{i} = {san}\n")
|
161
|
-
else:
|
162
|
-
f.write(f"DNS.{i} = {san}\n")
|
163
|
-
|
164
|
-
# Sign the certificate with CA
|
165
|
-
cert_cmd = [
|
166
|
-
"openssl", "x509", "-req", "-in", str(csr_file),
|
167
|
-
"-CA", str(server_info["ca_cert_path"]), "-CAkey", str(server_info["ca_key_path"]),
|
168
|
-
"-CAcreateserial", "-out", str(server_info["output_cert"]),
|
169
|
-
"-days", str(server_info["validity_days"]), "-extensions", "v3_req", "-extfile", str(ext_file)
|
170
|
-
]
|
171
|
-
|
172
|
-
self.print_info(f"Generating server certificate: {server_info['common_name']}")
|
173
|
-
result = subprocess.run(cert_cmd, capture_output=True, text=True, cwd=self.working_dir)
|
174
|
-
|
175
|
-
if result.returncode == 0:
|
176
|
-
self.print_success(f"Server certificate generated: {server_info['output_cert']}")
|
177
|
-
# Clean up temporary files
|
178
|
-
csr_file.unlink(missing_ok=True)
|
179
|
-
ext_file.unlink(missing_ok=True)
|
180
|
-
return True
|
181
|
-
else:
|
182
|
-
self.print_error(f"Failed to generate server certificate: {result.stderr}")
|
183
|
-
return False
|
184
|
-
|
185
|
-
except Exception as e:
|
186
|
-
self.print_error(f"Exception during server certificate generation: {e}")
|
187
|
-
return False
|
188
|
-
|
189
|
-
def generate_client_certificate(self, cert_name: str) -> bool:
|
190
|
-
"""Generate client certificate using OpenSSL."""
|
191
|
-
self.print_step(f"3.{cert_name}", f"Generating {cert_name.title()} Client Certificate")
|
192
|
-
|
193
|
-
client_info = REQUIRED_CERTIFICATES[cert_name]
|
194
|
-
|
195
|
-
try:
|
196
|
-
# Check if client certificate already exists
|
197
|
-
if client_info["output_cert"].exists() and client_info["output_key"].exists():
|
198
|
-
self.print_info(f"{cert_name} certificate already exists: {client_info['output_cert']}")
|
199
|
-
return True
|
200
|
-
|
201
|
-
# Generate client private key
|
202
|
-
key_cmd = [
|
203
|
-
"openssl", "genrsa", "-out", str(client_info["output_key"]), "2048"
|
204
|
-
]
|
205
|
-
|
206
|
-
self.print_info(f"Generating {cert_name} private key...")
|
207
|
-
result = subprocess.run(key_cmd, capture_output=True, text=True, cwd=self.working_dir)
|
208
|
-
|
209
|
-
if result.returncode != 0:
|
210
|
-
self.print_error(f"Failed to generate {cert_name} key: {result.stderr}")
|
211
|
-
return False
|
212
|
-
|
213
|
-
# Create certificate signing request
|
214
|
-
csr_file = self.certs_dir / f"{cert_name}.csr"
|
215
|
-
csr_cmd = [
|
216
|
-
"openssl", "req", "-new", "-key", str(client_info["output_key"]),
|
217
|
-
"-out", str(csr_file),
|
218
|
-
"-subj", f"/C={client_info['country']}/ST={client_info['state']}/L={client_info['city']}/O={client_info['organization']}/CN={client_info['common_name']}"
|
219
|
-
]
|
220
|
-
|
221
|
-
self.print_info(f"Creating {cert_name} certificate signing request...")
|
222
|
-
result = subprocess.run(csr_cmd, capture_output=True, text=True, cwd=self.working_dir)
|
223
|
-
|
224
|
-
if result.returncode != 0:
|
225
|
-
self.print_error(f"Failed to create {cert_name} CSR: {result.stderr}")
|
226
|
-
return False
|
227
|
-
|
228
|
-
# Sign the certificate with CA
|
229
|
-
cert_cmd = [
|
230
|
-
"openssl", "x509", "-req", "-in", str(csr_file),
|
231
|
-
"-CA", str(client_info["ca_cert_path"]), "-CAkey", str(client_info["ca_key_path"]),
|
232
|
-
"-CAcreateserial", "-out", str(client_info["output_cert"]),
|
233
|
-
"-days", str(client_info["validity_days"])
|
234
|
-
]
|
235
|
-
|
236
|
-
self.print_info(f"Generating {cert_name} certificate: {client_info['common_name']}")
|
237
|
-
result = subprocess.run(cert_cmd, capture_output=True, text=True, cwd=self.working_dir)
|
238
|
-
|
239
|
-
if result.returncode == 0:
|
240
|
-
self.print_success(f"{cert_name} certificate generated: {client_info['output_cert']}")
|
241
|
-
# Clean up temporary files
|
242
|
-
csr_file.unlink(missing_ok=True)
|
243
|
-
return True
|
244
|
-
else:
|
245
|
-
self.print_error(f"Failed to generate {cert_name} certificate: {result.stderr}")
|
246
|
-
return False
|
247
|
-
|
248
|
-
except Exception as e:
|
249
|
-
self.print_error(f"Exception during {cert_name} certificate generation: {e}")
|
250
|
-
return False
|
251
|
-
|
252
|
-
def create_certificate_aliases(self) -> bool:
|
253
|
-
"""Create certificate aliases for different configurations."""
|
254
|
-
self.print_step("4", "Creating Certificate Aliases")
|
255
|
-
|
256
|
-
try:
|
257
|
-
# Create aliases for HTTPS configurations
|
258
|
-
if (self.certs_dir / "server_cert.pem").exists():
|
259
|
-
# HTTPS aliases
|
260
|
-
(self.certs_dir / "mcp_proxy_adapter_server.crt").unlink(missing_ok=True)
|
261
|
-
(self.certs_dir / "mcp_proxy_adapter_server.crt").symlink_to("server_cert.pem")
|
262
|
-
|
263
|
-
(self.certs_dir / "mcp_proxy_adapter_server.key").unlink(missing_ok=True)
|
264
|
-
(self.certs_dir / "mcp_proxy_adapter_server.key").symlink_to(self.keys_dir / "server_key.pem")
|
265
|
-
|
266
|
-
# mTLS aliases
|
267
|
-
(self.certs_dir / "localhost_server.crt").unlink(missing_ok=True)
|
268
|
-
(self.certs_dir / "localhost_server.crt").symlink_to("server_cert.pem")
|
269
|
-
|
270
|
-
self.print_success("Certificate aliases created")
|
271
|
-
|
272
|
-
# Create CA alias
|
273
|
-
if (self.certs_dir / "ca_cert.pem").exists():
|
274
|
-
(self.certs_dir / "mcp_proxy_adapter_ca_ca.crt").unlink(missing_ok=True)
|
275
|
-
(self.certs_dir / "mcp_proxy_adapter_ca_ca.crt").symlink_to("ca_cert.pem")
|
276
|
-
|
277
|
-
self.print_success("CA certificate alias created")
|
278
|
-
|
279
|
-
return True
|
280
|
-
|
281
|
-
except Exception as e:
|
282
|
-
self.print_error(f"Failed to create certificate aliases: {e}")
|
283
|
-
return False
|
284
|
-
|
285
|
-
def validate_certificates(self) -> bool:
|
286
|
-
"""Validate generated certificates."""
|
287
|
-
self.print_step("5", "Validating Certificates")
|
288
|
-
|
289
|
-
all_required = get_all_required_certificates()
|
290
|
-
validation_results = []
|
291
|
-
|
292
|
-
for cert_name in all_required:
|
293
|
-
cert_info = REQUIRED_CERTIFICATES[cert_name]
|
294
|
-
cert_file = cert_info["output_cert"]
|
295
|
-
key_file = cert_info["output_key"]
|
296
|
-
|
297
|
-
if cert_file.exists() and key_file.exists():
|
298
|
-
# Validate certificate and key match
|
299
|
-
validate_cmd = [
|
300
|
-
"openssl", "x509", "-noout", "-modulus", "-in", str(cert_file)
|
301
|
-
]
|
302
|
-
cert_result = subprocess.run(validate_cmd, capture_output=True, text=True)
|
303
|
-
|
304
|
-
key_cmd = [
|
305
|
-
"openssl", "rsa", "-noout", "-modulus", "-in", str(key_file)
|
306
|
-
]
|
307
|
-
key_result = subprocess.run(key_cmd, capture_output=True, text=True)
|
308
|
-
|
309
|
-
if cert_result.returncode == 0 and key_result.returncode == 0:
|
310
|
-
if cert_result.stdout == key_result.stdout:
|
311
|
-
self.print_success(f"{cert_name}: Valid (certificate and key match)")
|
312
|
-
validation_results.append(True)
|
313
|
-
else:
|
314
|
-
self.print_error(f"{cert_name}: Certificate and key do not match")
|
315
|
-
validation_results.append(False)
|
316
|
-
else:
|
317
|
-
self.print_error(f"{cert_name}: Invalid certificate or key")
|
318
|
-
validation_results.append(False)
|
319
|
-
else:
|
320
|
-
self.print_error(f"{cert_name}: Missing files")
|
321
|
-
validation_results.append(False)
|
322
|
-
|
323
|
-
success_count = sum(validation_results)
|
324
|
-
total_count = len(validation_results)
|
325
|
-
|
326
|
-
self.print_info(f"Validation results: {success_count}/{total_count} certificates valid")
|
327
|
-
|
328
|
-
return success_count == total_count
|
329
|
-
|
330
|
-
def generate_all_certificates(self) -> bool:
|
331
|
-
"""Generate all required certificates."""
|
332
|
-
print("🔐 Generating All Certificates Using OpenSSL")
|
333
|
-
print("=" * 60)
|
334
|
-
|
335
|
-
try:
|
336
|
-
# Check OpenSSL availability
|
337
|
-
if not self.check_openssl():
|
338
|
-
return False
|
339
|
-
|
340
|
-
# Generate CA certificate first
|
341
|
-
if not self.generate_ca_certificate():
|
342
|
-
return False
|
343
|
-
|
344
|
-
# Generate server certificate
|
345
|
-
if not self.generate_server_certificate():
|
346
|
-
return False
|
347
|
-
|
348
|
-
# Generate client certificates
|
349
|
-
client_certs = ["admin_cert", "user_cert", "proxy_cert"]
|
350
|
-
for cert_name in client_certs:
|
351
|
-
if cert_name in REQUIRED_CERTIFICATES:
|
352
|
-
if not self.generate_client_certificate(cert_name):
|
353
|
-
return False
|
354
|
-
|
355
|
-
# Create aliases
|
356
|
-
if not self.create_certificate_aliases():
|
357
|
-
return False
|
358
|
-
|
359
|
-
# Validate certificates
|
360
|
-
if not self.validate_certificates():
|
361
|
-
return False
|
362
|
-
|
363
|
-
# Print summary
|
364
|
-
print(f"\n{'=' * 60}")
|
365
|
-
print("📊 CERTIFICATE GENERATION SUMMARY")
|
366
|
-
print(f"{'=' * 60}")
|
367
|
-
print("✅ All certificates generated successfully!")
|
368
|
-
print(f"📁 Certificates directory: {self.certs_dir}")
|
369
|
-
print(f"📁 Keys directory: {self.keys_dir}")
|
370
|
-
|
371
|
-
return True
|
372
|
-
|
373
|
-
except Exception as e:
|
374
|
-
self.print_error(f"Certificate generation failed: {e}")
|
375
|
-
return False
|
376
|
-
|
377
|
-
|
378
|
-
def main():
|
379
|
-
"""Main entry point."""
|
380
|
-
generator = OpenSSLCertificateGenerator()
|
381
|
-
|
382
|
-
try:
|
383
|
-
success = generator.generate_all_certificates()
|
384
|
-
sys.exit(0 if success else 1)
|
385
|
-
except Exception as e:
|
386
|
-
print(f"❌ Fatal error: {e}")
|
387
|
-
sys.exit(1)
|
388
|
-
|
389
|
-
|
390
|
-
if __name__ == "__main__":
|
391
|
-
main()
|
File without changes
|
File without changes
|
File without changes
|