mcp-proxy-adapter 6.6.1__py3-none-any.whl → 6.6.4__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 (27) hide show
  1. mcp_proxy_adapter/api/app.py +61 -55
  2. mcp_proxy_adapter/commands/command_registry.py +27 -13
  3. mcp_proxy_adapter/config.py +1 -8
  4. mcp_proxy_adapter/core/proxy_registration.py +80 -7
  5. mcp_proxy_adapter/core/server_adapter.py +1 -1
  6. mcp_proxy_adapter/examples/check_config.py +1 -1
  7. mcp_proxy_adapter/examples/config_builder.py +13 -19
  8. mcp_proxy_adapter/examples/{generate_certificates_bugfix.py → generate_certificates.py} +11 -0
  9. mcp_proxy_adapter/examples/generate_config.py +3 -3
  10. mcp_proxy_adapter/examples/run_full_test_suite.py +3 -3
  11. mcp_proxy_adapter/examples/security_test_client.py +6 -5
  12. mcp_proxy_adapter/examples/test_chk_hostname_automated.py +7 -10
  13. mcp_proxy_adapter/examples/test_framework_complete.py +269 -0
  14. mcp_proxy_adapter/examples/test_mcp_server.py +188 -0
  15. mcp_proxy_adapter/main.py +19 -18
  16. mcp_proxy_adapter/version.py +1 -1
  17. {mcp_proxy_adapter-6.6.1.dist-info → mcp_proxy_adapter-6.6.4.dist-info}/METADATA +1 -1
  18. {mcp_proxy_adapter-6.6.1.dist-info → mcp_proxy_adapter-6.6.4.dist-info}/RECORD +21 -25
  19. mcp_proxy_adapter/examples/config_builder_simple.py +0 -271
  20. mcp_proxy_adapter/examples/generate_all_certificates.py +0 -487
  21. mcp_proxy_adapter/examples/generate_certificates_cli.py +0 -406
  22. mcp_proxy_adapter/examples/generate_certificates_fixed.py +0 -313
  23. mcp_proxy_adapter/examples/generate_certificates_framework.py +0 -366
  24. mcp_proxy_adapter/examples/generate_certificates_openssl.py +0 -391
  25. {mcp_proxy_adapter-6.6.1.dist-info → mcp_proxy_adapter-6.6.4.dist-info}/WHEEL +0 -0
  26. {mcp_proxy_adapter-6.6.1.dist-info → mcp_proxy_adapter-6.6.4.dist-info}/entry_points.txt +0 -0
  27. {mcp_proxy_adapter-6.6.1.dist-info → mcp_proxy_adapter-6.6.4.dist-info}/top_level.txt +0 -0
