mcp-proxy-adapter 6.1.1__py3-none-any.whl → 6.2.1__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/__main__.py +27 -7
- mcp_proxy_adapter/api/app.py +18 -7
- mcp_proxy_adapter/commands/ssl_setup_command.py +234 -351
- mcp_proxy_adapter/core/app_factory.py +87 -3
- mcp_proxy_adapter/core/app_runner.py +272 -0
- mcp_proxy_adapter/core/certificate_utils.py +291 -73
- mcp_proxy_adapter/core/client.py +574 -0
- mcp_proxy_adapter/core/client_manager.py +284 -0
- mcp_proxy_adapter/core/server_adapter.py +17 -80
- mcp_proxy_adapter/core/server_engine.py +5 -99
- mcp_proxy_adapter/core/ssl_utils.py +13 -12
- mcp_proxy_adapter/core/transport_manager.py +5 -5
- mcp_proxy_adapter/examples/__init__.py +16 -0
- mcp_proxy_adapter/examples/basic_framework/__init__.py +7 -0
- mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/main.py +21 -40
- mcp_proxy_adapter/examples/commands/__init__.py +5 -1
- mcp_proxy_adapter/examples/create_certificates_simple.py +260 -75
- mcp_proxy_adapter/examples/debug_request_state.py +4 -36
- mcp_proxy_adapter/examples/debug_role_chain.py +2 -49
- mcp_proxy_adapter/examples/demo_client.py +0 -66
- mcp_proxy_adapter/examples/full_application/__init__.py +11 -0
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +0 -19
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +0 -16
- mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +0 -22
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +0 -24
- mcp_proxy_adapter/examples/full_application/main.py +65 -44
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
- mcp_proxy_adapter/examples/generate_all_certificates.py +0 -67
- mcp_proxy_adapter/examples/generate_certificates.py +0 -15
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
- mcp_proxy_adapter/examples/generate_test_configs.py +204 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +3 -70
- mcp_proxy_adapter/examples/run_example.py +1 -23
- mcp_proxy_adapter/examples/run_security_tests.py +2 -60
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +0 -53
- mcp_proxy_adapter/examples/security_test_client.py +18 -123
- mcp_proxy_adapter/examples/setup_test_environment.py +179 -0
- mcp_proxy_adapter/examples/test_config.py +148 -0
- mcp_proxy_adapter/examples/test_config_generator.py +1 -25
- mcp_proxy_adapter/examples/test_examples.py +4 -67
- mcp_proxy_adapter/examples/universal_client.py +154 -162
- mcp_proxy_adapter/main.py +51 -161
- mcp_proxy_adapter/version.py +1 -1
- mcp_proxy_adapter-6.2.1.dist-info/METADATA +676 -0
- mcp_proxy_adapter-6.2.1.dist-info/RECORD +119 -0
- mcp_proxy_adapter/docs/EN/TROUBLESHOOTING.md +0 -285
- mcp_proxy_adapter/docs/RU/TROUBLESHOOTING.md +0 -285
- mcp_proxy_adapter/examples/README.md +0 -257
- mcp_proxy_adapter/examples/README_EN.md +0 -258
- mcp_proxy_adapter/examples/SECURITY_TESTING.md +0 -455
- mcp_proxy_adapter/examples/basic_framework/configs/http_auth.json +0 -37
- mcp_proxy_adapter/examples/basic_framework/configs/http_simple.json +0 -23
- mcp_proxy_adapter/examples/basic_framework/configs/https_auth.json +0 -43
- mcp_proxy_adapter/examples/basic_framework/configs/https_no_protocol_middleware.json +0 -36
- mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +0 -29
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_protocol_middleware.json +0 -34
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +0 -39
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_simple.json +0 -35
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_with_roles.json +0 -45
- mcp_proxy_adapter/examples/basic_framework/roles.json +0 -21
- mcp_proxy_adapter/examples/cert_config.json +0 -9
- mcp_proxy_adapter/examples/certs/admin.crt +0 -32
- mcp_proxy_adapter/examples/certs/admin.key +0 -52
- mcp_proxy_adapter/examples/certs/admin_cert.pem +0 -21
- mcp_proxy_adapter/examples/certs/admin_key.pem +0 -28
- mcp_proxy_adapter/examples/certs/ca_cert.pem +0 -23
- mcp_proxy_adapter/examples/certs/ca_cert.srl +0 -1
- mcp_proxy_adapter/examples/certs/ca_key.pem +0 -28
- mcp_proxy_adapter/examples/certs/cert_config.json +0 -9
- mcp_proxy_adapter/examples/certs/client.crt +0 -32
- mcp_proxy_adapter/examples/certs/client.key +0 -52
- mcp_proxy_adapter/examples/certs/client_admin.crt +0 -32
- mcp_proxy_adapter/examples/certs/client_admin.key +0 -52
- mcp_proxy_adapter/examples/certs/client_user.crt +0 -32
- mcp_proxy_adapter/examples/certs/client_user.key +0 -52
- mcp_proxy_adapter/examples/certs/guest_cert.pem +0 -21
- mcp_proxy_adapter/examples/certs/guest_key.pem +0 -28
- mcp_proxy_adapter/examples/certs/mcp_proxy_adapter_ca_ca.crt +0 -23
- mcp_proxy_adapter/examples/certs/proxy_cert.pem +0 -21
- mcp_proxy_adapter/examples/certs/proxy_key.pem +0 -28
- mcp_proxy_adapter/examples/certs/readonly.crt +0 -32
- mcp_proxy_adapter/examples/certs/readonly.key +0 -52
- mcp_proxy_adapter/examples/certs/readonly_cert.pem +0 -21
- mcp_proxy_adapter/examples/certs/readonly_key.pem +0 -28
- mcp_proxy_adapter/examples/certs/server.crt +0 -32
- mcp_proxy_adapter/examples/certs/server.key +0 -52
- mcp_proxy_adapter/examples/certs/server_cert.pem +0 -32
- mcp_proxy_adapter/examples/certs/server_key.pem +0 -52
- mcp_proxy_adapter/examples/certs/test_ca_ca.crt +0 -20
- mcp_proxy_adapter/examples/certs/user.crt +0 -32
- mcp_proxy_adapter/examples/certs/user.key +0 -52
- mcp_proxy_adapter/examples/certs/user_cert.pem +0 -21
- mcp_proxy_adapter/examples/certs/user_key.pem +0 -28
- mcp_proxy_adapter/examples/client_configs/api_key_client.json +0 -13
- mcp_proxy_adapter/examples/client_configs/basic_auth_client.json +0 -13
- mcp_proxy_adapter/examples/client_configs/certificate_client.json +0 -22
- mcp_proxy_adapter/examples/client_configs/jwt_client.json +0 -15
- mcp_proxy_adapter/examples/client_configs/no_auth_client.json +0 -9
- mcp_proxy_adapter/examples/full_application/configs/http_auth.json +0 -37
- mcp_proxy_adapter/examples/full_application/configs/http_simple.json +0 -23
- mcp_proxy_adapter/examples/full_application/configs/https_auth.json +0 -39
- mcp_proxy_adapter/examples/full_application/configs/https_simple.json +0 -25
- mcp_proxy_adapter/examples/full_application/configs/mtls_no_roles.json +0 -39
- mcp_proxy_adapter/examples/full_application/configs/mtls_with_roles.json +0 -45
- mcp_proxy_adapter/examples/full_application/roles.json +0 -21
- mcp_proxy_adapter/examples/keys/ca_key.pem +0 -28
- mcp_proxy_adapter/examples/keys/mcp_proxy_adapter_ca_ca.key +0 -28
- mcp_proxy_adapter/examples/keys/test_ca_ca.key +0 -28
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log +0 -220
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.1 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.2 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.3 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.4 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.5 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log +0 -220
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.1 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.2 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.3 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.4 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.5 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log +0 -2
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.1 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.2 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.3 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.4 +0 -1
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.5 +0 -1
- mcp_proxy_adapter/examples/roles.json +0 -38
- mcp_proxy_adapter/examples/server_configs/config_basic_http.json +0 -204
- mcp_proxy_adapter/examples/server_configs/config_http_token.json +0 -238
- mcp_proxy_adapter/examples/server_configs/config_https.json +0 -215
- mcp_proxy_adapter/examples/server_configs/config_https_token.json +0 -231
- mcp_proxy_adapter/examples/server_configs/config_mtls.json +0 -215
- mcp_proxy_adapter/examples/server_configs/config_proxy_registration.json +0 -250
- mcp_proxy_adapter/examples/server_configs/config_simple.json +0 -46
- mcp_proxy_adapter/examples/server_configs/roles.json +0 -38
- mcp_proxy_adapter/utils/config_generator.py +0 -727
- mcp_proxy_adapter-6.1.1.dist-info/METADATA +0 -205
- mcp_proxy_adapter-6.1.1.dist-info/RECORD +0 -197
- mcp_proxy_adapter-6.1.1.dist-info/entry_points.txt +0 -2
- mcp_proxy_adapter-6.1.1.dist-info/licenses/LICENSE +0 -21
- {mcp_proxy_adapter-6.1.1.dist-info → mcp_proxy_adapter-6.2.1.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.1.1.dist-info → mcp_proxy_adapter-6.2.1.dist-info}/top_level.txt +0 -0
@@ -1,63 +1,44 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
"""
|
3
|
-
Basic Framework Example
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
Basic Framework Example
|
4
|
+
This example demonstrates the basic usage of the MCP Proxy Adapter framework
|
5
|
+
with minimal configuration and built-in commands.
|
7
6
|
Author: Vasiliy Zdanovskiy
|
8
7
|
email: vasilyvz@gmail.com
|
9
8
|
"""
|
10
|
-
|
11
9
|
import sys
|
12
10
|
import argparse
|
13
11
|
from pathlib import Path
|
14
|
-
|
15
12
|
# Add the framework to the path
|
16
13
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
17
|
-
|
18
|
-
from mcp_proxy_adapter.api.app import create_app
|
19
|
-
from mcp_proxy_adapter.config import Config
|
20
|
-
|
21
|
-
|
14
|
+
from mcp_proxy_adapter.core.app_factory import create_and_run_server
|
22
15
|
def main():
|
23
16
|
"""Main entry point for the basic framework example."""
|
24
17
|
parser = argparse.ArgumentParser(description="Basic Framework Example")
|
25
18
|
parser.add_argument("--config", "-c", required=True, help="Path to configuration file")
|
26
|
-
parser.add_argument("--host",
|
27
|
-
parser.add_argument("--port", type=int, help="Server port
|
19
|
+
parser.add_argument("--host", help="Server host")
|
20
|
+
parser.add_argument("--port", type=int, help="Server port")
|
28
21
|
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
|
29
|
-
|
30
22
|
args = parser.parse_args()
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
# Override port if specified
|
23
|
+
# Override configuration if specified
|
24
|
+
config_overrides = {}
|
25
|
+
if args.host:
|
26
|
+
config_overrides["host"] = args.host
|
36
27
|
if args.port:
|
37
|
-
|
38
|
-
|
39
|
-
# Override debug if specified
|
28
|
+
config_overrides["port"] = args.port
|
40
29
|
if args.debug:
|
41
|
-
|
42
|
-
|
43
|
-
# Create application
|
44
|
-
app = create_app(app_config=config)
|
45
|
-
|
46
|
-
# Get server configuration
|
47
|
-
host = config.get("server.host", "0.0.0.0")
|
48
|
-
port = config.get("server.port", 8000)
|
49
|
-
debug = config.get("server.debug", False)
|
50
|
-
|
30
|
+
config_overrides["debug"] = True
|
51
31
|
print(f"🚀 Starting Basic Framework Example")
|
52
32
|
print(f"📋 Configuration: {args.config}")
|
53
|
-
print(f"🌐 Server: {host}:{port}")
|
54
|
-
print(f"🔧 Debug: {debug}")
|
55
33
|
print("=" * 50)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
34
|
+
# Use the factory method to create and run the server
|
35
|
+
create_and_run_server(
|
36
|
+
config_path=args.config,
|
37
|
+
title="Basic Framework Example",
|
38
|
+
description="Basic MCP Proxy Adapter with minimal configuration",
|
39
|
+
version="1.0.0",
|
40
|
+
host=config_overrides.get("host", "0.0.0.0"),
|
41
|
+
log_level="debug" if config_overrides.get("debug", False) else "info"
|
42
|
+
)
|
62
43
|
if __name__ == "__main__":
|
63
44
|
main()
|
@@ -1,38 +1,50 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
"""
|
3
3
|
Simple Certificate Creation Script
|
4
|
-
|
5
|
-
This script creates basic certificates for testing using OpenSSL directly.
|
6
|
-
|
4
|
+
This script creates basic certificates for testing using mcp_security_framework.
|
7
5
|
Author: Vasiliy Zdanovskiy
|
8
6
|
email: vasilyvz@gmail.com
|
9
7
|
"""
|
10
|
-
|
11
8
|
import os
|
12
9
|
import subprocess
|
13
10
|
import sys
|
11
|
+
import argparse
|
14
12
|
from pathlib import Path
|
15
|
-
|
16
|
-
|
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")
|
17
22
|
class SimpleCertificateCreator:
|
18
23
|
"""Create certificates using OpenSSL directly."""
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
def __init__(self, certs_dir: str = None, keys_dir: str = None):
|
25
|
+
if certs_dir:
|
26
|
+
self.certs_dir = Path(certs_dir).resolve()
|
27
|
+
else:
|
28
|
+
self.project_root = Path(__file__).parent.parent.parent
|
29
|
+
self.certs_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "certs"
|
30
|
+
if keys_dir:
|
31
|
+
self.keys_dir = Path(keys_dir).resolve()
|
32
|
+
else:
|
33
|
+
if not certs_dir:
|
34
|
+
self.project_root = Path(__file__).parent.parent.parent
|
35
|
+
self.keys_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "keys"
|
25
36
|
# Create directories
|
26
37
|
self.certs_dir.mkdir(parents=True, exist_ok=True)
|
27
38
|
self.keys_dir.mkdir(parents=True, exist_ok=True)
|
28
|
-
|
39
|
+
print(f"🔧 Using certificates directory: {self.certs_dir}")
|
40
|
+
print(f"🔧 Using keys directory: {self.keys_dir}")
|
29
41
|
def run_command(self, cmd: list, description: str) -> bool:
|
30
42
|
"""Run a command and handle errors."""
|
31
43
|
try:
|
32
44
|
print(f"🔧 {description}...")
|
45
|
+
# Use current working directory instead of project_root
|
33
46
|
result = subprocess.run(
|
34
47
|
cmd,
|
35
|
-
cwd=self.project_root,
|
36
48
|
capture_output=True,
|
37
49
|
text=True,
|
38
50
|
check=True
|
@@ -47,23 +59,73 @@ class SimpleCertificateCreator:
|
|
47
59
|
except Exception as e:
|
48
60
|
print(f"❌ {description} failed: {e}")
|
49
61
|
return False
|
50
|
-
|
51
62
|
def create_ca_certificate(self) -> bool:
|
52
|
-
"""Create CA certificate using OpenSSL."""
|
63
|
+
"""Create CA certificate using mcp_security_framework or OpenSSL fallback."""
|
53
64
|
ca_cert_path = self.certs_dir / "ca_cert.pem"
|
54
65
|
ca_key_path = self.keys_dir / "ca_key.pem"
|
55
|
-
|
56
66
|
if ca_cert_path.exists() and ca_key_path.exists():
|
57
67
|
print(f"ℹ️ CA certificate already exists: {ca_cert_path}")
|
58
68
|
return True
|
59
|
-
|
69
|
+
if SECURITY_FRAMEWORK_AVAILABLE:
|
70
|
+
return self._create_ca_certificate_with_framework()
|
71
|
+
else:
|
72
|
+
return self._create_ca_certificate_with_openssl()
|
73
|
+
def _create_ca_certificate_with_framework(self) -> bool:
|
74
|
+
"""Create CA certificate using mcp_security_framework."""
|
75
|
+
try:
|
76
|
+
print("🔧 Creating CA certificate using mcp_security_framework...")
|
77
|
+
# Create CA certificate configuration
|
78
|
+
ca_config = CAConfig(
|
79
|
+
common_name="mcp_proxy_adapter_test_ca",
|
80
|
+
organization="Test Organization",
|
81
|
+
organizational_unit="Test Unit",
|
82
|
+
country="US",
|
83
|
+
state="Test State",
|
84
|
+
locality="Test City",
|
85
|
+
validity_years=10
|
86
|
+
)
|
87
|
+
# Create certificate manager
|
88
|
+
cert_config = CertificateConfig(
|
89
|
+
cert_storage_path=str(self.certs_dir),
|
90
|
+
key_storage_path=str(self.keys_dir),
|
91
|
+
default_validity_days=365,
|
92
|
+
key_size=2048,
|
93
|
+
hash_algorithm="sha256"
|
94
|
+
)
|
95
|
+
cert_manager = CertificateManager(cert_config)
|
96
|
+
# Create CA certificate
|
97
|
+
cert_pair = cert_manager.create_root_ca(ca_config)
|
98
|
+
if cert_pair and cert_pair.certificate_path and cert_pair.private_key_path:
|
99
|
+
# Rename the generated files to the expected names
|
100
|
+
generated_cert = Path(cert_pair.certificate_path)
|
101
|
+
generated_key = Path(cert_pair.private_key_path)
|
102
|
+
if generated_cert.exists() and generated_key.exists():
|
103
|
+
# Move to expected names
|
104
|
+
expected_cert = self.certs_dir / "ca_cert.pem"
|
105
|
+
expected_key = self.keys_dir / "ca_key.pem"
|
106
|
+
generated_cert.rename(expected_cert)
|
107
|
+
generated_key.rename(expected_key)
|
108
|
+
print("✅ CA certificate created successfully using mcp_security_framework")
|
109
|
+
return True
|
110
|
+
else:
|
111
|
+
print("❌ Generated CA certificate files not found")
|
112
|
+
return False
|
113
|
+
else:
|
114
|
+
print("❌ Failed to create CA certificate: Invalid certificate pair")
|
115
|
+
return False
|
116
|
+
except Exception as e:
|
117
|
+
print(f"❌ Error creating CA certificate with framework: {e}")
|
118
|
+
return False
|
119
|
+
def _create_ca_certificate_with_openssl(self) -> bool:
|
120
|
+
"""Create CA certificate using OpenSSL fallback."""
|
121
|
+
ca_cert_path = self.certs_dir / "ca_cert.pem"
|
122
|
+
ca_key_path = self.keys_dir / "ca_key.pem"
|
60
123
|
# Create CA private key
|
61
124
|
key_cmd = [
|
62
125
|
"openssl", "genrsa", "-out", str(ca_key_path), "2048"
|
63
126
|
]
|
64
127
|
if not self.run_command(key_cmd, "Creating CA private key"):
|
65
128
|
return False
|
66
|
-
|
67
129
|
# Create CA certificate
|
68
130
|
cert_cmd = [
|
69
131
|
"openssl", "req", "-new", "-x509", "-days", "3650",
|
@@ -72,23 +134,97 @@ class SimpleCertificateCreator:
|
|
72
134
|
"-subj", "/C=US/ST=Test State/L=Test City/O=Test Organization/CN=MCP Proxy Adapter Test CA"
|
73
135
|
]
|
74
136
|
return self.run_command(cert_cmd, "Creating CA certificate")
|
75
|
-
|
76
137
|
def create_server_certificate(self) -> bool:
|
77
|
-
"""Create server certificate using OpenSSL."""
|
138
|
+
"""Create server certificate using mcp_security_framework or OpenSSL fallback."""
|
78
139
|
server_cert_path = self.certs_dir / "server_cert.pem"
|
79
140
|
server_key_path = self.certs_dir / "server_key.pem"
|
80
|
-
|
81
141
|
if server_cert_path.exists() and server_key_path.exists():
|
82
|
-
print(
|
142
|
+
print("ℹ️ Server certificate already exists")
|
83
143
|
return True
|
84
|
-
|
144
|
+
if SECURITY_FRAMEWORK_AVAILABLE:
|
145
|
+
return self._create_server_certificate_with_framework()
|
146
|
+
else:
|
147
|
+
return self._create_server_certificate_with_openssl()
|
148
|
+
def _create_server_certificate_with_framework(self) -> bool:
|
149
|
+
"""Create server certificate using mcp_security_framework."""
|
150
|
+
try:
|
151
|
+
print("🔧 Creating server certificate using mcp_security_framework...")
|
152
|
+
# Find CA certificate and key files
|
153
|
+
ca_cert_path = None
|
154
|
+
ca_key_path = None
|
155
|
+
# Look for CA certificate files with expected names
|
156
|
+
expected_ca_cert = self.certs_dir / "ca_cert.pem"
|
157
|
+
expected_ca_key = self.keys_dir / "ca_key.pem"
|
158
|
+
if expected_ca_cert.exists():
|
159
|
+
ca_cert_path = str(expected_ca_cert)
|
160
|
+
else:
|
161
|
+
# Fallback: look for CA certificate files with pattern
|
162
|
+
for cert_file in self.certs_dir.glob("*_ca.crt"):
|
163
|
+
ca_cert_path = str(cert_file)
|
164
|
+
break
|
165
|
+
if expected_ca_key.exists():
|
166
|
+
ca_key_path = str(expected_ca_key)
|
167
|
+
else:
|
168
|
+
# Fallback: look for CA key files with pattern
|
169
|
+
for key_file in self.keys_dir.glob("*_ca.key"):
|
170
|
+
ca_key_path = str(key_file)
|
171
|
+
break
|
172
|
+
if not ca_cert_path or not ca_key_path:
|
173
|
+
print("❌ CA certificate or key not found")
|
174
|
+
return False
|
175
|
+
# Create server certificate configuration
|
176
|
+
server_config = ServerCertConfig(
|
177
|
+
common_name="localhost",
|
178
|
+
organization="Test Organization",
|
179
|
+
organizational_unit="Test Unit",
|
180
|
+
country="US",
|
181
|
+
state="Test State",
|
182
|
+
locality="Test City",
|
183
|
+
subject_alt_names=["localhost", "127.0.0.1"],
|
184
|
+
validity_years=1,
|
185
|
+
ca_cert_path=ca_cert_path,
|
186
|
+
ca_key_path=ca_key_path
|
187
|
+
)
|
188
|
+
# Create certificate manager
|
189
|
+
cert_config = CertificateConfig(
|
190
|
+
cert_storage_path=str(self.certs_dir),
|
191
|
+
key_storage_path=str(self.certs_dir), # Server keys in certs dir
|
192
|
+
default_validity_days=365,
|
193
|
+
key_size=2048,
|
194
|
+
hash_algorithm="sha256"
|
195
|
+
)
|
196
|
+
cert_manager = CertificateManager(cert_config)
|
197
|
+
# Create server certificate
|
198
|
+
cert_pair = cert_manager.create_server_certificate(server_config)
|
199
|
+
if cert_pair and cert_pair.certificate_path and cert_pair.private_key_path:
|
200
|
+
# Rename the generated files to the expected names
|
201
|
+
generated_cert = Path(cert_pair.certificate_path)
|
202
|
+
generated_key = Path(cert_pair.private_key_path)
|
203
|
+
if generated_cert.exists() and generated_key.exists():
|
204
|
+
# Move to expected names
|
205
|
+
generated_cert.rename(self.certs_dir / "server_cert.pem")
|
206
|
+
generated_key.rename(self.certs_dir / "server_key.pem")
|
207
|
+
print("✅ Server certificate created successfully using mcp_security_framework")
|
208
|
+
return True
|
209
|
+
else:
|
210
|
+
print("❌ Generated certificate files not found")
|
211
|
+
return False
|
212
|
+
else:
|
213
|
+
print("❌ Failed to create server certificate: Invalid certificate pair")
|
214
|
+
return False
|
215
|
+
except Exception as e:
|
216
|
+
print(f"❌ Error creating server certificate with framework: {e}")
|
217
|
+
return False
|
218
|
+
def _create_server_certificate_with_openssl(self) -> bool:
|
219
|
+
"""Create server certificate using OpenSSL fallback."""
|
220
|
+
server_cert_path = self.certs_dir / "server_cert.pem"
|
221
|
+
server_key_path = self.certs_dir / "server_key.pem"
|
85
222
|
# Create server private key
|
86
223
|
key_cmd = [
|
87
224
|
"openssl", "genrsa", "-out", str(server_key_path), "2048"
|
88
225
|
]
|
89
226
|
if not self.run_command(key_cmd, "Creating server private key"):
|
90
227
|
return False
|
91
|
-
|
92
228
|
# Create server certificate signing request
|
93
229
|
csr_path = self.certs_dir / "server.csr"
|
94
230
|
csr_cmd = [
|
@@ -99,7 +235,6 @@ class SimpleCertificateCreator:
|
|
99
235
|
]
|
100
236
|
if not self.run_command(csr_cmd, "Creating server CSR"):
|
101
237
|
return False
|
102
|
-
|
103
238
|
# Create server certificate
|
104
239
|
cert_cmd = [
|
105
240
|
"openssl", "x509", "-req", "-days", "730",
|
@@ -110,29 +245,102 @@ class SimpleCertificateCreator:
|
|
110
245
|
"-out", str(server_cert_path)
|
111
246
|
]
|
112
247
|
success = self.run_command(cert_cmd, "Creating server certificate")
|
113
|
-
|
114
248
|
# Clean up CSR
|
115
249
|
if csr_path.exists():
|
116
250
|
csr_path.unlink()
|
117
|
-
|
118
251
|
return success
|
119
|
-
|
120
|
-
|
121
|
-
"""Create client certificate using OpenSSL."""
|
252
|
+
def create_client_certificate(self, name: str, common_name: str, roles: list = None, permissions: list = None) -> bool:
|
253
|
+
"""Create client certificate using mcp_security_framework or OpenSSL fallback."""
|
122
254
|
cert_path = self.certs_dir / f"{name}_cert.pem"
|
123
255
|
key_path = self.certs_dir / f"{name}_key.pem"
|
124
|
-
|
125
256
|
if cert_path.exists() and key_path.exists():
|
126
257
|
print(f"ℹ️ Client certificate {name} already exists: {cert_path}")
|
127
258
|
return True
|
128
|
-
|
259
|
+
if SECURITY_FRAMEWORK_AVAILABLE:
|
260
|
+
return self._create_client_certificate_with_framework(name, common_name, roles, permissions)
|
261
|
+
else:
|
262
|
+
return self._create_client_certificate_with_openssl(name, common_name)
|
263
|
+
def _create_client_certificate_with_framework(self, name: str, common_name: str, roles: list = None, permissions: list = None) -> bool:
|
264
|
+
"""Create client certificate using mcp_security_framework."""
|
265
|
+
try:
|
266
|
+
print(f"🔧 Creating client certificate {name} using mcp_security_framework...")
|
267
|
+
# Find CA certificate and key files
|
268
|
+
ca_cert_path = None
|
269
|
+
ca_key_path = None
|
270
|
+
# Look for CA certificate files with expected names
|
271
|
+
expected_ca_cert = self.certs_dir / "ca_cert.pem"
|
272
|
+
expected_ca_key = self.keys_dir / "ca_key.pem"
|
273
|
+
if expected_ca_cert.exists():
|
274
|
+
ca_cert_path = str(expected_ca_cert)
|
275
|
+
else:
|
276
|
+
# Fallback: look for CA certificate files with pattern
|
277
|
+
for cert_file in self.certs_dir.glob("*_ca.crt"):
|
278
|
+
ca_cert_path = str(cert_file)
|
279
|
+
break
|
280
|
+
if expected_ca_key.exists():
|
281
|
+
ca_key_path = str(expected_ca_key)
|
282
|
+
else:
|
283
|
+
# Fallback: look for CA key files with pattern
|
284
|
+
for key_file in self.keys_dir.glob("*_ca.key"):
|
285
|
+
ca_key_path = str(key_file)
|
286
|
+
break
|
287
|
+
if not ca_cert_path or not ca_key_path:
|
288
|
+
print("❌ CA certificate or key not found")
|
289
|
+
return False
|
290
|
+
# Create client certificate configuration
|
291
|
+
client_config = ClientCertConfig(
|
292
|
+
common_name=common_name,
|
293
|
+
organization="Test Organization",
|
294
|
+
organizational_unit="Test Unit",
|
295
|
+
country="US",
|
296
|
+
state="Test State",
|
297
|
+
locality="Test City",
|
298
|
+
validity_years=1,
|
299
|
+
ca_cert_path=ca_cert_path,
|
300
|
+
ca_key_path=ca_key_path
|
301
|
+
)
|
302
|
+
# Create certificate manager
|
303
|
+
cert_config = CertificateConfig(
|
304
|
+
cert_storage_path=str(self.certs_dir),
|
305
|
+
key_storage_path=str(self.certs_dir), # Client keys in certs dir
|
306
|
+
default_validity_days=365,
|
307
|
+
key_size=2048,
|
308
|
+
hash_algorithm="sha256"
|
309
|
+
)
|
310
|
+
cert_manager = CertificateManager(cert_config)
|
311
|
+
# Create client certificate
|
312
|
+
cert_pair = cert_manager.create_client_certificate(client_config)
|
313
|
+
if cert_pair and cert_pair.certificate_path and cert_pair.private_key_path:
|
314
|
+
# Rename the generated files to the expected names
|
315
|
+
generated_cert = Path(cert_pair.certificate_path)
|
316
|
+
generated_key = Path(cert_pair.private_key_path)
|
317
|
+
if generated_cert.exists() and generated_key.exists():
|
318
|
+
# Move to expected names
|
319
|
+
expected_cert = self.certs_dir / f"{name}_cert.pem"
|
320
|
+
expected_key = self.certs_dir / f"{name}_key.pem"
|
321
|
+
generated_cert.rename(expected_cert)
|
322
|
+
generated_key.rename(expected_key)
|
323
|
+
print(f"✅ Client certificate {name} created successfully using mcp_security_framework")
|
324
|
+
return True
|
325
|
+
else:
|
326
|
+
print(f"❌ Generated certificate files not found for {name}")
|
327
|
+
return False
|
328
|
+
else:
|
329
|
+
print(f"❌ Failed to create client certificate {name}: Invalid certificate pair")
|
330
|
+
return False
|
331
|
+
except Exception as e:
|
332
|
+
print(f"❌ Error creating client certificate {name} with framework: {e}")
|
333
|
+
return False
|
334
|
+
def _create_client_certificate_with_openssl(self, name: str, common_name: str) -> bool:
|
335
|
+
"""Create client certificate using OpenSSL fallback."""
|
336
|
+
cert_path = self.certs_dir / f"{name}_cert.pem"
|
337
|
+
key_path = self.certs_dir / f"{name}_key.pem"
|
129
338
|
# Create client private key
|
130
339
|
key_cmd = [
|
131
340
|
"openssl", "genrsa", "-out", str(key_path), "2048"
|
132
341
|
]
|
133
342
|
if not self.run_command(key_cmd, f"Creating {name} private key"):
|
134
343
|
return False
|
135
|
-
|
136
344
|
# Create client certificate signing request
|
137
345
|
csr_path = self.certs_dir / f"{name}.csr"
|
138
346
|
csr_cmd = [
|
@@ -143,7 +351,6 @@ class SimpleCertificateCreator:
|
|
143
351
|
]
|
144
352
|
if not self.run_command(csr_cmd, f"Creating {name} CSR"):
|
145
353
|
return False
|
146
|
-
|
147
354
|
# Create client certificate
|
148
355
|
cert_cmd = [
|
149
356
|
"openssl", "x509", "-req", "-days", "730",
|
@@ -154,45 +361,36 @@ class SimpleCertificateCreator:
|
|
154
361
|
"-out", str(cert_path)
|
155
362
|
]
|
156
363
|
success = self.run_command(cert_cmd, f"Creating {name} certificate")
|
157
|
-
|
158
364
|
# Clean up CSR
|
159
365
|
if csr_path.exists():
|
160
366
|
csr_path.unlink()
|
161
|
-
|
162
367
|
return success
|
163
|
-
|
164
368
|
def create_legacy_certificates(self) -> bool:
|
165
369
|
"""Create legacy certificate files for compatibility."""
|
166
370
|
legacy_files = [
|
167
|
-
("client.crt", "client.key", "client"),
|
168
371
|
("client_admin.crt", "client_admin.key", "admin"),
|
169
372
|
("admin.crt", "admin.key", "admin"),
|
170
373
|
("user.crt", "user.key", "user"),
|
171
374
|
("readonly.crt", "readonly.key", "readonly")
|
172
375
|
]
|
173
|
-
|
174
376
|
success = True
|
175
377
|
for cert_file, key_file, source_name in legacy_files:
|
176
378
|
cert_path = self.certs_dir / cert_file
|
177
379
|
key_path = self.certs_dir / key_file
|
178
|
-
|
179
380
|
if not cert_path.exists() or not key_path.exists():
|
180
381
|
source_cert = self.certs_dir / f"{source_name}_cert.pem"
|
181
382
|
source_key = self.certs_dir / f"{source_name}_key.pem"
|
182
|
-
|
183
383
|
if source_cert.exists() and source_key.exists():
|
184
384
|
self.run_command(["cp", str(source_cert), str(cert_path)], f"Creating {cert_file}")
|
185
385
|
self.run_command(["cp", str(source_key), str(key_path)], f"Creating {key_file}")
|
186
386
|
else:
|
187
387
|
print(f"⚠️ Source certificate {source_name} not found for {cert_file}")
|
188
|
-
|
189
|
-
|
190
|
-
return
|
191
|
-
|
388
|
+
# Don't fail the entire process for missing legacy certificates
|
389
|
+
continue
|
390
|
+
return True # Always return True for legacy certificates
|
192
391
|
def validate_certificates(self) -> bool:
|
193
392
|
"""Validate all created certificates."""
|
194
393
|
print("\n🔍 Validating certificates...")
|
195
|
-
|
196
394
|
cert_files = [
|
197
395
|
"ca_cert.pem",
|
198
396
|
"server_cert.pem",
|
@@ -202,7 +400,6 @@ class SimpleCertificateCreator:
|
|
202
400
|
"guest_cert.pem",
|
203
401
|
"proxy_cert.pem"
|
204
402
|
]
|
205
|
-
|
206
403
|
success = True
|
207
404
|
for cert_file in cert_files:
|
208
405
|
cert_path = self.certs_dir / cert_file
|
@@ -220,78 +417,68 @@ class SimpleCertificateCreator:
|
|
220
417
|
success = False
|
221
418
|
else:
|
222
419
|
print(f"⚠️ {cert_file}: Not found")
|
223
|
-
|
224
420
|
return success
|
225
|
-
|
226
421
|
def create_all(self) -> bool:
|
227
422
|
"""Create all certificates."""
|
228
423
|
print("🔐 Creating All Certificates for Security Testing")
|
229
424
|
print("=" * 60)
|
230
|
-
|
231
425
|
success = True
|
232
|
-
|
233
426
|
# 1. Create CA certificate
|
234
427
|
if not self.create_ca_certificate():
|
235
428
|
success = False
|
236
429
|
print("❌ Cannot continue without CA certificate")
|
237
430
|
return False
|
238
|
-
|
239
431
|
# 2. Create server certificate
|
240
432
|
if not self.create_server_certificate():
|
241
433
|
success = False
|
242
|
-
|
243
434
|
# 3. Create client certificates
|
244
435
|
print("\n👥 Creating client certificates...")
|
245
436
|
client_certs = [
|
246
|
-
("admin", "admin-client"),
|
247
|
-
("user", "user-client"),
|
248
|
-
("readonly", "readonly-client"),
|
249
|
-
("guest", "guest-client"),
|
250
|
-
("proxy", "proxy-client")
|
437
|
+
("admin", "admin-client", ["admin"], ["read", "write", "execute", "delete", "admin", "register", "unregister", "heartbeat", "discover"]),
|
438
|
+
("user", "user-client", ["user"], ["read", "execute", "register", "unregister", "heartbeat", "discover"]),
|
439
|
+
("readonly", "readonly-client", ["readonly"], ["read", "discover"]),
|
440
|
+
("guest", "guest-client", ["guest"], ["read", "discover"]),
|
441
|
+
("proxy", "proxy-client", ["proxy"], ["register", "unregister", "heartbeat", "discover"])
|
251
442
|
]
|
252
|
-
|
253
|
-
|
254
|
-
if not self.create_client_certificate(name, common_name):
|
443
|
+
for name, common_name, roles, permissions in client_certs:
|
444
|
+
if not self.create_client_certificate(name, common_name, roles, permissions):
|
255
445
|
success = False
|
256
|
-
|
257
446
|
# 4. Create legacy certificates
|
258
447
|
print("\n🔄 Creating legacy certificates...")
|
259
448
|
if not self.create_legacy_certificates():
|
260
449
|
success = False
|
261
|
-
|
262
450
|
# 5. Validate certificates
|
263
451
|
if not self.validate_certificates():
|
264
452
|
success = False
|
265
|
-
|
266
453
|
# Print summary
|
267
454
|
print("\n" + "=" * 60)
|
268
455
|
print("📊 CERTIFICATE CREATION SUMMARY")
|
269
456
|
print("=" * 60)
|
270
|
-
|
271
457
|
if success:
|
272
458
|
print("✅ All certificates created successfully!")
|
273
459
|
print(f"📁 Certificates directory: {self.certs_dir}")
|
274
460
|
print(f"🔑 Keys directory: {self.keys_dir}")
|
275
461
|
print("\n📋 Created certificates:")
|
276
|
-
|
277
462
|
cert_files = list(self.certs_dir.glob("*.pem")) + list(self.certs_dir.glob("*.crt"))
|
278
463
|
for cert_file in sorted(cert_files):
|
279
464
|
print(f" - {cert_file.name}")
|
280
|
-
|
281
465
|
key_files = list(self.keys_dir.glob("*.pem")) + list(self.keys_dir.glob("*.key"))
|
282
466
|
for key_file in sorted(key_files):
|
283
467
|
print(f" - {key_file.name}")
|
284
468
|
else:
|
285
469
|
print("❌ Some certificates failed to create")
|
286
470
|
print("Check the error messages above")
|
287
|
-
|
288
471
|
return success
|
289
|
-
|
290
|
-
|
291
472
|
def main():
|
292
473
|
"""Main function."""
|
293
|
-
|
294
|
-
|
474
|
+
parser = argparse.ArgumentParser(description="Create certificates for testing")
|
475
|
+
parser.add_argument("--certs-dir", help="Directory for certificates")
|
476
|
+
parser.add_argument("--keys-dir", help="Directory for keys")
|
477
|
+
args = parser.parse_args()
|
478
|
+
creator = SimpleCertificateCreator(
|
479
|
+
certs_dir=args.certs_dir,
|
480
|
+
keys_dir=args.keys_dir
|
481
|
+
)
|
295
482
|
try:
|
296
483
|
success = creator.create_all()
|
297
484
|
sys.exit(0 if success else 1)
|
@@ -301,7 +488,5 @@ def main():
|
|
301
488
|
except Exception as e:
|
302
489
|
print(f"\n❌ Certificate creation failed: {e}")
|
303
490
|
sys.exit(1)
|
304
|
-
|
305
|
-
|
306
491
|
if __name__ == "__main__":
|
307
492
|
main()
|