mcp-proxy-adapter 6.3.4__py3-none-any.whl → 6.3.5__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 (129) hide show
  1. mcp_proxy_adapter/__init__.py +9 -5
  2. mcp_proxy_adapter/__main__.py +1 -1
  3. mcp_proxy_adapter/api/app.py +227 -176
  4. mcp_proxy_adapter/api/handlers.py +68 -60
  5. mcp_proxy_adapter/api/middleware/__init__.py +7 -5
  6. mcp_proxy_adapter/api/middleware/base.py +19 -16
  7. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
  8. mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
  9. mcp_proxy_adapter/api/middleware/factory.py +50 -52
  10. mcp_proxy_adapter/api/middleware/logging.py +46 -30
  11. mcp_proxy_adapter/api/middleware/performance.py +19 -16
  12. mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
  13. mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
  14. mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
  15. mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
  16. mcp_proxy_adapter/api/schemas.py +69 -43
  17. mcp_proxy_adapter/api/tool_integration.py +83 -63
  18. mcp_proxy_adapter/api/tools.py +60 -50
  19. mcp_proxy_adapter/commands/__init__.py +15 -6
  20. mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
  21. mcp_proxy_adapter/commands/base.py +108 -112
  22. mcp_proxy_adapter/commands/builtin_commands.py +28 -18
  23. mcp_proxy_adapter/commands/catalog_manager.py +394 -265
  24. mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
  25. mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
  26. mcp_proxy_adapter/commands/command_registry.py +275 -226
  27. mcp_proxy_adapter/commands/config_command.py +48 -33
  28. mcp_proxy_adapter/commands/dependency_container.py +22 -23
  29. mcp_proxy_adapter/commands/dependency_manager.py +65 -56
  30. mcp_proxy_adapter/commands/echo_command.py +15 -15
  31. mcp_proxy_adapter/commands/health_command.py +31 -29
  32. mcp_proxy_adapter/commands/help_command.py +97 -61
  33. mcp_proxy_adapter/commands/hooks.py +65 -49
  34. mcp_proxy_adapter/commands/key_management_command.py +148 -147
  35. mcp_proxy_adapter/commands/load_command.py +58 -40
  36. mcp_proxy_adapter/commands/plugins_command.py +80 -54
  37. mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
  38. mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
  39. mcp_proxy_adapter/commands/reload_command.py +43 -37
  40. mcp_proxy_adapter/commands/result.py +26 -33
  41. mcp_proxy_adapter/commands/role_test_command.py +26 -26
  42. mcp_proxy_adapter/commands/roles_management_command.py +176 -173
  43. mcp_proxy_adapter/commands/security_command.py +134 -122
  44. mcp_proxy_adapter/commands/settings_command.py +47 -56
  45. mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
  46. mcp_proxy_adapter/commands/token_management_command.py +129 -158
  47. mcp_proxy_adapter/commands/transport_management_command.py +41 -36
  48. mcp_proxy_adapter/commands/unload_command.py +42 -37
  49. mcp_proxy_adapter/config.py +36 -35
  50. mcp_proxy_adapter/core/__init__.py +19 -21
  51. mcp_proxy_adapter/core/app_factory.py +30 -9
  52. mcp_proxy_adapter/core/app_runner.py +81 -64
  53. mcp_proxy_adapter/core/auth_validator.py +176 -182
  54. mcp_proxy_adapter/core/certificate_utils.py +469 -426
  55. mcp_proxy_adapter/core/client.py +155 -126
  56. mcp_proxy_adapter/core/client_manager.py +60 -54
  57. mcp_proxy_adapter/core/client_security.py +108 -88
  58. mcp_proxy_adapter/core/config_converter.py +176 -143
  59. mcp_proxy_adapter/core/config_validator.py +12 -4
  60. mcp_proxy_adapter/core/crl_utils.py +21 -7
  61. mcp_proxy_adapter/core/errors.py +64 -20
  62. mcp_proxy_adapter/core/logging.py +34 -29
  63. mcp_proxy_adapter/core/mtls_asgi.py +29 -25
  64. mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
  65. mcp_proxy_adapter/core/protocol_manager.py +154 -104
  66. mcp_proxy_adapter/core/proxy_client.py +202 -144
  67. mcp_proxy_adapter/core/proxy_registration.py +7 -3
  68. mcp_proxy_adapter/core/role_utils.py +139 -125
  69. mcp_proxy_adapter/core/security_adapter.py +88 -77
  70. mcp_proxy_adapter/core/security_factory.py +50 -44
  71. mcp_proxy_adapter/core/security_integration.py +72 -24
  72. mcp_proxy_adapter/core/server_adapter.py +68 -64
  73. mcp_proxy_adapter/core/server_engine.py +71 -53
  74. mcp_proxy_adapter/core/settings.py +68 -58
  75. mcp_proxy_adapter/core/ssl_utils.py +69 -56
  76. mcp_proxy_adapter/core/transport_manager.py +72 -60
  77. mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
  78. mcp_proxy_adapter/core/utils.py +4 -2
  79. mcp_proxy_adapter/custom_openapi.py +107 -99
  80. mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
  81. mcp_proxy_adapter/examples/commands/__init__.py +1 -1
  82. mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
  83. mcp_proxy_adapter/examples/debug_request_state.py +38 -19
  84. mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
  85. mcp_proxy_adapter/examples/demo_client.py +48 -36
  86. mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
  87. mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
  88. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
  89. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  90. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
  91. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  92. mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
  93. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
  94. mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
  95. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
  96. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  97. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
  98. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  99. mcp_proxy_adapter/examples/full_application/main.py +27 -2
  100. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
  101. mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
  102. mcp_proxy_adapter/examples/generate_certificates.py +31 -16
  103. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
  104. mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
  105. mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
  106. mcp_proxy_adapter/examples/run_example.py +23 -5
  107. mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
  108. mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
  109. mcp_proxy_adapter/examples/run_security_tests.py +103 -41
  110. mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
  111. mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
  112. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
  113. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
  114. mcp_proxy_adapter/examples/security_test_client.py +196 -127
  115. mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
  116. mcp_proxy_adapter/examples/test_config.py +19 -4
  117. mcp_proxy_adapter/examples/test_config_generator.py +23 -7
  118. mcp_proxy_adapter/examples/test_examples.py +84 -56
  119. mcp_proxy_adapter/examples/universal_client.py +119 -62
  120. mcp_proxy_adapter/openapi.py +108 -115
  121. mcp_proxy_adapter/utils/config_generator.py +429 -274
  122. mcp_proxy_adapter/version.py +1 -2
  123. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
  124. mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
  125. mcp_proxy_adapter-6.3.4.dist-info/RECORD +0 -143
  126. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
  127. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
  128. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
  129. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -10,17 +10,27 @@ import subprocess
