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.
Files changed (24) hide show
  1. mcp_proxy_adapter/core/proxy_registration.py +100 -68
  2. mcp_proxy_adapter/examples/bugfix_certificate_config.py +284 -0
  3. mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
  4. mcp_proxy_adapter/examples/config_builder.py +574 -0
  5. mcp_proxy_adapter/examples/config_cli.py +283 -0
  6. mcp_proxy_adapter/examples/create_test_configs.py +169 -266
  7. mcp_proxy_adapter/examples/generate_certificates_bugfix.py +374 -0
  8. mcp_proxy_adapter/examples/generate_certificates_cli.py +406 -0
  9. mcp_proxy_adapter/examples/generate_certificates_fixed.py +313 -0
  10. mcp_proxy_adapter/examples/generate_certificates_framework.py +366 -0
  11. mcp_proxy_adapter/examples/generate_certificates_openssl.py +391 -0
  12. mcp_proxy_adapter/examples/required_certificates.py +210 -0
  13. mcp_proxy_adapter/examples/run_full_test_suite.py +117 -13
  14. mcp_proxy_adapter/examples/run_security_tests_fixed.py +42 -26
  15. mcp_proxy_adapter/examples/security_test_client.py +332 -85
  16. mcp_proxy_adapter/examples/test_config_builder.py +450 -0
  17. mcp_proxy_adapter/examples/update_config_certificates.py +136 -0
  18. mcp_proxy_adapter/version.py +1 -1
  19. {mcp_proxy_adapter-6.4.44.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/METADATA +81 -1
  20. {mcp_proxy_adapter-6.4.44.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/RECORD +23 -11
  21. mcp_proxy_adapter-6.4.45.dist-info/entry_points.txt +12 -0
  22. mcp_proxy_adapter-6.4.44.dist-info/entry_points.txt +0 -2
  23. {mcp_proxy_adapter-6.4.44.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/WHEEL +0 -0
  24. {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']}")