mcp-proxy-adapter 6.0.0__py3-none-any.whl → 6.0.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 +209 -79
- mcp_proxy_adapter/api/handlers.py +16 -5
- mcp_proxy_adapter/api/middleware/__init__.py +14 -9
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
- mcp_proxy_adapter/api/middleware/factory.py +36 -12
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +84 -18
- mcp_proxy_adapter/api/middleware/unified_security.py +197 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +158 -0
- mcp_proxy_adapter/commands/__init__.py +7 -1
- mcp_proxy_adapter/commands/base.py +7 -4
- mcp_proxy_adapter/commands/builtin_commands.py +8 -2
- mcp_proxy_adapter/commands/command_registry.py +8 -0
- mcp_proxy_adapter/commands/echo_command.py +81 -0
- mcp_proxy_adapter/commands/health_command.py +1 -1
- mcp_proxy_adapter/commands/help_command.py +21 -14
- mcp_proxy_adapter/commands/proxy_registration_command.py +326 -185
- mcp_proxy_adapter/commands/role_test_command.py +141 -0
- mcp_proxy_adapter/commands/security_command.py +488 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +234 -351
- mcp_proxy_adapter/commands/token_management_command.py +1 -1
- mcp_proxy_adapter/config.py +323 -40
- mcp_proxy_adapter/core/app_factory.py +410 -0
- 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/client_security.py +384 -0
- mcp_proxy_adapter/core/logging.py +8 -3
- mcp_proxy_adapter/core/mtls_asgi.py +156 -0
- mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
- mcp_proxy_adapter/core/protocol_manager.py +169 -10
- mcp_proxy_adapter/core/proxy_client.py +602 -0
- mcp_proxy_adapter/core/proxy_registration.py +299 -47
- mcp_proxy_adapter/core/security_adapter.py +12 -15
- mcp_proxy_adapter/core/security_integration.py +286 -0
- mcp_proxy_adapter/core/server_adapter.py +282 -0
- mcp_proxy_adapter/core/server_engine.py +270 -0
- mcp_proxy_adapter/core/ssl_utils.py +13 -12
- mcp_proxy_adapter/core/transport_manager.py +5 -5
- mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
- mcp_proxy_adapter/examples/__init__.py +13 -4
- mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -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 +44 -0
- mcp_proxy_adapter/examples/commands/__init__.py +5 -0
- mcp_proxy_adapter/examples/create_certificates_simple.py +550 -0
- mcp_proxy_adapter/examples/debug_request_state.py +112 -0
- mcp_proxy_adapter/examples/debug_role_chain.py +158 -0
- mcp_proxy_adapter/examples/demo_client.py +275 -0
- 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/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +80 -0
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +90 -0
- mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +75 -0
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +71 -0
- mcp_proxy_adapter/examples/full_application/main.py +173 -0
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
- mcp_proxy_adapter/examples/generate_all_certificates.py +362 -0
- mcp_proxy_adapter/examples/generate_certificates.py +177 -0
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
- mcp_proxy_adapter/examples/generate_test_configs.py +331 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +334 -0
- mcp_proxy_adapter/examples/run_example.py +59 -0
- mcp_proxy_adapter/examples/run_full_test_suite.py +318 -0
- mcp_proxy_adapter/examples/run_proxy_server.py +146 -0
- mcp_proxy_adapter/examples/run_security_tests.py +544 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +247 -0
- 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/examples/security_test_client.py +782 -0
- mcp_proxy_adapter/examples/setup_test_environment.py +328 -0
- mcp_proxy_adapter/examples/test_config.py +148 -0
- mcp_proxy_adapter/examples/test_config_generator.py +86 -0
- mcp_proxy_adapter/examples/test_examples.py +281 -0
- mcp_proxy_adapter/examples/universal_client.py +620 -0
- mcp_proxy_adapter/main.py +66 -148
- mcp_proxy_adapter/utils/config_generator.py +1008 -0
- mcp_proxy_adapter/version.py +5 -2
- mcp_proxy_adapter-6.0.1.dist-info/METADATA +679 -0
- mcp_proxy_adapter-6.0.1.dist-info/RECORD +140 -0
- mcp_proxy_adapter-6.0.1.dist-info/entry_points.txt +2 -0
- {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/licenses/LICENSE +2 -2
- mcp_proxy_adapter/api/middleware/auth.py +0 -146
- mcp_proxy_adapter/api/middleware/auth_adapter.py +0 -235
- mcp_proxy_adapter/api/middleware/mtls_adapter.py +0 -305
- mcp_proxy_adapter/api/middleware/mtls_middleware.py +0 -296
- mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
- mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +0 -241
- mcp_proxy_adapter/api/middleware/roles_adapter.py +0 -365
- mcp_proxy_adapter/api/middleware/roles_middleware.py +0 -381
- mcp_proxy_adapter/api/middleware/security.py +0 -376
- mcp_proxy_adapter/api/middleware/token_auth_middleware.py +0 -261
- mcp_proxy_adapter/examples/README.md +0 -124
- mcp_proxy_adapter/examples/basic_server/README.md +0 -60
- mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
- mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
- mcp_proxy_adapter/examples/basic_server/config.json +0 -70
- mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +0 -54
- mcp_proxy_adapter/examples/basic_server/config_http.json +0 -70
- mcp_proxy_adapter/examples/basic_server/config_http_only.json +0 -52
- mcp_proxy_adapter/examples/basic_server/config_https.json +0 -58
- mcp_proxy_adapter/examples/basic_server/config_mtls.json +0 -58
- mcp_proxy_adapter/examples/basic_server/config_ssl.json +0 -46
- mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
- mcp_proxy_adapter/examples/basic_server/server.py +0 -114
- mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
- mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
- mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -566
- mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
- mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +0 -105
- mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +0 -129
- mcp_proxy_adapter/examples/custom_commands/config.json +0 -118
- mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_https_only.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
- mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
- mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
- mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
- mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
- mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
- mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
- mcp_proxy_adapter/examples/custom_commands/full_help_response.json +0 -1
- mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +0 -629
- mcp_proxy_adapter/examples/custom_commands/get_openapi.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
- mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
- mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +0 -129
- mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +0 -278
- mcp_proxy_adapter/examples/custom_commands/server.py +0 -252
- mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +0 -75
- mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +0 -299
- mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +0 -278
- mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
- mcp_proxy_adapter/examples/custom_commands/test_openapi.py +0 -27
- mcp_proxy_adapter/examples/custom_commands/test_registry.py +0 -23
- mcp_proxy_adapter/examples/custom_commands/test_simple.py +0 -19
- mcp_proxy_adapter/examples/custom_project_example/README.md +0 -103
- mcp_proxy_adapter/examples/custom_project_example/README_EN.md +0 -103
- mcp_proxy_adapter/examples/deployment/README.md +0 -49
- mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
- mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
- mcp_proxy_adapter/examples/deployment/config.json +0 -29
- mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
- mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
- mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
- mcp_proxy_adapter/examples/deployment/run.sh +0 -43
- mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
- mcp_proxy_adapter/examples/simple_custom_commands/README.md +0 -149
- mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +0 -149
- mcp_proxy_adapter/schemas/base_schema.json +0 -114
- mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
- mcp_proxy_adapter/schemas/roles_schema.json +0 -162
- mcp_proxy_adapter/tests/__init__.py +0 -0
- mcp_proxy_adapter/tests/api/__init__.py +0 -3
- mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
- mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
- mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
- mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
- mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
- mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
- mcp_proxy_adapter/tests/commands/__init__.py +0 -3
- mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
- mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
- mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
- mcp_proxy_adapter/tests/conftest.py +0 -131
- mcp_proxy_adapter/tests/functional/__init__.py +0 -3
- mcp_proxy_adapter/tests/functional/test_api.py +0 -253
- mcp_proxy_adapter/tests/integration/__init__.py +0 -3
- mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
- mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
- mcp_proxy_adapter/tests/performance/__init__.py +0 -3
- mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
- mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
- mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
- mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
- mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
- mcp_proxy_adapter/tests/test_base_command.py +0 -123
- mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
- mcp_proxy_adapter/tests/test_command_registry.py +0 -281
- mcp_proxy_adapter/tests/test_config.py +0 -127
- mcp_proxy_adapter/tests/test_utils.py +0 -65
- mcp_proxy_adapter/tests/unit/__init__.py +0 -3
- mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
- mcp_proxy_adapter/tests/unit/test_config.py +0 -270
- mcp_proxy_adapter-6.0.0.dist-info/METADATA +0 -201
- mcp_proxy_adapter-6.0.0.dist-info/RECORD +0 -179
- {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,247 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Security Testing Script - Fixed Version
|
4
|
+
This script runs comprehensive security tests without fallback mode
|
5
|
+
and with proper port management.
|
6
|
+
Author: Vasiliy Zdanovskiy
|
7
|
+
email: vasilyvz@gmail.com
|
8
|
+
"""
|
9
|
+
import asyncio
|
10
|
+
import json
|
11
|
+
import os
|
12
|
+
import signal
|
13
|
+
import subprocess
|
14
|
+
import sys
|
15
|
+
import time
|
16
|
+
from pathlib import Path
|
17
|
+
from typing import Dict, List, Optional, Tuple
|
18
|
+
# Add project root to path
|
19
|
+
project_root = Path(__file__).parent.parent.parent
|
20
|
+
sys.path.insert(0, str(project_root))
|
21
|
+
from security_test_client import SecurityTestClient, TestResult
|
22
|
+
class SecurityTestRunner:
|
23
|
+
"""Security test runner with proper port management."""
|
24
|
+
def __init__(self):
|
25
|
+
self.project_root = Path(__file__).parent.parent.parent
|
26
|
+
self.configs_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "server_configs"
|
27
|
+
self.server_processes = {}
|
28
|
+
self.test_results = []
|
29
|
+
def kill_process_on_port(self, port: int) -> bool:
|
30
|
+
"""Kill process using specific port."""
|
31
|
+
try:
|
32
|
+
# Find process using the port
|
33
|
+
result = subprocess.run(
|
34
|
+
["lsof", "-ti", f":{port}"],
|
35
|
+
capture_output=True,
|
36
|
+
text=True,
|
37
|
+
timeout=5
|
38
|
+
)
|
39
|
+
if result.returncode == 0 and result.stdout.strip():
|
40
|
+
pid = result.stdout.strip()
|
41
|
+
# Kill the process
|
42
|
+
subprocess.run(["kill", "-9", pid], check=True)
|
43
|
+
print(f"✅ Killed process {pid} on port {port}")
|
44
|
+
time.sleep(1) # Wait for port to be released
|
45
|
+
return True
|
46
|
+
else:
|
47
|
+
print(f"ℹ️ No process found on port {port}")
|
48
|
+
return True
|
49
|
+
except subprocess.TimeoutExpired:
|
50
|
+
print(f"⚠️ Timeout checking port {port}")
|
51
|
+
return False
|
52
|
+
except Exception as e:
|
53
|
+
print(f"❌ Error killing process on port {port}: {e}")
|
54
|
+
return False
|
55
|
+
def start_server(self, config_name: str, config_path: Path) -> Optional[subprocess.Popen]:
|
56
|
+
"""Start server with proper error handling."""
|
57
|
+
try:
|
58
|
+
# Get port from config
|
59
|
+
with open(config_path) as f:
|
60
|
+
config = json.load(f)
|
61
|
+
port = config.get("server", {}).get("port", 8000)
|
62
|
+
# Kill any existing process on this port
|
63
|
+
self.kill_process_on_port(port)
|
64
|
+
# Start server
|
65
|
+
cmd = [
|
66
|
+
sys.executable, "-m", "mcp_proxy_adapter.main",
|
67
|
+
"--config", str(config_path)
|
68
|
+
]
|
69
|
+
# For mTLS, start from examples directory
|
70
|
+
if config_name == "mtls":
|
71
|
+
cwd = self.project_root / "mcp_proxy_adapter" / "examples"
|
72
|
+
else:
|
73
|
+
cwd = self.project_root
|
74
|
+
print(f"🚀 Starting {config_name} on port {port}...")
|
75
|
+
process = subprocess.Popen(
|
76
|
+
cmd,
|
77
|
+
cwd=cwd,
|
78
|
+
stdout=subprocess.PIPE,
|
79
|
+
stderr=subprocess.PIPE,
|
80
|
+
text=True
|
81
|
+
)
|
82
|
+
# Wait a bit for server to start
|
83
|
+
time.sleep(3)
|
84
|
+
# Check if process is still running
|
85
|
+
if process.poll() is None:
|
86
|
+
print(f"✅ {config_name} started successfully on port {port}")
|
87
|
+
return process
|
88
|
+
else:
|
89
|
+
stdout, stderr = process.communicate()
|
90
|
+
print(f"❌ {config_name} failed to start:")
|
91
|
+
print(f"STDOUT: {stdout}")
|
92
|
+
print(f"STDERR: {stderr}")
|
93
|
+
return None
|
94
|
+
except Exception as e:
|
95
|
+
print(f"❌ Error starting {config_name}: {e}")
|
96
|
+
return None
|
97
|
+
def stop_server(self, config_name: str, process: subprocess.Popen):
|
98
|
+
"""Stop server gracefully."""
|
99
|
+
try:
|
100
|
+
print(f"🛑 Stopping {config_name}...")
|
101
|
+
process.terminate()
|
102
|
+
process.wait(timeout=5)
|
103
|
+
print(f"✅ {config_name} stopped")
|
104
|
+
except subprocess.TimeoutExpired:
|
105
|
+
print(f"⚠️ Force killing {config_name}...")
|
106
|
+
process.kill()
|
107
|
+
process.wait()
|
108
|
+
except Exception as e:
|
109
|
+
print(f"❌ Error stopping {config_name}: {e}")
|
110
|
+
async def test_server(self, config_name: str, config_path: Path) -> List[TestResult]:
|
111
|
+
"""Test a single server configuration."""
|
112
|
+
results = []
|
113
|
+
# Start server
|
114
|
+
process = self.start_server(config_name, config_path)
|
115
|
+
if not process:
|
116
|
+
return [TestResult(
|
117
|
+
test_name=f"{config_name}_startup",
|
118
|
+
server_url=f"http://localhost:{port}",
|
119
|
+
auth_type="none",
|
120
|
+
success=False,
|
121
|
+
error_message="Server failed to start"
|
122
|
+
)]
|
123
|
+
try:
|
124
|
+
# Get config for client setup
|
125
|
+
with open(config_path) as f:
|
126
|
+
config = json.load(f)
|
127
|
+
port = config.get("server", {}).get("port", 8000)
|
128
|
+
auth_enabled = config.get("security", {}).get("auth", {}).get("enabled", False)
|
129
|
+
auth_methods = config.get("security", {}).get("auth", {}).get("methods", [])
|
130
|
+
# Create test client with correct protocol
|
131
|
+
protocol = "https" if config.get("ssl", {}).get("enabled", False) else "http"
|
132
|
+
client = SecurityTestClient(base_url=f"{protocol}://localhost:{port}")
|
133
|
+
client.auth_enabled = auth_enabled
|
134
|
+
client.auth_methods = auth_methods
|
135
|
+
client.api_keys = config.get("security", {}).get("auth", {}).get("api_keys", {})
|
136
|
+
# For mTLS, override SSL context creation and change working directory
|
137
|
+
if config_name == "mtls":
|
138
|
+
client.create_ssl_context = client.create_ssl_context_for_mtls
|
139
|
+
# Ensure mTLS uses certificate auth
|
140
|
+
client.auth_methods = ["certificate"]
|
141
|
+
# Change to examples directory for mTLS tests
|
142
|
+
import os
|
143
|
+
os.chdir(self.project_root / "mcp_proxy_adapter" / "examples")
|
144
|
+
# Run tests
|
145
|
+
async with client:
|
146
|
+
# Test 1: Health check
|
147
|
+
result = await client.test_health()
|
148
|
+
results.append(result)
|
149
|
+
# Test 2: Command execution
|
150
|
+
result = await client.test_command_execution()
|
151
|
+
results.append(result)
|
152
|
+
# Test 3: Authentication (if enabled)
|
153
|
+
if auth_enabled:
|
154
|
+
result = await client.test_authentication()
|
155
|
+
results.append(result)
|
156
|
+
# Test 4: Negative authentication
|
157
|
+
result = await client.test_negative_authentication()
|
158
|
+
results.append(result)
|
159
|
+
# Test 5: Role-based access
|
160
|
+
result = await client.test_role_based_access(client.base_url, "api_key")
|
161
|
+
results.append(result)
|
162
|
+
# Test 6: Role permissions
|
163
|
+
result = await client.test_role_permissions(client.base_url, "api_key")
|
164
|
+
results.append(result)
|
165
|
+
# Test 7: Multiple roles test
|
166
|
+
result = await client.test_multiple_roles(client.base_url, "api_key")
|
167
|
+
results.append(result)
|
168
|
+
else:
|
169
|
+
# Test 3: No authentication required
|
170
|
+
result = await client.test_no_auth_required()
|
171
|
+
results.append(result)
|
172
|
+
# Test 4: Negative auth (should fail)
|
173
|
+
result = await client.test_negative_authentication()
|
174
|
+
results.append(result)
|
175
|
+
except Exception as e:
|
176
|
+
results.append(TestResult(
|
177
|
+
test_name=f"{config_name}_client_error",
|
178
|
+
server_url=f"http://localhost:{port}",
|
179
|
+
auth_type="none",
|
180
|
+
success=False,
|
181
|
+
error_message=str(e)
|
182
|
+
))
|
183
|
+
finally:
|
184
|
+
# Stop server
|
185
|
+
self.stop_server(config_name, process)
|
186
|
+
return results
|
187
|
+
async def run_all_tests(self):
|
188
|
+
"""Run all security tests."""
|
189
|
+
print("🔒 Starting Security Testing Suite")
|
190
|
+
print("=" * 50)
|
191
|
+
# Test configurations
|
192
|
+
configs = [
|
193
|
+
("basic_http", "config_basic_http.json"),
|
194
|
+
("http_token", "config_http_token.json"),
|
195
|
+
("https", "config_https.json"),
|
196
|
+
("https_token", "config_https_token.json"),
|
197
|
+
("mtls", "config_mtls.json")
|
198
|
+
]
|
199
|
+
total_tests = 0
|
200
|
+
passed_tests = 0
|
201
|
+
for config_name, config_file in configs:
|
202
|
+
config_path = self.configs_dir / config_file
|
203
|
+
if not config_path.exists():
|
204
|
+
print(f"❌ Configuration not found: {config_path}")
|
205
|
+
continue
|
206
|
+
print(f"\n📋 Testing {config_name.upper()} configuration")
|
207
|
+
print("-" * 30)
|
208
|
+
results = await self.test_server(config_name, config_path)
|
209
|
+
for result in results:
|
210
|
+
total_tests += 1
|
211
|
+
if result.success:
|
212
|
+
passed_tests += 1
|
213
|
+
print(f"✅ {result.test_name}: PASS")
|
214
|
+
else:
|
215
|
+
print(f"❌ {result.test_name}: FAIL - {result.error_message}")
|
216
|
+
self.test_results.extend(results)
|
217
|
+
# Print summary
|
218
|
+
print("\n" + "=" * 50)
|
219
|
+
print("📊 TEST SUMMARY")
|
220
|
+
print("=" * 50)
|
221
|
+
print(f"Total tests: {total_tests}")
|
222
|
+
print(f"Passed: {passed_tests}")
|
223
|
+
print(f"Failed: {total_tests - passed_tests}")
|
224
|
+
print(f"Success rate: {(passed_tests/total_tests*100):.1f}%" if total_tests > 0 else "N/A")
|
225
|
+
# Detailed results
|
226
|
+
print("\n📋 DETAILED RESULTS")
|
227
|
+
print("-" * 30)
|
228
|
+
for result in self.test_results:
|
229
|
+
status = "✅ PASS" if result.success else "❌ FAIL"
|
230
|
+
print(f"{status} {result.test_name}")
|
231
|
+
if not result.success and result.error_message:
|
232
|
+
print(f" Error: {result.error_message}")
|
233
|
+
return passed_tests == total_tests
|
234
|
+
async def main():
|
235
|
+
"""Main function."""
|
236
|
+
runner = SecurityTestRunner()
|
237
|
+
try:
|
238
|
+
success = await runner.run_all_tests()
|
239
|
+
sys.exit(0 if success else 1)
|
240
|
+
except KeyboardInterrupt:
|
241
|
+
print("\n⚠️ Testing interrupted by user")
|
242
|
+
sys.exit(1)
|
243
|
+
except Exception as e:
|
244
|
+
print(f"\n❌ Testing failed: {e}")
|
245
|
+
sys.exit(1)
|
246
|
+
if __name__ == "__main__":
|
247
|
+
asyncio.run(main())
|