10
10
  import sys
11
11
  import argparse
12
12
  from pathlib import Path
13
+
13
14
  # Import mcp_security_framework
14
15
  try:
15
16
  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.config import (
18
+ CertificateConfig,
19
+ CAConfig,
20
+ ServerCertConfig,
21
+ ClientCertConfig,
22
+ )
17
23
  from mcp_security_framework.schemas.models import CertificateType
24
+
18
25
  SECURITY_FRAMEWORK_AVAILABLE = True
19
26
  except ImportError:
20
27
  SECURITY_FRAMEWORK_AVAILABLE = False
21
28
  print("Warning: mcp_security_framework not available, falling back to OpenSSL")
29
+
30
+
22
31
  class SimpleCertificateCreator:
23
32
  """Create certificates using OpenSSL directly."""
33
+
24
34
  def __init__(self, certs_dir: str = None, keys_dir: str = None):
25
35
  # Use current working directory as base
26
36
  cwd = Path.cwd()
@@ -39,17 +49,13 @@ class SimpleCertificateCreator:
39
49
  self.keys_dir.mkdir(parents=True, exist_ok=True)
40
50
  print(f"🔧 Using certificates directory: {self.certs_dir}")
41
51
  print(f"🔧 Using keys directory: {self.keys_dir}")
52
+
42
53
  def run_command(self, cmd: list, description: str) -> bool:
43
54
  """Run a command and handle errors."""
44
55
  try:
45
56
  print(f"🔧 {description}...")
46
57
  # 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
- )
58
+ result = subprocess.run(cmd, capture_output=True, text=True, check=True)
53
59
  print(f"✅ {description} completed successfully")
54
60
  return True
55
61
  except subprocess.CalledProcessError as e:
@@ -60,6 +66,7 @@ class SimpleCertificateCreator:
60
66
  except Exception as e:
61
67
  print(f"❌ {description} failed: {e}")
62
68
  return False
69
+
63
70
  def create_ca_certificate(self) -> bool:
64
71
  """Create CA certificate using mcp_security_framework or OpenSSL fallback."""
65
72
  ca_cert_path = self.certs_dir / "ca_cert.pem"
@@ -71,6 +78,7 @@ class SimpleCertificateCreator:
71
78
  return self._create_ca_certificate_with_framework()
72
79
  else:
73
80
  return self._create_ca_certificate_with_openssl()
81
+
74
82
  def _create_ca_certificate_with_framework(self) -> bool:
75
83
  """Create CA certificate using mcp_security_framework."""
76
84
  try:
@@ -83,7 +91,7 @@ class SimpleCertificateCreator:
83
91
  country="US",
84
92
  state="Test State",
85
93
  locality="Test City",
86
- validity_years=10
94
+ validity_years=10,
87
95
  )
88
96
  # Create certificate manager
89
97
  cert_config = CertificateConfig(
@@ -91,7 +99,7 @@ class SimpleCertificateCreator:
91
99
  key_storage_path=str(self.keys_dir),
92
100
  default_validity_days=365,
93
101
  key_size=2048,
94
- hash_algorithm="sha256"
102
+ hash_algorithm="sha256",
95
103
  )
96
104
  cert_manager = CertificateManager(cert_config)
97
105
  # Create CA certificate
@@ -106,7 +114,9 @@ class SimpleCertificateCreator:
106
114
  expected_key = self.keys_dir / "ca_key.pem"
107
115
  generated_cert.rename(expected_cert)
108
116
  generated_key.rename(expected_key)
109
- print("✅ CA certificate created successfully using mcp_security_framework")
117
+ print(
118
+ "✅ CA certificate created successfully using mcp_security_framework"
119
+ )
110
120
  return True
111
121
  else:
112
122
  print("❌ Generated CA certificate files not found")
@@ -117,24 +127,32 @@ class SimpleCertificateCreator:
117
127
  except Exception as e:
118
128
  print(f"❌ Error creating CA certificate with framework: {e}")
119
129
  return False
130
+
120
131
  def _create_ca_certificate_with_openssl(self) -> bool:
121
132
  """Create CA certificate using OpenSSL fallback."""
122
133
  ca_cert_path = self.certs_dir / "ca_cert.pem"
123
134
  ca_key_path = self.keys_dir / "ca_key.pem"
124
135
  # Create CA private key
125
- key_cmd = [
126
- "openssl", "genrsa", "-out", str(ca_key_path), "2048"
127
- ]
136
+ key_cmd = ["openssl", "genrsa", "-out", str(ca_key_path), "2048"]
128
137
  if not self.run_command(key_cmd, "Creating CA private key"):
129
138
  return False
130
139
  # Create CA certificate
131
140
  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"
141
+ "openssl",
142
+ "req",
143
+ "-new",
144
+ "-x509",
145
+ "-days",
146
+ "3650",
147
+ "-key",
148
+ str(ca_key_path),
149
+ "-out",
150
+ str(ca_cert_path),
151
+ "-subj",
152
+ "/C=US/ST=Test State/L=Test City/O=Test Organization/CN=MCP Proxy Adapter Test CA",
136
153
  ]
137
154
  return self.run_command(cert_cmd, "Creating CA certificate")
155
+
138
156
  def create_server_certificate(self) -> bool:
139
157
  """Create server certificate using mcp_security_framework or OpenSSL fallback."""
140
158
  server_cert_path = self.certs_dir / "server_cert.pem"
@@ -146,6 +164,7 @@ class SimpleCertificateCreator:
146
164
  return self._create_server_certificate_with_framework()
147
165
  else:
148
166
  return self._create_server_certificate_with_openssl()
167
+
149
168
  def _create_server_certificate_with_framework(self) -> bool:
150
169
  """Create server certificate using mcp_security_framework."""
151
170
  try:
@@ -184,7 +203,7 @@ class SimpleCertificateCreator:
184
203
  subject_alt_names=["localhost", "127.0.0.1"],
185
204
  validity_years=1,
186
205
  ca_cert_path=ca_cert_path,
