mcp-proxy-adapter 6.2.24__py3-none-any.whl → 6.2.25__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 (31) hide show
  1. mcp_proxy_adapter/api/app.py +0 -3
  2. mcp_proxy_adapter/api/middleware/protocol_middleware.py +10 -10
  3. mcp_proxy_adapter/commands/health_command.py +1 -1
  4. mcp_proxy_adapter/core/protocol_manager.py +9 -9
  5. mcp_proxy_adapter/examples/create_certificates_simple.py +7 -17
  6. mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
  7. mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
  8. mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
  9. mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
  10. mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
  11. mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
  12. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
  13. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  14. mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
  15. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
  16. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  17. mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
  18. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
  19. mcp_proxy_adapter/examples/generate_test_configs.py +70 -33
  20. mcp_proxy_adapter/examples/run_full_test_suite.py +302 -109
  21. mcp_proxy_adapter/examples/run_security_tests.py +14 -5
  22. mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
  23. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
  24. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
  25. mcp_proxy_adapter/main.py +0 -2
  26. {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.25.dist-info}/METADATA +1 -1
  27. {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.25.dist-info}/RECORD +31 -15
  28. {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.25.dist-info}/WHEEL +0 -0
  29. {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.25.dist-info}/entry_points.txt +0 -0
  30. {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.25.dist-info}/licenses/LICENSE +0 -0
  31. {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.25.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,560 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Simple Certificate Creation Script
4
+ This script creates basic certificates for testing using mcp_security_framework.
5
+ Author: Vasiliy Zdanovskiy
6
+ email: vasilyvz@gmail.com
7
+ """
8
+ import os
9
+ import subprocess
10
+ import sys
11
+ import argparse
12
+ from pathlib import Path
13
+ # Import mcp_security_framework
14
+ try:
15
+ from mcp_security_framework.core.cert_manager import CertificateManager
16
+ from mcp_security_framework.schemas.config import CertificateConfig, CAConfig, ServerCertConfig, ClientCertConfig
17
+ from mcp_security_framework.schemas.models import CertificateType
18
+ SECURITY_FRAMEWORK_AVAILABLE = True
19
+ except ImportError:
20
+ SECURITY_FRAMEWORK_AVAILABLE = False
21
+ print("Warning: mcp_security_framework not available, falling back to OpenSSL")
22
+ class SimpleCertificateCreator:
23
+ """Create certificates using OpenSSL directly."""
24
+ def __init__(self, certs_dir: str = None, keys_dir: str = None):
25
+ # Use current working directory as base
26
+ cwd = Path.cwd()
27
+
28
+ if certs_dir:
29
+ self.certs_dir = Path(certs_dir).resolve()
30
+ else:
31
+ self.certs_dir = cwd / "certs"
32
+
33
+ if keys_dir:
34
+ self.keys_dir = Path(keys_dir).resolve()
35
+ else:
36
+ self.keys_dir = cwd / "keys"
37
+ # Create directories
38
+ self.certs_dir.mkdir(parents=True, exist_ok=True)
39
+ self.keys_dir.mkdir(parents=True, exist_ok=True)
40
+ print(f"🔧 Using certificates directory: {self.certs_dir}")
41
+ print(f"🔧 Using keys directory: {self.keys_dir}")
42
+ def run_command(self, cmd: list, description: str) -> bool:
43
+ """Run a command and handle errors."""
44
+ try:
45
+ print(f"🔧 {description}...")
46
+ # Use current working directory instead of project_root
47
+ result = subprocess.run(
48
+ cmd,
49
+ capture_output=True,
50
+ text=True,
51
+ check=True
52
+ )
53
+ print(f"✅ {description} completed successfully")
54
+ return True
55
+ except subprocess.CalledProcessError as e:
56
+ print(f"❌ {description} failed:")
57
+ print(f" Command: {' '.join(cmd)}")
58
+ print(f" Error: {e.stderr}")
59
+ return False
60
+ except Exception as e:
61
+ print(f"❌ {description} failed: {e}")
62
+ return False
63
+ def create_ca_certificate(self) -> bool:
64
+ """Create CA certificate using mcp_security_framework or OpenSSL fallback."""
65
+ ca_cert_path = self.certs_dir / "ca_cert.pem"
66
+ ca_key_path = self.keys_dir / "ca_key.pem"
67
+ if ca_cert_path.exists() and ca_key_path.exists():
68
+ print(f"ℹ️ CA certificate already exists: {ca_cert_path}")
69
+ return True
70
+ if SECURITY_FRAMEWORK_AVAILABLE:
71
+ return self._create_ca_certificate_with_framework()
72
+ else:
73
+ return self._create_ca_certificate_with_openssl()
74
+ def _create_ca_certificate_with_framework(self) -> bool:
75
+ """Create CA certificate using mcp_security_framework."""
76
+ try:
77
+ print("🔧 Creating CA certificate using mcp_security_framework...")
78
+ # Create CA certificate configuration
79
+ ca_config = CAConfig(
80
+ common_name="mcp_proxy_adapter_test_ca",
81
+ organization="Test Organization",
82
+ organizational_unit="Test Unit",
83
+ country="US",
84
+ state="Test State",
85
+ locality="Test City",
86
+ validity_years=10
87
+ )
88
+ # Create certificate manager
89
+ cert_config = CertificateConfig(
90
+ cert_storage_path=str(self.certs_dir),
91
+ key_storage_path=str(self.keys_dir),
92
+ default_validity_days=365,
93
+ key_size=2048,
94
+ hash_algorithm="sha256"
95
+ )
96
+ cert_manager = CertificateManager(cert_config)
97
+ # Create CA certificate
98
+ cert_pair = cert_manager.create_root_ca(ca_config)
99
+ if cert_pair and cert_pair.certificate_path and cert_pair.private_key_path:
100
+ # Rename the generated files to the expected names
101
+ generated_cert = Path(cert_pair.certificate_path)
102
+ generated_key = Path(cert_pair.private_key_path)
103
+ if generated_cert.exists() and generated_key.exists():
104
+ # Move to expected names
105
+ expected_cert = self.certs_dir / "ca_cert.pem"
106
+ expected_key = self.keys_dir / "ca_key.pem"
107
+ generated_cert.rename(expected_cert)
108
+ generated_key.rename(expected_key)
109
+ print("✅ CA certificate created successfully using mcp_security_framework")
110
+ return True
111
+ else:
112
+ print("❌ Generated CA certificate files not found")
113
+ return False
114
+ else:
115
+ print("❌ Failed to create CA certificate: Invalid certificate pair")
116
+ return False
117
+ except Exception as e:
118
+ print(f"❌ Error creating CA certificate with framework: {e}")
119
+ return False
120
+ def _create_ca_certificate_with_openssl(self) -> bool:
121
+ """Create CA certificate using OpenSSL fallback."""
122
+ ca_cert_path = self.certs_dir / "ca_cert.pem"
123
+ ca_key_path = self.keys_dir / "ca_key.pem"
124
+ # Create CA private key
125
+ key_cmd = [
126
+ "openssl", "genrsa", "-out", str(ca_key_path), "2048"
127
+ ]
128
+ if not self.run_command(key_cmd, "Creating CA private key"):
129
+ return False
130
+ # Create CA certificate
131
+ cert_cmd = [
132
+ "openssl", "req", "-new", "-x509", "-days", "3650",
133
+ "-key", str(ca_key_path),
134
+ "-out", str(ca_cert_path),
135
+ "-subj", "/C=US/ST=Test State/L=Test City/O=Test Organization/CN=MCP Proxy Adapter Test CA"
136
+ ]
137
+ return self.run_command(cert_cmd, "Creating CA certificate")
138
+ def create_server_certificate(self) -> bool:
139
+ """Create server certificate using mcp_security_framework or OpenSSL fallback."""
140
+ server_cert_path = self.certs_dir / "server_cert.pem"
141
+ server_key_path = self.certs_dir / "server_key.pem"
142
+ if server_cert_path.exists() and server_key_path.exists():
143
+ print("ℹ️ Server certificate already exists")
144
+ return True
145
+ if SECURITY_FRAMEWORK_AVAILABLE:
146
+ return self._create_server_certificate_with_framework()
147
+ else:
148
+ return self._create_server_certificate_with_openssl()
149
+ def _create_server_certificate_with_framework(self) -> bool:
150
+ """Create server certificate using mcp_security_framework."""
151
+ try:
152
+ print("🔧 Creating server certificate using mcp_security_framework...")
153
+ # Find CA certificate and key files
154
+ ca_cert_path = None
155
+ ca_key_path = None
156
+ # Look for CA certificate files with expected names
157
+ expected_ca_cert = self.certs_dir / "ca_cert.pem"
158
+ expected_ca_key = self.keys_dir / "ca_key.pem"
159
+ if expected_ca_cert.exists():
160
+ ca_cert_path = str(expected_ca_cert)
161
+ else:
162
+ # Fallback: look for CA certificate files with pattern
163
+ for cert_file in self.certs_dir.glob("*_ca.crt"):
164
+ ca_cert_path = str(cert_file)
165
+ break
166
+ if expected_ca_key.exists():
167
+ ca_key_path = str(expected_ca_key)
168
+ else:
169
+ # Fallback: look for CA key files with pattern
170
+ for key_file in self.keys_dir.glob("*_ca.key"):
171
+ ca_key_path = str(key_file)
172
+ break
173
+ if not ca_cert_path or not ca_key_path:
174
+ print("❌ CA certificate or key not found")
175
+ return False
176
+ # Create server certificate configuration
177
+ server_config = ServerCertConfig(
178
+ common_name="localhost",
179
+ organization="Test Organization",
180
+ organizational_unit="Test Unit",
181
+ country="US",
182
+ state="Test State",
183
+ locality="Test City",
184
+ subject_alt_names=["localhost", "127.0.0.1"],
185
+ validity_years=1,
186
+ ca_cert_path=ca_cert_path,
187
+ ca_key_path=ca_key_path
188
+ )
189
+ # Create certificate manager
190
+ cert_config = CertificateConfig(
191
+ cert_storage_path=str(self.certs_dir),
192
+ key_storage_path=str(self.certs_dir), # Server keys in certs dir
193
+ default_validity_days=365,
194
+ key_size=2048,
195
+ hash_algorithm="sha256"
196
+ )
197
+ cert_manager = CertificateManager(cert_config)
198
+ # Create server certificate
199
+ cert_pair = cert_manager.create_server_certificate(server_config)
200
+ if cert_pair and cert_pair.certificate_path and cert_pair.private_key_path:
201
+ # Rename the generated files to the expected names
202
+ generated_cert = Path(cert_pair.certificate_path)
203
+ generated_key = Path(cert_pair.private_key_path)
204
+ if generated_cert.exists() and generated_key.exists():
205
+ # Move to expected names
206
+ generated_cert.rename(self.certs_dir / "server_cert.pem")
207
+ generated_key.rename(self.certs_dir / "server_key.pem")
208
+ print("✅ Server certificate created successfully using mcp_security_framework")
209
+ return True
210
+ else:
211
+ print("❌ Generated certificate files not found")
212
+ return False
213
+ else:
214
+ print("❌ Failed to create server certificate: Invalid certificate pair")
215
+ return False
216
+ except Exception as e:
217
+ print(f"❌ Error creating server certificate with framework: {e}")
218
+ return False
219
+ def _create_server_certificate_with_openssl(self) -> bool:
220
+ """Create server certificate using OpenSSL fallback."""
221
+ server_cert_path = self.certs_dir / "server_cert.pem"
222
+ server_key_path = self.certs_dir / "server_key.pem"
223
+ # Create server private key
224
+ key_cmd = [
225
+ "openssl", "genrsa", "-out", str(server_key_path), "2048"
226
+ ]
227
+ if not self.run_command(key_cmd, "Creating server private key"):
228
+ return False
229
+ # Create server certificate signing request
230
+ csr_path = self.certs_dir / "server.csr"
231
+ csr_cmd = [
232
+ "openssl", "req", "-new",
233
+ "-key", str(server_key_path),
234
+ "-out", str(csr_path),
235
+ "-subj", "/C=US/ST=Test State/L=Test City/O=Test Organization/CN=localhost"
236
+ ]
237
+ if not self.run_command(csr_cmd, "Creating server CSR"):
238
+ return False
239
+ # Create server certificate
240
+ cert_cmd = [
241
+ "openssl", "x509", "-req", "-days", "730",
242
+ "-in", str(csr_path),
243
+ "-CA", str(self.certs_dir / "ca_cert.pem"),
244
+ "-CAkey", str(self.keys_dir / "ca_key.pem"),
245
+ "-CAcreateserial",
246
+ "-out", str(server_cert_path)
247
+ ]
248
+ success = self.run_command(cert_cmd, "Creating server certificate")
249
+ # Clean up CSR
250
+ if csr_path.exists():
251
+ csr_path.unlink()
252
+ return success
253
+ def create_client_certificate(self, name: str, common_name: str, roles: list = None, permissions: list = None) -> bool:
254
+ """Create client certificate using mcp_security_framework or OpenSSL fallback."""
255
+ cert_path = self.certs_dir / f"{name}_cert.pem"
256
+ key_path = self.certs_dir / f"{name}_key.pem"
257
+ if cert_path.exists() and key_path.exists():
258
+ print(f"ℹ️ Client certificate {name} already exists: {cert_path}")
259
+ return True
260
+ if SECURITY_FRAMEWORK_AVAILABLE:
261
+ return self._create_client_certificate_with_framework(name, common_name, roles, permissions)
262
+ else:
263
+ return self._create_client_certificate_with_openssl(name, common_name)
264
+ def _create_client_certificate_with_framework(self, name: str, common_name: str, roles: list = None, permissions: list = None) -> bool:
265
+ """Create client certificate using mcp_security_framework."""
266
+ try:
267
+ print(f"🔧 Creating client certificate {name} using mcp_security_framework...")
268
+ # Find CA certificate and key files
269
+ ca_cert_path = None
270
+ ca_key_path = None
271
+ # Look for CA certificate files with expected names
272
+ expected_ca_cert = self.certs_dir / "ca_cert.pem"
273
+ expected_ca_key = self.keys_dir / "ca_key.pem"
274
+ if expected_ca_cert.exists():
275
+ ca_cert_path = str(expected_ca_cert)
276
+ else:
277
+ # Fallback: look for CA certificate files with pattern
278
+ for cert_file in self.certs_dir.glob("*_ca.crt"):
279
+ ca_cert_path = str(cert_file)
280
+ break
281
+ if expected_ca_key.exists():
282
+ ca_key_path = str(expected_ca_key)
283
+ else:
284
+ # Fallback: look for CA key files with pattern
285
+ for key_file in self.keys_dir.glob("*_ca.key"):
286
+ ca_key_path = str(key_file)
287
+ break
288
+ if not ca_cert_path or not ca_key_path:
289
+ print("❌ CA certificate or key not found")
290
+ return False
291
+ # Create client certificate configuration
292
+ client_config = ClientCertConfig(
293
+ common_name=common_name,
294
+ organization="Test Organization",
295
+ organizational_unit="Test Unit",
296
+ country="US",
297
+ state="Test State",
298
+ locality="Test City",
299
+ validity_years=1,
300
+ ca_cert_path=ca_cert_path,
301
+ ca_key_path=ca_key_path
302
+ )
303
+ # Create certificate manager
304
+ cert_config = CertificateConfig(
305
+ cert_storage_path=str(self.certs_dir),
306
+ key_storage_path=str(self.certs_dir), # Client keys in certs dir
307
+ default_validity_days=365,
308
+ key_size=2048,
309
+ hash_algorithm="sha256"
310
+ )
311
+ cert_manager = CertificateManager(cert_config)
312
+ # Create client certificate
313
+ cert_pair = cert_manager.create_client_certificate(client_config)
314
+ if cert_pair and cert_pair.certificate_path and cert_pair.private_key_path:
315
+ # Rename the generated files to the expected names
316
+ generated_cert = Path(cert_pair.certificate_path)
317
+ generated_key = Path(cert_pair.private_key_path)
318
+ if generated_cert.exists() and generated_key.exists():
319
+ # Move to expected names
320
+ expected_cert = self.certs_dir / f"{name}_cert.pem"
321
+ expected_key = self.certs_dir / f"{name}_key.pem"
322
+ generated_cert.rename(expected_cert)
323
+ generated_key.rename(expected_key)
324
+ print(f"✅ Client certificate {name} created successfully using mcp_security_framework")
325
+ return True
326
+ else:
327
+ print(f"❌ Generated certificate files not found for {name}")
328
+ return False
329
+ else:
330
+ print(f"❌ Failed to create client certificate {name}: Invalid certificate pair")
331
+ return False
332
+ except Exception as e:
333
+ print(f"❌ Error creating client certificate {name} with framework: {e}")
334
+ return False
335
+ def _create_client_certificate_with_openssl(self, name: str, common_name: str) -> bool:
336
+ """Create client certificate using OpenSSL fallback."""
337
+ cert_path = self.certs_dir / f"{name}_cert.pem"
338
+ key_path = self.certs_dir / f"{name}_key.pem"
339
+ # Create client private key
340
+ key_cmd = [
341
+ "openssl", "genrsa", "-out", str(key_path), "2048"
342
+ ]
343
+ if not self.run_command(key_cmd, f"Creating {name} private key"):
344
+ return False
345
+ # Create client certificate signing request
346
+ csr_path = self.certs_dir / f"{name}.csr"
347
+ csr_cmd = [
348
+ "openssl", "req", "-new",
349
+ "-key", str(key_path),
350
+ "-out", str(csr_path),
351
+ "-subj", f"/C=US/ST=Test State/L=Test City/O=Test Organization/CN={common_name}"
352
+ ]
353
+ if not self.run_command(csr_cmd, f"Creating {name} CSR"):
354
+ return False
355
+ # Create client certificate
356
+ cert_cmd = [
357
+ "openssl", "x509", "-req", "-days", "730",
358
+ "-in", str(csr_path),
359
+ "-CA", str(self.certs_dir / "ca_cert.pem"),
360
+ "-CAkey", str(self.keys_dir / "ca_key.pem"),
361
+ "-CAcreateserial",
362
+ "-out", str(cert_path)
363
+ ]
364
+ success = self.run_command(cert_cmd, f"Creating {name} certificate")
365
+ # Clean up CSR
366
+ if csr_path.exists():
367
+ csr_path.unlink()
368
+ return success
369
+ def create_legacy_certificates(self) -> bool:
370
+ """Create legacy certificate files for compatibility."""
371
+ legacy_files = [
372
+ ("client_admin.crt", "client_admin.key", "admin"),
373
+ ("admin.crt", "admin.key", "admin"),
374
+ ("user.crt", "user.key", "user"),
375
+ ("readonly.crt", "readonly.key", "readonly")
376
+ ]
377
+ success = True
378
+ for cert_file, key_file, source_name in legacy_files:
379
+ cert_path = self.certs_dir / cert_file
380
+ key_path = self.certs_dir / key_file
381
+ if not cert_path.exists() or not key_path.exists():
382
+ source_cert = self.certs_dir / f"{source_name}_cert.pem"
383
+ source_key = self.certs_dir / f"{source_name}_key.pem"
384
+ if source_cert.exists() and source_key.exists():
385
+ self.run_command(["cp", str(source_cert), str(cert_path)], f"Creating {cert_file}")
386
+ self.run_command(["cp", str(source_key), str(key_path)], f"Creating {key_file}")
387
+ else:
388
+ print(f"⚠️ Source certificate {source_name} not found for {cert_file}")
389
+ # Don't fail the entire process for missing legacy certificates
390
+ continue
391
+ return True # Always return True for legacy certificates
392
+ def validate_certificates(self) -> bool:
393
+ """Validate all created certificates."""
394
+ print("\n🔍 Validating certificates...")
395
+ cert_files = [
396
+ "ca_cert.pem",
397
+ "server_cert.pem",
398
+ "admin_cert.pem",
399
+ "user_cert.pem",
400
+ "readonly_cert.pem",
401
+ "guest_cert.pem",
402
+ "proxy_cert.pem"
403
+ ]
404
+ success = True
405
+ for cert_file in cert_files:
406
+ cert_path = self.certs_dir / cert_file
407
+ if cert_path.exists():
408
+ try:
409
+ result = subprocess.run(
410
+ ["openssl", "x509", "-in", str(cert_path), "-text", "-noout"],
411
+ capture_output=True,
412
+ text=True,
413
+ check=True
414
+ )
415
+ print(f"✅ {cert_file}: Valid")
416
+ except subprocess.CalledProcessError:
417
+ print(f"❌ {cert_file}: Invalid")
418
+ success = False
419
+ else:
420
+ print(f"⚠️ {cert_file}: Not found")
421
+ return success
422
+ def create_all(self) -> bool:
423
+ """Create all certificates."""
424
+ print("🔐 Creating All Certificates for Security Testing")
425
+ print("=" * 60)
426
+ success = True
427
+ # 1. Create CA certificate
428
+ if not self.create_ca_certificate():
429
+ success = False
430
+ print("❌ Cannot continue without CA certificate")
431
+ return False
432
+ # 2. Create server certificate
433
+ if not self.create_server_certificate():
434
+ success = False
435
+ # 3. Create client certificates
436
+ print("\n👥 Creating client certificates...")
437
+ client_certs = [
438
+ ("admin", "admin-client", ["admin"], ["read", "write", "execute", "delete", "admin", "register", "unregister", "heartbeat", "discover"]),
439
+ ("user", "user-client", ["user"], ["read", "execute", "register", "unregister", "heartbeat", "discover"]),
440
+ ("readonly", "readonly-client", ["readonly"], ["read", "discover"]),
441
+ ("guest", "guest-client", ["guest"], ["read", "discover"]),
442
+ ("proxy", "proxy-client", ["proxy"], ["register", "unregister", "heartbeat", "discover"])
443
+ ]
444
+ for name, common_name, roles, permissions in client_certs:
445
+ if not self.create_client_certificate(name, common_name, roles, permissions):
446
+ success = False
447
+ # 4. Create legacy certificates
448
+ print("\n🔄 Creating legacy certificates...")
449
+ if not self.create_legacy_certificates():
450
+ success = False
451
+ # 5. Validate certificates
452
+ if not self.validate_certificates():
453
+ success = False
454
+ # Create compatibility symlinks
455
+ if success:
456
+ # CA certificate symlink
457
+ ca_cert = self.certs_dir / "ca_cert.pem"
458
+ expected_ca_cert = self.certs_dir / "mcp_proxy_adapter_ca_ca.crt"
459
+ if ca_cert.exists() and not expected_ca_cert.exists():
460
+ try:
461
+ expected_ca_cert.symlink_to(ca_cert)
462
+ print(f"✅ Created CA certificate symlink: {expected_ca_cert}")
463
+ except OSError:
464
+ # On Windows, symlink might require admin privileges, copy instead
465
+ import shutil
466
+ shutil.copy2(ca_cert, expected_ca_cert)
467
+ print(f"✅ Created CA certificate copy: {expected_ca_cert}")
468
+
469
+ # Server certificate symlink
470
+ server_cert = self.certs_dir / "server_cert.pem"
471
+ expected_server_cert = self.certs_dir / "localhost_server.crt"
472
+ if server_cert.exists() and not expected_server_cert.exists():
473
+ try:
474
+ expected_server_cert.symlink_to(server_cert)
475
+ print(f"✅ Created server certificate symlink: {expected_server_cert}")
476
+ except OSError:
477
+ # On Windows, symlink might require admin privileges, copy instead
478
+ import shutil
479
+ shutil.copy2(server_cert, expected_server_cert)
480
+ print(f"✅ Created server certificate copy: {expected_server_cert}")
481
+
482
+ # Server key symlink - check if it's in certs or keys directory
483
+ server_key_certs = self.certs_dir / "server_key.pem"
484
+ server_key_keys = self.keys_dir / "server_key.pem"
485
+
486
+ if server_key_certs.exists():
487
+ # Server key is in certs directory, move it to keys directory
488
+ import shutil
489
+ shutil.move(str(server_key_certs), str(server_key_keys))
490
+ print(f"✅ Moved server key to keys directory: {server_key_keys}")
491
+
492
+ if server_key_keys.exists():
493
+ expected_server_key = self.keys_dir / "localhost_server.key"
494
+ if not expected_server_key.exists():
495
+ try:
496
+ expected_server_key.symlink_to(server_key_keys)
497
+ print(f"✅ Created server key symlink: {expected_server_key}")
498
+ except OSError:
499
+ # On Windows, symlink might require admin privileges, copy instead
500
+ import shutil
501
+ shutil.copy2(server_key_keys, expected_server_key)
502
+ print(f"✅ Created server key copy: {expected_server_key}")
503
+
504
+ # Print summary
505
+ print("\n" + "=" * 60)
506
+ print("📊 CERTIFICATE CREATION SUMMARY")
507
+ print("=" * 60)
508
+ if success:
509
+ print("✅ All certificates created successfully!")
510
+ print(f"📁 Certificates directory: {self.certs_dir}")
511
+ print(f"🔑 Keys directory: {self.keys_dir}")
512
+ print("\n📋 Created certificates:")
513
+ cert_files = list(self.certs_dir.glob("*.pem")) + list(self.certs_dir.glob("*.crt"))
514
+ for cert_file in sorted(cert_files):
515
+ print(f" - {cert_file.name}")
516
+ key_files = list(self.keys_dir.glob("*.pem")) + list(self.keys_dir.glob("*.key"))
517
+ for key_file in sorted(key_files):
518
+ print(f" - {key_file.name}")
519
+ else:
520
+ print("❌ Some certificates failed to create")
521
+ print("Check the error messages above")
522
+ return success
523
+ def main():
524
+ """Main function."""
525
+ parser = argparse.ArgumentParser(description="Create certificates for testing")
526
+ parser.add_argument("--certs-dir", help="Directory for certificates (default: ./certs)")
527
+ parser.add_argument("--keys-dir", help="Directory for keys (default: ./keys)")
528
+ args = parser.parse_args()
529
+
530
+ # If no directories specified, check if we're in a test environment
531
+ if not args.certs_dir and not args.keys_dir:
532
+ cwd = Path.cwd()
533
+ # Check if we're in a test environment by looking for typical directories
534
+ if (cwd / "configs").exists() and (cwd / "examples").exists():
535
+ # We're in a test environment, use current directory
536
+ certs_dir = cwd / "certs"
537
+ keys_dir = cwd / "keys"
538
+ else:
539
+ # Use default project structure
540
+ certs_dir = None
541
+ keys_dir = None
542
+ else:
543
+ certs_dir = args.certs_dir
544
+ keys_dir = args.keys_dir
545
+
546
+ creator = SimpleCertificateCreator(
547
+ certs_dir=certs_dir,
548
+ keys_dir=keys_dir
549
+ )
550
+ try:
551
+ success = creator.create_all()
552
+ sys.exit(0 if success else 1)
553
+ except KeyboardInterrupt:
554
+ print("\n⚠️ Certificate creation interrupted by user")
555
+ sys.exit(1)
556
+ except Exception as e:
557
+ print(f"\n❌ Certificate creation failed: {e}")
558
+ sys.exit(1)
559
+ if __name__ == "__main__":
560
+ main()