@@ -1,487 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Generate All Certificates for Security Testing
4
- This script generates all necessary certificates for comprehensive security testing:
5
- - Root CA certificate and key
6
- - Server certificates for HTTPS and mTLS
7
- - Client certificates for different roles (admin, user, readonly, etc.)
8
- - Test certificates for negative scenarios
9
- Author: Vasiliy Zdanovskiy
10
- email: vasilyvz@gmail.com
11
- """
12
- import json
13
- import os
14
- import subprocess
15
- import sys
16
- from pathlib import Path
17
- from typing import Dict, List, Optional
18
-
19
-
20
- class CertificateGenerator:
21
- """Generate all certificates for security testing."""
22
-
23
- def __init__(self):
24
- self.project_root = Path(__file__).parent.parent.parent
25
- self.certs_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "certs"
26
- self.keys_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "keys"
27
- # Create directories if they don't exist
28
- self.certs_dir.mkdir(parents=True, exist_ok=True)
29
- self.keys_dir.mkdir(parents=True, exist_ok=True)
30
- # Certificate configuration
31
- self.ca_config = {
32
- "common_name": "MCP Proxy Adapter Test CA",
33
- "organization": "Test Organization",
34
- "country": "US",
35
- "state": "Test State",
36
- "city": "Test City",
37
- "validity_years": 10,
38
- }
39
- self.server_config = {
40
- "common_name": "mcp-proxy-adapter-test.local",
41
- "organization": "Test Organization",
42
- "country": "US",
43
- "state": "Test State",
44
- "city": "Test City",
45
- "validity_years": 2,
46
- "san": ["localhost", "127.0.0.1", "mcp-proxy-adapter-test.local"],
47
- }
48
- # Client certificates configuration
49
- self.client_certs = {
50
- "admin": {
51
- "common_name": "admin-client",
52
- "organization": "Test Organization",
53
- "roles": ["admin"],
54
- "permissions": ["*"],
55
- },
56
- "user": {
57
- "common_name": "user-client",
58
- "organization": "Test Organization",
59
- "roles": ["user"],
60
- "permissions": ["read", "write"],
61
- },
62
- "readonly": {
63
- "common_name": "readonly-client",
64
- "organization": "Test Organization",
65
- "roles": ["readonly"],
66
- "permissions": ["read"],
67
- },
68
- "guest": {
69
- "common_name": "guest-client",
70
- "organization": "Test Organization",
71
- "roles": ["guest"],
72
- "permissions": ["read"],
73
- },
74
- "proxy": {
75
- "common_name": "proxy-client",
76
- "organization": "Test Organization",
77
- "roles": ["proxy"],
78
- "permissions": ["register", "discover"],
79
- },
80
- }
81
- # Negative test certificates
82
- self.negative_certs = {
83
- "expired": {
84
- "common_name": "expired-client",
85
- "organization": "Test Organization",
86
- "validity_days": 1, # Will expire quickly
87
- },
88
- "wrong_org": {
89
- "common_name": "wrong-org-client",
90
- "organization": "Wrong Organization",
91
- "roles": ["user"],
92
- },
93
- "no_roles": {
94
- "common_name": "no-roles-client",
95
- "organization": "Test Organization",
96
- "roles": [],
97
- },
98
- "invalid_roles": {
99
- "common_name": "invalid-roles-client",
100
- "organization": "Test Organization",
101
- "roles": ["invalid_role"],
102
- },
103
- }
104
-
105
- def run_command(self, cmd: List[str], description: str) -> bool:
106
- """Run a command and handle errors."""
107
- try:
108
- print(f"🔧 {description}...")
109
- result = subprocess.run(
110
- cmd, cwd=self.project_root, capture_output=True, text=True, check=True
111
- )
112
- print(f"✅ {description} completed successfully")
113
- return True
114
- except subprocess.CalledProcessError as e:
115
- print(f"❌ {description} failed:")
116
- print(f" Command: {' '.join(cmd)}")
117
- print(f" Error: {e.stderr}")
118
- return False
119
- except Exception as e:
120
- print(f"❌ {description} failed: {e}")
121
- return False
122
-
123
- def create_ca_certificate(self) -> bool:
124
- """Create Root CA certificate and key."""
125
- ca_cert_path = self.certs_dir / "ca_cert.pem"
126
- ca_key_path = self.keys_dir / "ca_key.pem"
127
- if ca_cert_path.exists() and ca_key_path.exists():
128
- print(f"ℹ️ CA certificate already exists: {ca_cert_path}")
129
- return True
130
- cmd = [
131
- sys.executable,
132
- "-m",
133
- "mcp_security_framework.cli.cert_cli",
134
- "create-ca",
135
- "-cn",
136
- self.ca_config["common_name"],
137
- "-o",
138
- self.ca_config["organization"],
139
- "-c",
140
- self.ca_config["country"],
141
- "-s",
142
- self.ca_config["state"],
143
- "-l",
144
- self.ca_config["city"],
145
- "-y",
146
- str(self.ca_config["validity_years"]),
147
- ]
148
- success = self.run_command(cmd, "Creating Root CA certificate")
149
- if success:
150
- # Move files to correct locations
151
- default_ca_cert = (
152
- Path("./certs")
153
- / f"{self.ca_config['common_name'].lower().replace(' ', '_')}_ca.crt"
154
- )
155
- default_ca_key = (
156
- Path("./keys")
157
- / f"{self.ca_config['common_name'].lower().replace(' ', '_')}_ca.key"
158
- )
159
- if default_ca_cert.exists():
160
- self.run_command(
161
- ["mv", str(default_ca_cert), str(ca_cert_path)],
162
- "Moving CA certificate",
163
- )
164
- if default_ca_key.exists():
165
- self.run_command(
166
- ["mv", str(default_ca_key), str(ca_key_path)], "Moving CA key"
167
- )
168
- return success
169
-
170
- def create_server_certificate(self) -> bool:
171
- """Create server certificate for HTTPS and mTLS."""
172
- server_cert_path = self.certs_dir / "server_cert.pem"
173
- server_key_path = self.certs_dir / "server_key.pem"
174
- if server_cert_path.exists() and server_key_path.exists():
175
- print(f"ℹ️ Server certificate already exists: {server_cert_path}")
176
- return True
177
- # Create server certificate
178
- cmd = [
179
- sys.executable,
180
- "-m",
181
- "mcp_security_framework.cli.cert_cli",
182
- "create-server",
183
- "-cn",
184
- self.server_config["common_name"],
185
- "-o",
186
- self.server_config["organization"],
187
- "-c",
188
- self.server_config["country"],
189
- "-s",
190
- self.server_config["state"],
191
- "-l",
192
- self.server_config["city"],
193
- "-d",
194
- str(self.server_config["validity_years"] * 365), # Convert years to days
195
- ]
196
- # Add SAN if supported
197
- if self.server_config["san"]:
198
- for san in self.server_config["san"]:
199
- cmd.extend(["--san", san])
200
- success = self.run_command(cmd, "Creating server certificate")
201
- if success:
202
- # Move files to correct locations
203
- default_server_cert = (
204
- Path("./certs")
205
- / f"{self.server_config['common_name'].lower().replace('.', '_')}_server.crt"
206
- )
207
- default_server_key = (
208
- Path("./keys")
209
- / f"{self.server_config['common_name'].lower().replace('.', '_')}_server.key"
210
- )
211
- if default_server_cert.exists():
212
- self.run_command(
213
- ["mv", str(default_server_cert), str(server_cert_path)],
214
- "Moving server certificate",
215
- )
216
- if default_server_key.exists():
217
- self.run_command(
218
- ["mv", str(default_server_key), str(server_key_path)],
219
- "Moving server key",
220
- )
221
- return success
222
-
223
- def create_client_certificate(self, name: str, config: Dict) -> bool:
224
- """Create client certificate with specific configuration."""
225
- cert_path = self.certs_dir / f"{name}_cert.pem"
226
- key_path = self.certs_dir / f"{name}_key.pem"
227
- if cert_path.exists() and key_path.exists():
228
- print(f"ℹ️ Client certificate {name} already exists: {cert_path}")
229
- return True
230
- cmd = [
231
- sys.executable,
232
- "-m",
233
- "mcp_security_framework.cli.cert_cli",
234
- "create-client",
235
- "-cn",
236
- config["common_name"],
237
- "-o",
238
- config["organization"],
239
- "-c",
240
- self.ca_config["country"],
241
- "-s",
242
- self.ca_config["state"],
243
- "-l",
244
- self.ca_config["city"],
245
- "-d",
246
- "730", # 2 years in days
247
- ]
248
- # Add roles if specified
249
- if "roles" in config and config["roles"]:
250
- for role in config["roles"]:
251
- cmd.extend(["--roles", role])
252
- # Add permissions if specified
253
- if "permissions" in config and config["permissions"]:
254
- for permission in config["permissions"]:
255
- cmd.extend(["--permissions", permission])
256
- # Add custom validity for negative tests
257
- if "validity_days" in config:
258
- cmd[cmd.index("-d") + 1] = str(config["validity_days"])
259
- success = self.run_command(cmd, f"Creating client certificate: {name}")
260
- if success:
261
- # Move files to correct locations
262
- default_client_cert = (
263
- Path("./certs")
264
- / f"{config['common_name'].lower().replace('-', '_')}_client.crt"
265
- )
266
- default_client_key = (
267
- Path("./keys")
268
- / f"{config['common_name'].lower().replace('-', '_')}_client.key"
269
- )
270
- if default_client_cert.exists():
271
- self.run_command(
272
- ["mv", str(default_client_cert), str(cert_path)],
273
- f"Moving {name} certificate",
274
- )
275
- if default_client_key.exists():
276
- self.run_command(
277
- ["mv", str(default_client_key), str(key_path)], f"Moving {name} key"
278
- )
279
- return success
280
-
281
- def create_legacy_certificates(self) -> bool:
282
- """Create legacy certificate files for compatibility."""
283
- legacy_files = [
284
- ("client.crt", "client.key"),
285
- ("client_admin.crt", "client_admin.key"),
286
- ("admin.crt", "admin.key"),
287
- ("user.crt", "user.key"),
288
- ("readonly.crt", "readonly.key"),
289
- ]
290
- success = True
291
- for cert_file, key_file in legacy_files:
292
- cert_path = self.certs_dir / cert_file
293
- key_path = self.certs_dir / key_file
294
- if not cert_path.exists() or not key_path.exists():
295
- # Copy from existing certificates
296
- if (
297
- cert_file == "client.crt"
298
- and (self.certs_dir / "user_cert.pem").exists()
299
- ):
300
- self.run_command(
301
- ["cp", str(self.certs_dir / "user_cert.pem"), str(cert_path)],
302
- f"Creating {cert_file}",
303
- )
304
- self.run_command(
305
- ["cp", str(self.certs_dir / "user_key.pem"), str(key_path)],
306
- f"Creating {key_file}",
307
- )
308
- elif (
309
- cert_file == "client_admin.crt"
310
- and (self.certs_dir / "admin_cert.pem").exists()
311
- ):
312
- self.run_command(
313
- ["cp", str(self.certs_dir / "admin_cert.pem"), str(cert_path)],
314
- f"Creating {cert_file}",
315
- )
316
- self.run_command(
317
- ["cp", str(self.certs_dir / "admin_key.pem"), str(key_path)],
318
- f"Creating {key_file}",
319
- )
320
- elif (
321
- cert_file == "admin.crt"
322
- and (self.certs_dir / "admin_cert.pem").exists()
323
- ):
324
- self.run_command(
325
- ["cp", str(self.certs_dir / "admin_cert.pem"), str(cert_path)],
326
- f"Creating {cert_file}",
327
- )
328
- self.run_command(
329
- ["cp", str(self.certs_dir / "admin_key.pem"), str(key_path)],
330
- f"Creating {key_file}",
331
- )
332
- elif (
333
- cert_file == "user.crt"
334
- and (self.certs_dir / "user_cert.pem").exists()
335
- ):
336
- self.run_command(
337
- ["cp", str(self.certs_dir / "user_cert.pem"), str(cert_path)],
338
- f"Creating {cert_file}",
339
- )
340
- self.run_command(
341
- ["cp", str(self.certs_dir / "user_key.pem"), str(key_path)],
342
- f"Creating {key_file}",
343
- )
344
- elif (
345
- cert_file == "readonly.crt"
346
- and (self.certs_dir / "readonly_cert.pem").exists()
347
- ):
348
- self.run_command(
349
- [
350
- "cp",
351
- str(self.certs_dir / "readonly_cert.pem"),
352
- str(cert_path),
353
- ],
354
- f"Creating {cert_file}",
355
- )
356
- self.run_command(
357
- ["cp", str(self.certs_dir / "readonly_key.pem"), str(key_path)],
358
- f"Creating {key_file}",
359
- )
360
- return success
361
-
362
- def create_certificate_config(self) -> bool:
363
- """Create certificate configuration file."""
364
- config_path = self.certs_dir / "cert_config.json"
365
- config = {
366
- "ca_cert_path": str(self.certs_dir / "ca_cert.pem"),
367
- "ca_key_path": str(self.keys_dir / "ca_key.pem"),
368
- "cert_storage_path": str(self.certs_dir),
369
- "key_storage_path": str(self.keys_dir),
370
- "default_validity_days": 365,
371
- "key_size": 2048,
372
- "hash_algorithm": "sha256",
373
- }
374
- try:
375
- with open(config_path, "w") as f:
376
- json.dump(config, f, indent=2)
377
- print(f"✅ Created certificate config: {config_path}")
378
- return True
379
- except Exception as e:
380
- print(f"❌ Failed to create certificate config: {e}")
381
- return False
382
-
383
- def validate_certificates(self) -> bool:
384
- """Validate all created certificates."""
385
- print("\n🔍 Validating certificates...")
386
- cert_files = [
387
- "ca_cert.pem",
388
- "server_cert.pem",
389
- "admin_cert.pem",
390
- "user_cert.pem",
391
- "readonly_cert.pem",
392
- "guest_cert.pem",
393
- "proxy_cert.pem",
394
- ]
395
- success = True
396
- for cert_file in cert_files:
397
- cert_path = self.certs_dir / cert_file
398
- if cert_path.exists():
399
- try:
400
- result = subprocess.run(
401
- ["openssl", "x509", "-in", str(cert_path), "-text", "-noout"],
402
- capture_output=True,
403
- text=True,
404
- check=True,
405
- )
406
- print(f"✅ {cert_file}: Valid")
407
- except subprocess.CalledProcessError:
408
- print(f"❌ {cert_file}: Invalid")
409
- success = False
410
- else:
411
- print(f"⚠️ {cert_file}: Not found")
412
- return success
413
-
414
- def generate_all(self) -> bool:
415
- """Generate all certificates."""
416
- print("🔐 Generating All Certificates for Security Testing")
417
- print("=" * 60)
418
- success = True
419
- # 1. Create CA certificate
420
- if not self.create_ca_certificate():
421
- success = False
422
- print("❌ Cannot continue without CA certificate")
423
- return False
424
- # 2. Create server certificate
425
- if not self.create_server_certificate():
426
- success = False
427
- # 3. Create client certificates for different roles
428
- print("\n👥 Creating client certificates...")
429
- for name, config in self.client_certs.items():
430
- if not self.create_client_certificate(name, config):
431
- success = False
432
- # 4. Create negative test certificates
433
- print("\n🚫 Creating negative test certificates...")
434
- for name, config in self.negative_certs.items():
435
- if not self.create_client_certificate(name, config):
436
- success = False
437
- # 5. Create legacy certificates for compatibility
438
- print("\n🔄 Creating legacy certificates...")
439
- if not self.create_legacy_certificates():
440
- success = False
441
- # 6. Create certificate configuration
442
- if not self.create_certificate_config():
443
- success = False
444
- # 7. Validate certificates
445
- if not self.validate_certificates():
446
- success = False
447
- # Print summary
448
- print("\n" + "=" * 60)
449
- print("📊 CERTIFICATE GENERATION SUMMARY")
450
- print("=" * 60)
451
- if success:
452
- print("✅ All certificates generated successfully!")
453
- print(f"📁 Certificates directory: {self.certs_dir}")
454
- print(f"🔑 Keys directory: {self.keys_dir}")
455
- print("\n📋 Generated certificates:")
456
- cert_files = list(self.certs_dir.glob("*.pem")) + list(
457
- self.certs_dir.glob("*.crt")
458
- )
459
- for cert_file in sorted(cert_files):
460
- print(f" - {cert_file.name}")
461
- key_files = list(self.keys_dir.glob("*.pem")) + list(
462
- self.keys_dir.glob("*.key")
463
- )
464
- for key_file in sorted(key_files):
465
- print(f" - {key_file.name}")
466
- else:
467
- print("❌ Some certificates failed to generate")
468
- print("Check the error messages above")
469
- return success
470
-
471
-
472
- def main():
473
- """Main function."""
474
- generator = CertificateGenerator()
475
- try:
476
- success = generator.generate_all()
477
- sys.exit(0 if success else 1)
478
- except KeyboardInterrupt:
479
- print("\n⚠️ Certificate generation interrupted by user")
480
- sys.exit(1)
481
- except Exception as e:
482
- print(f"\n❌ Certificate generation failed: {e}")
483
- sys.exit(1)
484
-
485
-
486
- if __name__ == "__main__":
487
- main()