mcp-proxy-adapter 6.4.44__py3-none-any.whl → 6.4.45__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/core/proxy_registration.py +100 -68
- mcp_proxy_adapter/examples/bugfix_certificate_config.py +284 -0
- mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
- mcp_proxy_adapter/examples/config_builder.py +574 -0
- mcp_proxy_adapter/examples/config_cli.py +283 -0
- mcp_proxy_adapter/examples/create_test_configs.py +169 -266
- mcp_proxy_adapter/examples/generate_certificates_bugfix.py +374 -0
- mcp_proxy_adapter/examples/generate_certificates_cli.py +406 -0
- mcp_proxy_adapter/examples/generate_certificates_fixed.py +313 -0
- mcp_proxy_adapter/examples/generate_certificates_framework.py +366 -0
- mcp_proxy_adapter/examples/generate_certificates_openssl.py +391 -0
- mcp_proxy_adapter/examples/required_certificates.py +210 -0
- mcp_proxy_adapter/examples/run_full_test_suite.py +117 -13
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +42 -26
- mcp_proxy_adapter/examples/security_test_client.py +332 -85
- mcp_proxy_adapter/examples/test_config_builder.py +450 -0
- mcp_proxy_adapter/examples/update_config_certificates.py +136 -0
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.4.44.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/METADATA +81 -1
- {mcp_proxy_adapter-6.4.44.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/RECORD +23 -11
- mcp_proxy_adapter-6.4.45.dist-info/entry_points.txt +12 -0
- mcp_proxy_adapter-6.4.44.dist-info/entry_points.txt +0 -2
- {mcp_proxy_adapter-6.4.44.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.4.44.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,391 @@
|
|
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()
|
@@ -0,0 +1,210 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Required Certificates Configuration
|
4
|
+
Defines all certificates needed for testing different server configurations.
|
5
|
+
|
6
|
+
Author: Vasiliy Zdanovskiy
|
7
|
+
email: vasilyvz@gmail.com
|
8
|
+
"""
|
9
|
+
|
10
|
+
from typing import Dict, List, Any
|
11
|
+
from pathlib import Path
|
12
|
+
|
13
|
+
# Base paths
|
14
|
+
CERTS_DIR = Path("certs")
|
15
|
+
KEYS_DIR = Path("keys")
|
16
|
+
|
17
|
+
# Required certificates for different server configurations
|
18
|
+
REQUIRED_CERTIFICATES = {
|
19
|
+
# CA Certificate (required for all SSL/mTLS configurations)
|
20
|
+
"ca_cert": {
|
21
|
+
"type": "ca",
|
22
|
+
"common_name": "MCP Proxy Adapter Test CA",
|
23
|
+
"organization": "Test Organization",
|
24
|
+
"country": "US",
|
25
|
+
"state": "Test State",
|
26
|
+
"city": "Test City",
|
27
|
+
"validity_days": 3650, # 10 years
|
28
|
+
"output_cert": CERTS_DIR / "ca_cert.pem",
|
29
|
+
"output_key": KEYS_DIR / "ca_key.pem",
|
30
|
+
"required_for": ["https", "mtls", "proxy_registration"]
|
31
|
+
},
|
32
|
+
|
33
|
+
# Server Certificate for HTTPS configurations
|
34
|
+
"server_cert": {
|
35
|
+
"type": "server",
|
36
|
+
"common_name": "localhost",
|
37
|
+
"organization": "Test Organization",
|
38
|
+
"country": "US",
|
39
|
+
"state": "Test State",
|
40
|
+
"city": "Test City",
|
41
|
+
"validity_days": 365,
|
42
|
+
"san": ["localhost", "127.0.0.1", "mcp-proxy-adapter-test.local"],
|
43
|
+
"ca_cert_path": CERTS_DIR / "ca_cert.pem",
|
44
|
+
"ca_key_path": KEYS_DIR / "ca_key.pem",
|
45
|
+
"output_cert": CERTS_DIR / "server_cert.pem",
|
46
|
+
"output_key": KEYS_DIR / "server_key.pem",
|
47
|
+
"required_for": ["https", "mtls"]
|
48
|
+
},
|
49
|
+
|
50
|
+
# Admin Client Certificate
|
51
|
+
"admin_cert": {
|
52
|
+
"type": "client",
|
53
|
+
"common_name": "admin-client",
|
54
|
+
"organization": "Test Organization",
|
55
|
+
"country": "US",
|
56
|
+
"state": "Test State",
|
57
|
+
"city": "Test City",
|
58
|
+
"validity_days": 365,
|
59
|
+
"roles": ["admin"],
|
60
|
+
"permissions": ["*"],
|
61
|
+
"ca_cert_path": CERTS_DIR / "ca_cert.pem",
|
62
|
+
"ca_key_path": KEYS_DIR / "ca_key.pem",
|
63
|
+
"output_cert": CERTS_DIR / "admin_cert.pem",
|
64
|
+
"output_key": KEYS_DIR / "admin_key.pem",
|
65
|
+
"required_for": ["mtls", "client_auth"]
|
66
|
+
},
|
67
|
+
|
68
|
+
# User Client Certificate
|
69
|
+
"user_cert": {
|
70
|
+
"type": "client",
|
71
|
+
"common_name": "user-client",
|
72
|
+
"organization": "Test Organization",
|
73
|
+
"country": "US",
|
74
|
+
"state": "Test State",
|
75
|
+
"city": "Test City",
|
76
|
+
"validity_days": 365,
|
77
|
+
"roles": ["user"],
|
78
|
+
"permissions": ["read", "write"],
|
79
|
+
"ca_cert_path": CERTS_DIR / "ca_cert.pem",
|
80
|
+
"ca_key_path": KEYS_DIR / "ca_key.pem",
|
81
|
+
"output_cert": CERTS_DIR / "user_cert.pem",
|
82
|
+
"output_key": KEYS_DIR / "user_key.pem",
|
83
|
+
"required_for": ["mtls", "client_auth"]
|
84
|
+
},
|
85
|
+
|
86
|
+
# Proxy Certificate for proxy registration
|
87
|
+
"proxy_cert": {
|
88
|
+
"type": "server",
|
89
|
+
"common_name": "proxy-server",
|
90
|
+
"organization": "Test Organization",
|
91
|
+
"country": "US",
|
92
|
+
"state": "Test State",
|
93
|
+
"city": "Test City",
|
94
|
+
"validity_days": 365,
|
95
|
+
"san": ["localhost", "127.0.0.1"],
|
96
|
+
"ca_cert_path": CERTS_DIR / "ca_cert.pem",
|
97
|
+
"ca_key_path": KEYS_DIR / "ca_key.pem",
|
98
|
+
"output_cert": CERTS_DIR / "proxy_cert.pem",
|
99
|
+
"output_key": KEYS_DIR / "proxy_key.pem",
|
100
|
+
"required_for": ["proxy_registration"]
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
# Certificate aliases for different configurations
|
105
|
+
CERTIFICATE_ALIASES = {
|
106
|
+
# HTTPS configurations
|
107
|
+
"https_server_cert": "server_cert",
|
108
|
+
"https_server_key": "server_cert",
|
109
|
+
|
110
|
+
# mTLS configurations
|
111
|
+
"mtls_server_cert": "server_cert",
|
112
|
+
"mtls_server_key": "server_cert",
|
113
|
+
"mtls_ca_cert": "ca_cert",
|
114
|
+
|
115
|
+
# Proxy registration
|
116
|
+
"proxy_server_cert": "proxy_cert",
|
117
|
+
"proxy_server_key": "proxy_cert",
|
118
|
+
|
119
|
+
# Legacy names for compatibility
|
120
|
+
"localhost_server_cert": "server_cert",
|
121
|
+
"mcp_proxy_adapter_server_cert": "server_cert",
|
122
|
+
"mcp_proxy_adapter_ca_cert": "ca_cert"
|
123
|
+
}
|
124
|
+
|
125
|
+
# Configuration file mappings
|
126
|
+
CONFIG_CERTIFICATE_MAPPINGS = {
|
127
|
+
"https_simple.json": {
|
128
|
+
"ssl.cert_file": "certs/server_cert.pem",
|
129
|
+
"ssl.key_file": "keys/server_key.pem",
|
130
|
+
"ssl.ca_cert": "certs/ca_cert.pem"
|
131
|
+
},
|
132
|
+
"https_auth.json": {
|
133
|
+
"ssl.cert_file": "certs/server_cert.pem",
|
134
|
+
"ssl.key_file": "keys/server_key.pem",
|
135
|
+
"ssl.ca_cert": "certs/ca_cert.pem"
|
136
|
+
},
|
137
|
+
"https_token.json": {
|
138
|
+
"ssl.cert_file": "certs/server_cert.pem",
|
139
|
+
"ssl.key_file": "keys/server_key.pem",
|
140
|
+
"ssl.ca_cert": "certs/ca_cert.pem"
|
141
|
+
},
|
142
|
+
"mtls_simple.json": {
|
143
|
+
"ssl.cert_file": "certs/server_cert.pem",
|
144
|
+
"ssl.key_file": "keys/server_key.pem",
|
145
|
+
"ssl.ca_cert": "certs/ca_cert.pem",
|
146
|
+
"ssl.client_cert_file": "certs/admin_cert.pem",
|
147
|
+
"ssl.client_key_file": "keys/admin_key.pem"
|
148
|
+
},
|
149
|
+
"mtls_no_roles.json": {
|
150
|
+
"ssl.cert_file": "certs/server_cert.pem",
|
151
|
+
"ssl.key_file": "keys/server_key.pem",
|
152
|
+
"ssl.ca_cert": "certs/ca_cert.pem"
|
153
|
+
},
|
154
|
+
"mtls_with_roles.json": {
|
155
|
+
"ssl.cert_file": "certs/server_cert.pem",
|
156
|
+
"ssl.key_file": "keys/server_key.pem",
|
157
|
+
"ssl.ca_cert": "certs/ca_cert.pem",
|
158
|
+
"ssl.client_cert_file": "certs/admin_cert.pem",
|
159
|
+
"ssl.client_key_file": "keys/admin_key.pem"
|
160
|
+
},
|
161
|
+
"mtls_with_proxy.json": {
|
162
|
+
"ssl.cert_file": "certs/server_cert.pem",
|
163
|
+
"ssl.key_file": "keys/server_key.pem",
|
164
|
+
"ssl.ca_cert": "certs/ca_cert.pem",
|
165
|
+
"ssl.client_cert_file": "certs/admin_cert.pem",
|
166
|
+
"ssl.client_key_file": "keys/admin_key.pem",
|
167
|
+
"proxy_registration.ssl.ca_cert": "certs/ca_cert.pem"
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
def get_required_certificates_for_config(config_name: str) -> List[str]:
|
172
|
+
"""Get list of required certificates for a specific configuration."""
|
173
|
+
if config_name not in CONFIG_CERTIFICATE_MAPPINGS:
|
174
|
+
return []
|
175
|
+
|
176
|
+
required = []
|
177
|
+
mappings = CONFIG_CERTIFICATE_MAPPINGS[config_name]
|
178
|
+
|
179
|
+
for cert_path in mappings.values():
|
180
|
+
if "server_cert.pem" in cert_path:
|
181
|
+
required.append("server_cert")
|
182
|
+
elif "ca_cert.pem" in cert_path:
|
183
|
+
required.append("ca_cert")
|
184
|
+
elif "admin_cert.pem" in cert_path:
|
185
|
+
required.append("admin_cert")
|
186
|
+
elif "proxy_cert.pem" in cert_path:
|
187
|
+
required.append("proxy_cert")
|
188
|
+
|
189
|
+
return list(set(required))
|
190
|
+
|
191
|
+
def get_all_required_certificates() -> List[str]:
|
192
|
+
"""Get list of all required certificates."""
|
193
|
+
all_certs = set()
|
194
|
+
for config_name in CONFIG_CERTIFICATE_MAPPINGS.keys():
|
195
|
+
all_certs.update(get_required_certificates_for_config(config_name))
|
196
|
+
return list(all_certs)
|
197
|
+
|
198
|
+
if __name__ == "__main__":
|
199
|
+
print("📋 Required Certificates Configuration")
|
200
|
+
print("=" * 50)
|
201
|
+
|
202
|
+
all_required = get_all_required_certificates()
|
203
|
+
print(f"Total certificates needed: {len(all_required)}")
|
204
|
+
print(f"Certificates: {', '.join(all_required)}")
|
205
|
+
|
206
|
+
print(f"\n📁 Certificate files to create:")
|
207
|
+
for cert_name in all_required:
|
208
|
+
cert_info = REQUIRED_CERTIFICATES[cert_name]
|
209
|
+
print(f" {cert_info['output_cert']}")
|
210
|
+
print(f" {cert_info['output_key']}")
|