187
- ca_key_path=ca_key_path
206
+ ca_key_path=ca_key_path,
188
207
  )
189
208
  # Create certificate manager
190
209
  cert_config = CertificateConfig(
@@ -192,7 +211,7 @@ class SimpleCertificateCreator:
192
211
  key_storage_path=str(self.certs_dir), # Server keys in certs dir
193
212
  default_validity_days=365,
194
213
  key_size=2048,
195
- hash_algorithm="sha256"
214
+ hash_algorithm="sha256",
196
215
  )
197
216
  cert_manager = CertificateManager(cert_config)
198
217
  # Create server certificate
@@ -205,52 +224,71 @@ class SimpleCertificateCreator:
205
224
  # Move to expected names
206
225
  generated_cert.rename(self.certs_dir / "server_cert.pem")
207
226
  generated_key.rename(self.certs_dir / "server_key.pem")
208
- print("✅ Server certificate created successfully using mcp_security_framework")
227
+ print(
228
+ "✅ Server certificate created successfully using mcp_security_framework"
229
+ )
209
230
  return True
210
231
  else:
211
232
  print("❌ Generated certificate files not found")
212
233
  return False
213
234
  else:
214
- print("❌ Failed to create server certificate: Invalid certificate pair")
235
+ print(
236
+ "❌ Failed to create server certificate: Invalid certificate pair"
237
+ )
215
238
  return False
216
239
  except Exception as e:
217
240
  print(f"❌ Error creating server certificate with framework: {e}")
218
241
  return False
242
+
219
243
  def _create_server_certificate_with_openssl(self) -> bool:
220
244
  """Create server certificate using OpenSSL fallback."""
221
245
  server_cert_path = self.certs_dir / "server_cert.pem"
222
246
  server_key_path = self.certs_dir / "server_key.pem"
223
247
  # Create server private key
224
- key_cmd = [
225
- "openssl", "genrsa", "-out", str(server_key_path), "2048"
226
- ]
248
+ key_cmd = ["openssl", "genrsa", "-out", str(server_key_path), "2048"]
227
249
  if not self.run_command(key_cmd, "Creating server private key"):
228
250
  return False
229
251
  # Create server certificate signing request
230
252
  csr_path = self.certs_dir / "server.csr"
231
253
  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"
254
+ "openssl",
255
+ "req",
256
+ "-new",
257
+ "-key",
258
+ str(server_key_path),
259
+ "-out",
260
+ str(csr_path),
261
+ "-subj",
262
+ "/C=US/ST=Test State/L=Test City/O=Test Organization/CN=localhost",
236
263
  ]
237
264
  if not self.run_command(csr_cmd, "Creating server CSR"):
238
265
  return False
239
266
  # Create server certificate
240
267
  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"),
268
+ "openssl",
269
+ "x509",
270
+ "-req",
271
+ "-days",
272
+ "730",
273
+ "-in",
274
+ str(csr_path),
275
+ "-CA",
276
+ str(self.certs_dir / "ca_cert.pem"),
277
+ "-CAkey",
278
+ str(self.keys_dir / "ca_key.pem"),
245
279
  "-CAcreateserial",
246
- "-out", str(server_cert_path)
280
+ "-out",
281
+ str(server_cert_path),
247
282
  ]
248
283
  success = self.run_command(cert_cmd, "Creating server certificate")
249
284
  # Clean up CSR
250
285
  if csr_path.exists():
251
286
  csr_path.unlink()
252
287
  return success
253
- def create_client_certificate(self, name: str, common_name: str, roles: list = None, permissions: list = None) -> bool:
288
+
289
+ def create_client_certificate(
290
+ self, name: str, common_name: str, roles: list = None, permissions: list = None
291
+ ) -> bool:
254
292
  """Create client certificate using mcp_security_framework or OpenSSL fallback."""
255
293
  cert_path = self.certs_dir / f"{name}_cert.pem"
256
294
  key_path = self.certs_dir / f"{name}_key.pem"
@@ -258,13 +296,20 @@ class SimpleCertificateCreator:
258
296
  print(f"ℹ️ Client certificate {name} already exists: {cert_path}")
259
297
  return True
260
298
  if SECURITY_FRAMEWORK_AVAILABLE:
261
- return self._create_client_certificate_with_framework(name, common_name, roles, permissions)
299
+ return self._create_client_certificate_with_framework(
300
+ name, common_name, roles, permissions
301
+ )
262
302
  else:
