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.
- mcp_proxy_adapter/api/app.py +0 -3
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +10 -10
- mcp_proxy_adapter/commands/health_command.py +1 -1
- mcp_proxy_adapter/core/protocol_manager.py +9 -9
- mcp_proxy_adapter/examples/create_certificates_simple.py +7 -17
- mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
- mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
- mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
- mcp_proxy_adapter/examples/generate_test_configs.py +70 -33
- mcp_proxy_adapter/examples/run_full_test_suite.py +302 -109
- mcp_proxy_adapter/examples/run_security_tests.py +14 -5
- mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
- mcp_proxy_adapter/main.py +0 -2
- {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.25.dist-info}/METADATA +1 -1
- {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.25.dist-info}/RECORD +31 -15
- {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.25.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.25.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.2.24.dist-info → mcp_proxy_adapter-6.2.25.dist-info}/licenses/LICENSE +0 -0
- {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()
|