263
303
  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:
304
+
305
+ def _create_client_certificate_with_framework(
306
+ self, name: str, common_name: str, roles: list = None, permissions: list = None
307
+ ) -> bool:
265
308
  """Create client certificate using mcp_security_framework."""
266
309
  try:
267
- print(f"🔧 Creating client certificate {name} using mcp_security_framework...")
310
+ print(
311
+ f"🔧 Creating client certificate {name} using mcp_security_framework..."
312
+ )
268
313
  # Find CA certificate and key files
269
314
  ca_cert_path = None
270
315
  ca_key_path = None
@@ -298,7 +343,7 @@ class SimpleCertificateCreator:
298
343
  locality="Test City",
299
344
  validity_years=1,
300
345
  ca_cert_path=ca_cert_path,
301
- ca_key_path=ca_key_path
346
+ ca_key_path=ca_key_path,
302
347
  )
303
348
  # Create certificate manager
304
349
  cert_config = CertificateConfig(
@@ -306,7 +351,7 @@ class SimpleCertificateCreator:
306
351
  key_storage_path=str(self.certs_dir), # Client keys in certs dir
307
352
  default_validity_days=365,
308
353
  key_size=2048,
309
- hash_algorithm="sha256"
354
+ hash_algorithm="sha256",
310
355
  )
311
356
  cert_manager = CertificateManager(cert_config)
312
357
  # Create client certificate
@@ -321,58 +366,77 @@ class SimpleCertificateCreator:
321
366
  expected_key = self.certs_dir / f"{name}_key.pem"
322
367
  generated_cert.rename(expected_cert)
323
368
  generated_key.rename(expected_key)
324
- print(f"✅ Client certificate {name} created successfully using mcp_security_framework")
369
+ print(
370
+ f"✅ Client certificate {name} created successfully using mcp_security_framework"
371
+ )
325
372
  return True
326
373
  else:
327
374
  print(f"❌ Generated certificate files not found for {name}")
328
375
  return False
329
376
  else:
330
- print(f"❌ Failed to create client certificate {name}: Invalid certificate pair")
377
+ print(
378
+ f"❌ Failed to create client certificate {name}: Invalid certificate pair"
379
+ )
331
380
  return False
332
381
  except Exception as e:
333
382
  print(f"❌ Error creating client certificate {name} with framework: {e}")
334
383
  return False
335
- def _create_client_certificate_with_openssl(self, name: str, common_name: str) -> bool:
384
+
385
+ def _create_client_certificate_with_openssl(
386
+ self, name: str, common_name: str
387
+ ) -> bool:
336
388
  """Create client certificate using OpenSSL fallback."""
337
389
  cert_path = self.certs_dir / f"{name}_cert.pem"
338
390
  key_path = self.certs_dir / f"{name}_key.pem"
339
391
  # Create client private key
340
- key_cmd = [
341
- "openssl", "genrsa", "-out", str(key_path), "2048"
342
- ]
392
+ key_cmd = ["openssl", "genrsa", "-out", str(key_path), "2048"]
343
393
  if not self.run_command(key_cmd, f"Creating {name} private key"):
344
394
  return False
345
395
  # Create client certificate signing request
346
396
  csr_path = self.certs_dir / f"{name}.csr"
347
397
  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}"
398
+ "openssl",
399
+ "req",
400
+ "-new",
401
+ "-key",
402
+ str(key_path),
403
+ "-out",
404
+ str(csr_path),
405
+ "-subj",
406
+ f"/C=US/ST=Test State/L=Test City/O=Test Organization/CN={common_name}",
352
407
  ]
353
408
  if not self.run_command(csr_cmd, f"Creating {name} CSR"):
354
409
  return False
355
410
  # Create client certificate
356
411
  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"),
412
+ "openssl",
413
+ "x509",
414
+ "-req",
415
+ "-days",
416
+ "730",
417
+ "-in",
418
+ str(csr_path),
419
+ "-CA",
420
+ str(self.certs_dir / "ca_cert.pem"),
421
+ "-CAkey",
422
+ str(self.keys_dir / "ca_key.pem"),
361
423
  "-CAcreateserial",
362
- "-out", str(cert_path)
424
+ "-out",
425
+ str(cert_path),
363
426
  ]
364
427
  success = self.run_command(cert_cmd, f"Creating {name} certificate")
365
428
  # Clean up CSR
366
429
  if csr_path.exists():
367
430
  csr_path.unlink()
368
431
  return success
432
+
369
433
  def create_legacy_certificates(self) -> bool:
370
434
  """Create legacy certificate files for compatibility."""
371
435
  legacy_files = [
372
436
  ("client_admin.crt", "client_admin.key", "admin"),
373
437
  ("admin.crt", "admin.key", "admin"),
374
438
  ("user.crt", "user.key", "user"),
375
- ("readonly.crt", "readonly.key", "readonly")
439
+ ("readonly.crt", "readonly.key", "readonly"),
376
440
  ]
377
441
  success = True
378
442
  for cert_file, key_file, source_name in legacy_files:
@@ -382,13 +446,21 @@ class SimpleCertificateCreator:
382
446
  source_cert = self.certs_dir / f"{source_name}_cert.pem"
383
447
  source_key = self.certs_dir / f"{source_name}_key.pem"
384
448
  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}")
449
+ self.run_command(
450
+ ["cp", str(source_cert), str(cert_path)],
451
+ f"Creating {cert_file}",
452
+ )
453
+ self.run_command(
454
+ ["cp", str(source_key), str(key_path)], f"Creating {key_file}"
455
+ )
387
456
  else:
388
- print(f"⚠️ Source certificate {source_name} not found for {cert_file}")
457
+ print(
458
+ f"⚠️ Source certificate {source_name} not found for {cert_file}"
459
+ )
389
460
  # Don't fail the entire process for missing legacy certificates
390
461
  continue
391
462
  return True # Always return True for legacy certificates
463
+
392
464
  def validate_certificates(self) -> bool:
393
465
  """Validate all created certificates."""
394
466
  print("\n🔍 Validating certificates...")
@@ -399,7 +471,7 @@ class SimpleCertificateCreator:
399
471
  "user_cert.pem",
400
472
  "readonly_cert.pem",
401
473
  "guest_cert.pem",
402
- "proxy_cert.pem"
474
+ "proxy_cert.pem",
403
475
  ]
404
476
  success = True
405
477
  for cert_file in cert_files:
@@ -410,7 +482,7 @@ class SimpleCertificateCreator:
410
482
  ["openssl", "x509", "-in", str(cert_path), "-text", "-noout"],
411
483
  capture_output=True,
412
484
  text=True,
413
- check=True
485
+ check=True,
414
486
  )
415
487
  print(f"✅ {cert_file}: Valid")
416
488
  except subprocess.CalledProcessError:
@@ -419,6 +491,7 @@ class SimpleCertificateCreator:
419
491
  else:
420
492
  print(f"⚠️ {cert_file}: Not found")
421
493
  return success
494
+
422
495
  def create_all(self) -> bool:
423
496
  """Create all certificates."""
424
497
  print("🔐 Creating All Certificates for Security Testing")
@@ -435,14 +508,41 @@ class SimpleCertificateCreator:
435
508
  # 3. Create client certificates
436
509
  print("\n👥 Creating client certificates...")
437
510
  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"]),
511
+ (
512
+ "admin",
513
+ "admin-client",
514
+ ["admin"],
515
+ [
516
+ "read",
517
+ "write",
518
+ "execute",
519
+ "delete",
520
+ "admin",
521
+ "register",
522
+ "unregister",
523
+ "heartbeat",
524
+ "discover",
525
+ ],
526
+ ),
527
+ (
528
+ "user",
529
+ "user-client",
530
+ ["user"],
531
+ ["read", "execute", "register", "unregister", "heartbeat", "discover"],
532
+ ),
440
533
  ("readonly", "readonly-client", ["readonly"], ["read", "discover"]),
441
534
  ("guest", "guest-client", ["guest"], ["read", "discover"]),
442
- ("proxy", "proxy-client", ["proxy"], ["register", "unregister", "heartbeat", "discover"])
535
+ (
536
+ "proxy",
537
+ "proxy-client",
538
+ ["proxy"],
539
+ ["register", "unregister", "heartbeat", "discover"],
540
+ ),
443
541
  ]
444
542
  for name, common_name, roles, permissions in client_certs:
445
- if not self.create_client_certificate(name, common_name, roles, permissions):
543
+ if not self.create_client_certificate(
544
+ name, common_name, roles, permissions
545
+ ):
446
546
  success = False
447
547
  # 4. Create legacy certificates
448
548
  print("\n🔄 Creating legacy certificates...")
@@ -463,6 +563,7 @@ class SimpleCertificateCreator:
463
563
  except OSError:
464
564
  # On Windows, symlink might require admin privileges, copy instead
465
565
  import shutil
566
+
466
567
  shutil.copy2(ca_cert, expected_ca_cert)
467
568
  print(f"✅ Created CA certificate copy: {expected_ca_cert}")
468
569
 
@@ -471,6 +572,7 @@ class SimpleCertificateCreator:
471
572
  expected_server_cert = self.certs_dir / "localhost_server.crt"
472
573
  if server_cert.exists() and not expected_server_cert.exists():
473
574
  import shutil
575
+
474
576
  shutil.copy2(server_cert, expected_server_cert)
475
577
  print(f"✅ Created server certificate copy: {expected_server_cert}")
476
578
 
@@ -481,6 +583,7 @@ class SimpleCertificateCreator:
481
583
  if server_key_certs.exists():
482
584
  # Server key is in certs directory, move it to keys directory
483
585
  import shutil
586
+
484
587
  shutil.move(str(server_key_certs), str(server_key_keys))
485
588
  print(f"✅ Moved server key to keys directory: {server_key_keys}")
486
589
 
@@ -488,6 +591,7 @@ class SimpleCertificateCreator:
488
591
  expected_server_key = self.keys_dir / "localhost_server.key"
489
592
  if not expected_server_key.exists():
490
593
  import shutil
594
+
491
595
  shutil.copy2(server_key_keys, expected_server_key)
492
596
  print(f"✅ Created server key copy: {expected_server_key}")
493
597
 
@@ -500,20 +604,28 @@ class SimpleCertificateCreator:
500
604
  print(f"📁 Certificates directory: {self.certs_dir}")
501
605
  print(f"🔑 Keys directory: {self.keys_dir}")
502
606
  print("\n📋 Created certificates:")
503
- cert_files = list(self.certs_dir.glob("*.pem")) + list(self.certs_dir.glob("*.crt"))
607
+ cert_files = list(self.certs_dir.glob("*.pem")) + list(
608
+ self.certs_dir.glob("*.crt")
609
+ )
504
610
  for cert_file in sorted(cert_files):
505
611
  print(f" - {cert_file.name}")
506
- key_files = list(self.keys_dir.glob("*.pem")) + list(self.keys_dir.glob("*.key"))
612
+ key_files = list(self.keys_dir.glob("*.pem")) + list(
613
+ self.keys_dir.glob("*.key")
614
+ )
507
615
  for key_file in sorted(key_files):
508
616
  print(f" - {key_file.name}")
509
617
  else:
510
618
  print("❌ Some certificates failed to create")
511
619
  print("Check the error messages above")
512
620
  return success
621
+
622
+
513
623
  def main():
514
624
  """Main function."""
515
625
  parser = argparse.ArgumentParser(description="Create certificates for testing")
516
- parser.add_argument("--certs-dir", help="Directory for certificates (default: ./certs)")
626
+ parser.add_argument(
627
+ "--certs-dir", help="Directory for certificates (default: ./certs)"
628
+ )
517
629
  parser.add_argument("--keys-dir", help="Directory for keys (default: ./keys)")
518
630
  args = parser.parse_args()
519
631
 
@@ -533,10 +645,7 @@ def main():
533
645
  certs_dir = args.certs_dir
534
646
  keys_dir = args.keys_dir
535
647
 
536
- creator = SimpleCertificateCreator(
537
- certs_dir=certs_dir,
538
- keys_dir=keys_dir
539
- )
648
+ creator = SimpleCertificateCreator(certs_dir=certs_dir, keys_dir=keys_dir)
540
649
  try:
541
650
  success = creator.create_all()
542
651
  sys.exit(0 if success else 1)
@@ -546,5 +655,7 @@ def main():
546
655
  except Exception as e:
547
656
  print(f"\n❌ Certificate creation failed: {e}")
548
657
  sys.exit(1)
658
+
659
+
549
660
  if __name__ == "__main__":
550
661
  main()