mcp-proxy-adapter 6.0.0__py3-none-any.whl → 6.1.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/api/app.py +174 -80
- mcp_proxy_adapter/api/handlers.py +16 -5
- mcp_proxy_adapter/api/middleware/__init__.py +9 -4
- 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 +32 -13
- mcp_proxy_adapter/api/middleware/unified_security.py +160 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +83 -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/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 +2 -2
- mcp_proxy_adapter/commands/token_management_command.py +1 -1
- mcp_proxy_adapter/config.py +81 -21
- mcp_proxy_adapter/core/app_factory.py +326 -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 +139 -8
- 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 +285 -0
- mcp_proxy_adapter/core/server_adapter.py +345 -0
- mcp_proxy_adapter/core/server_engine.py +364 -0
- mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
- mcp_proxy_adapter/docs/EN/TROUBLESHOOTING.md +285 -0
- mcp_proxy_adapter/docs/RU/TROUBLESHOOTING.md +285 -0
- mcp_proxy_adapter/examples/README.md +230 -97
- mcp_proxy_adapter/examples/README_EN.md +258 -0
- mcp_proxy_adapter/examples/SECURITY_TESTING.md +455 -0
- mcp_proxy_adapter/examples/basic_framework/configs/http_auth.json +37 -0
- mcp_proxy_adapter/examples/basic_framework/configs/http_simple.json +23 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_auth.json +43 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_no_protocol_middleware.json +36 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +29 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_protocol_middleware.json +34 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +39 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_simple.json +35 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_with_roles.json +45 -0
- mcp_proxy_adapter/examples/basic_framework/main.py +63 -0
- mcp_proxy_adapter/examples/basic_framework/roles.json +21 -0
- mcp_proxy_adapter/examples/cert_config.json +9 -0
- mcp_proxy_adapter/examples/certs/admin.crt +32 -0
- mcp_proxy_adapter/examples/certs/admin.key +52 -0
- mcp_proxy_adapter/examples/certs/admin_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/admin_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/ca_cert.pem +23 -0
- mcp_proxy_adapter/examples/certs/ca_cert.srl +1 -0
- mcp_proxy_adapter/examples/certs/ca_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/cert_config.json +9 -0
- mcp_proxy_adapter/examples/certs/client.crt +32 -0
- mcp_proxy_adapter/examples/certs/client.key +52 -0
- mcp_proxy_adapter/examples/certs/client_admin.crt +32 -0
- mcp_proxy_adapter/examples/certs/client_admin.key +52 -0
- mcp_proxy_adapter/examples/certs/client_user.crt +32 -0
- mcp_proxy_adapter/examples/certs/client_user.key +52 -0
- mcp_proxy_adapter/examples/certs/guest_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/guest_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/mcp_proxy_adapter_ca_ca.crt +23 -0
- mcp_proxy_adapter/examples/certs/proxy_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/proxy_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/readonly.crt +32 -0
- mcp_proxy_adapter/examples/certs/readonly.key +52 -0
- mcp_proxy_adapter/examples/certs/readonly_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/readonly_key.pem +28 -0
- mcp_proxy_adapter/examples/certs/server.crt +32 -0
- mcp_proxy_adapter/examples/certs/server.key +52 -0
- mcp_proxy_adapter/examples/certs/server_cert.pem +32 -0
- mcp_proxy_adapter/examples/certs/server_key.pem +52 -0
- mcp_proxy_adapter/examples/certs/test_ca_ca.crt +20 -0
- mcp_proxy_adapter/examples/certs/user.crt +32 -0
- mcp_proxy_adapter/examples/certs/user.key +52 -0
- mcp_proxy_adapter/examples/certs/user_cert.pem +21 -0
- mcp_proxy_adapter/examples/certs/user_key.pem +28 -0
- mcp_proxy_adapter/examples/client_configs/api_key_client.json +13 -0
- mcp_proxy_adapter/examples/client_configs/basic_auth_client.json +13 -0
- mcp_proxy_adapter/examples/client_configs/certificate_client.json +22 -0
- mcp_proxy_adapter/examples/client_configs/jwt_client.json +15 -0
- mcp_proxy_adapter/examples/client_configs/no_auth_client.json +9 -0
- mcp_proxy_adapter/examples/commands/__init__.py +1 -0
- mcp_proxy_adapter/examples/create_certificates_simple.py +307 -0
- mcp_proxy_adapter/examples/debug_request_state.py +144 -0
- mcp_proxy_adapter/examples/debug_role_chain.py +205 -0
- mcp_proxy_adapter/examples/demo_client.py +341 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +99 -0
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +106 -0
- mcp_proxy_adapter/examples/full_application/configs/http_auth.json +37 -0
- mcp_proxy_adapter/examples/full_application/configs/http_simple.json +23 -0
- mcp_proxy_adapter/examples/full_application/configs/https_auth.json +39 -0
- mcp_proxy_adapter/examples/full_application/configs/https_simple.json +25 -0
- mcp_proxy_adapter/examples/full_application/configs/mtls_no_roles.json +39 -0
- mcp_proxy_adapter/examples/full_application/configs/mtls_with_roles.json +45 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +97 -0
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +95 -0
- mcp_proxy_adapter/examples/full_application/main.py +138 -0
- mcp_proxy_adapter/examples/full_application/roles.json +21 -0
- mcp_proxy_adapter/examples/generate_all_certificates.py +429 -0
- mcp_proxy_adapter/examples/generate_certificates.py +121 -0
- mcp_proxy_adapter/examples/keys/ca_key.pem +28 -0
- mcp_proxy_adapter/examples/keys/mcp_proxy_adapter_ca_ca.key +28 -0
- mcp_proxy_adapter/examples/keys/test_ca_ca.key +28 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log +220 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.5 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log +220 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.5 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log +2 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.1 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.2 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.3 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.4 +1 -0
- mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.5 +1 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +401 -0
- mcp_proxy_adapter/examples/roles.json +38 -0
- mcp_proxy_adapter/examples/run_example.py +81 -0
- mcp_proxy_adapter/examples/run_security_tests.py +326 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +300 -0
- mcp_proxy_adapter/examples/security_test_client.py +743 -0
- mcp_proxy_adapter/examples/server_configs/config_basic_http.json +204 -0
- mcp_proxy_adapter/examples/server_configs/config_http_token.json +238 -0
- mcp_proxy_adapter/examples/server_configs/config_https.json +215 -0
- mcp_proxy_adapter/examples/server_configs/config_https_token.json +231 -0
- mcp_proxy_adapter/examples/server_configs/config_mtls.json +215 -0
- mcp_proxy_adapter/examples/server_configs/config_proxy_registration.json +250 -0
- mcp_proxy_adapter/examples/server_configs/config_simple.json +46 -0
- mcp_proxy_adapter/examples/server_configs/roles.json +38 -0
- mcp_proxy_adapter/examples/test_config_generator.py +110 -0
- mcp_proxy_adapter/examples/test_examples.py +344 -0
- mcp_proxy_adapter/examples/universal_client.py +628 -0
- mcp_proxy_adapter/main.py +21 -10
- mcp_proxy_adapter/utils/config_generator.py +727 -0
- mcp_proxy_adapter/version.py +5 -2
- mcp_proxy_adapter-6.1.1.dist-info/METADATA +205 -0
- mcp_proxy_adapter-6.1.1.dist-info/RECORD +197 -0
- mcp_proxy_adapter-6.1.1.dist-info/entry_points.txt +2 -0
- {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.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/__init__.py +0 -7
- 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.1.1.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"server_url": "https://localhost:8443",
|
3
|
+
"timeout": 30,
|
4
|
+
"retry_attempts": 3,
|
5
|
+
"retry_delay": 1,
|
6
|
+
"security": {
|
7
|
+
"auth_method": "certificate",
|
8
|
+
"certificate": {
|
9
|
+
"enabled": true,
|
10
|
+
"cert_file": "./certs/client.crt",
|
11
|
+
"key_file": "./keys/client.key",
|
12
|
+
"ca_cert_file": "./certs/ca.crt"
|
13
|
+
},
|
14
|
+
"ssl": {
|
15
|
+
"enabled": true,
|
16
|
+
"check_hostname": true,
|
17
|
+
"ca_cert_file": "./certs/ca.crt",
|
18
|
+
"verify_mode": "CERT_REQUIRED",
|
19
|
+
"min_tls_version": "TLSv1.2"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
{
|
2
|
+
"server_url": "http://localhost:8000",
|
3
|
+
"timeout": 30,
|
4
|
+
"retry_attempts": 3,
|
5
|
+
"retry_delay": 1,
|
6
|
+
"security": {
|
7
|
+
"auth_method": "jwt",
|
8
|
+
"jwt": {
|
9
|
+
"username": "demo_user",
|
10
|
+
"password": "demo_password",
|
11
|
+
"secret": "your_jwt_secret_here",
|
12
|
+
"expiry_hours": 24
|
13
|
+
}
|
14
|
+
}
|
15
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
# Commands package
|
@@ -0,0 +1,307 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Simple Certificate Creation Script
|
4
|
+
|
5
|
+
This script creates basic certificates for testing using OpenSSL directly.
|
6
|
+
|
7
|
+
Author: Vasiliy Zdanovskiy
|
8
|
+
email: vasilyvz@gmail.com
|
9
|
+
"""
|
10
|
+
|
11
|
+
import os
|
12
|
+
import subprocess
|
13
|
+
import sys
|
14
|
+
from pathlib import Path
|
15
|
+
|
16
|
+
|
17
|
+
class SimpleCertificateCreator:
|
18
|
+
"""Create certificates using OpenSSL directly."""
|
19
|
+
|
20
|
+
def __init__(self):
|
21
|
+
self.project_root = Path(__file__).parent.parent.parent
|
22
|
+
self.certs_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "certs"
|
23
|
+
self.keys_dir = self.project_root / "mcp_proxy_adapter" / "examples" / "keys"
|
24
|
+
|
25
|
+
# Create directories
|
26
|
+
self.certs_dir.mkdir(parents=True, exist_ok=True)
|
27
|
+
self.keys_dir.mkdir(parents=True, exist_ok=True)
|
28
|
+
|
29
|
+
def run_command(self, cmd: list, description: str) -> bool:
|
30
|
+
"""Run a command and handle errors."""
|
31
|
+
try:
|
32
|
+
print(f"🔧 {description}...")
|
33
|
+
result = subprocess.run(
|
34
|
+
cmd,
|
35
|
+
cwd=self.project_root,
|
36
|
+
capture_output=True,
|
37
|
+
text=True,
|
38
|
+
check=True
|
39
|
+
)
|
40
|
+
print(f"✅ {description} completed successfully")
|
41
|
+
return True
|
42
|
+
except subprocess.CalledProcessError as e:
|
43
|
+
print(f"❌ {description} failed:")
|
44
|
+
print(f" Command: {' '.join(cmd)}")
|
45
|
+
print(f" Error: {e.stderr}")
|
46
|
+
return False
|
47
|
+
except Exception as e:
|
48
|
+
print(f"❌ {description} failed: {e}")
|
49
|
+
return False
|
50
|
+
|
51
|
+
def create_ca_certificate(self) -> bool:
|
52
|
+
"""Create CA certificate using OpenSSL."""
|
53
|
+
ca_cert_path = self.certs_dir / "ca_cert.pem"
|
54
|
+
ca_key_path = self.keys_dir / "ca_key.pem"
|
55
|
+
|
56
|
+
if ca_cert_path.exists() and ca_key_path.exists():
|
57
|
+
print(f"ℹ️ CA certificate already exists: {ca_cert_path}")
|
58
|
+
return True
|
59
|
+
|
60
|
+
# Create CA private key
|
61
|
+
key_cmd = [
|
62
|
+
"openssl", "genrsa", "-out", str(ca_key_path), "2048"
|
63
|
+
]
|
64
|
+
if not self.run_command(key_cmd, "Creating CA private key"):
|
65
|
+
return False
|
66
|
+
|
67
|
+
# Create CA certificate
|
68
|
+
cert_cmd = [
|
69
|
+
"openssl", "req", "-new", "-x509", "-days", "3650",
|
70
|
+
"-key", str(ca_key_path),
|
71
|
+
"-out", str(ca_cert_path),
|
72
|
+
"-subj", "/C=US/ST=Test State/L=Test City/O=Test Organization/CN=MCP Proxy Adapter Test CA"
|
73
|
+
]
|
74
|
+
return self.run_command(cert_cmd, "Creating CA certificate")
|
75
|
+
|
76
|
+
def create_server_certificate(self) -> bool:
|
77
|
+
"""Create server certificate using OpenSSL."""
|
78
|
+
server_cert_path = self.certs_dir / "server_cert.pem"
|
79
|
+
server_key_path = self.certs_dir / "server_key.pem"
|
80
|
+
|
81
|
+
if server_cert_path.exists() and server_key_path.exists():
|
82
|
+
print(f"ℹ️ Server certificate already exists: {server_cert_path}")
|
83
|
+
return True
|
84
|
+
|
85
|
+
# Create server private key
|
86
|
+
key_cmd = [
|
87
|
+
"openssl", "genrsa", "-out", str(server_key_path), "2048"
|
88
|
+
]
|
89
|
+
if not self.run_command(key_cmd, "Creating server private key"):
|
90
|
+
return False
|
91
|
+
|
92
|
+
# Create server certificate signing request
|
93
|
+
csr_path = self.certs_dir / "server.csr"
|
94
|
+
csr_cmd = [
|
95
|
+
"openssl", "req", "-new",
|
96
|
+
"-key", str(server_key_path),
|
97
|
+
"-out", str(csr_path),
|
98
|
+
"-subj", "/C=US/ST=Test State/L=Test City/O=Test Organization/CN=localhost"
|
99
|
+
]
|
100
|
+
if not self.run_command(csr_cmd, "Creating server CSR"):
|
101
|
+
return False
|
102
|
+
|
103
|
+
# Create server certificate
|
104
|
+
cert_cmd = [
|
105
|
+
"openssl", "x509", "-req", "-days", "730",
|
106
|
+
"-in", str(csr_path),
|
107
|
+
"-CA", str(self.certs_dir / "ca_cert.pem"),
|
108
|
+
"-CAkey", str(self.keys_dir / "ca_key.pem"),
|
109
|
+
"-CAcreateserial",
|
110
|
+
"-out", str(server_cert_path)
|
111
|
+
]
|
112
|
+
success = self.run_command(cert_cmd, "Creating server certificate")
|
113
|
+
|
114
|
+
# Clean up CSR
|
115
|
+
if csr_path.exists():
|
116
|
+
csr_path.unlink()
|
117
|
+
|
118
|
+
return success
|
119
|
+
|
120
|
+
def create_client_certificate(self, name: str, common_name: str) -> bool:
|
121
|
+
"""Create client certificate using OpenSSL."""
|
122
|
+
cert_path = self.certs_dir / f"{name}_cert.pem"
|
123
|
+
key_path = self.certs_dir / f"{name}_key.pem"
|
124
|
+
|
125
|
+
if cert_path.exists() and key_path.exists():
|
126
|
+
print(f"ℹ️ Client certificate {name} already exists: {cert_path}")
|
127
|
+
return True
|
128
|
+
|
129
|
+
# Create client private key
|
130
|
+
key_cmd = [
|
131
|
+
"openssl", "genrsa", "-out", str(key_path), "2048"
|
132
|
+
]
|
133
|
+
if not self.run_command(key_cmd, f"Creating {name} private key"):
|
134
|
+
return False
|
135
|
+
|
136
|
+
# Create client certificate signing request
|
137
|
+
csr_path = self.certs_dir / f"{name}.csr"
|
138
|
+
csr_cmd = [
|
139
|
+
"openssl", "req", "-new",
|
140
|
+
"-key", str(key_path),
|
141
|
+
"-out", str(csr_path),
|
142
|
+
"-subj", f"/C=US/ST=Test State/L=Test City/O=Test Organization/CN={common_name}"
|
143
|
+
]
|
144
|
+
if not self.run_command(csr_cmd, f"Creating {name} CSR"):
|
145
|
+
return False
|
146
|
+
|
147
|
+
# Create client certificate
|
148
|
+
cert_cmd = [
|
149
|
+
"openssl", "x509", "-req", "-days", "730",
|
150
|
+
"-in", str(csr_path),
|
151
|
+
"-CA", str(self.certs_dir / "ca_cert.pem"),
|
152
|
+
"-CAkey", str(self.keys_dir / "ca_key.pem"),
|
153
|
+
"-CAcreateserial",
|
154
|
+
"-out", str(cert_path)
|
155
|
+
]
|
156
|
+
success = self.run_command(cert_cmd, f"Creating {name} certificate")
|
157
|
+
|
158
|
+
# Clean up CSR
|
159
|
+
if csr_path.exists():
|
160
|
+
csr_path.unlink()
|
161
|
+
|
162
|
+
return success
|
163
|
+
|
164
|
+
def create_legacy_certificates(self) -> bool:
|
165
|
+
"""Create legacy certificate files for compatibility."""
|
166
|
+
legacy_files = [
|
167
|
+
("client.crt", "client.key", "client"),
|
168
|
+
("client_admin.crt", "client_admin.key", "admin"),
|
169
|
+
("admin.crt", "admin.key", "admin"),
|
170
|
+
("user.crt", "user.key", "user"),
|
171
|
+
("readonly.crt", "readonly.key", "readonly")
|
172
|
+
]
|
173
|
+
|
174
|
+
success = True
|
175
|
+
for cert_file, key_file, source_name in legacy_files:
|
176
|
+
cert_path = self.certs_dir / cert_file
|
177
|
+
key_path = self.certs_dir / key_file
|
178
|
+
|
179
|
+
if not cert_path.exists() or not key_path.exists():
|
180
|
+
source_cert = self.certs_dir / f"{source_name}_cert.pem"
|
181
|
+
source_key = self.certs_dir / f"{source_name}_key.pem"
|
182
|
+
|
183
|
+
if source_cert.exists() and source_key.exists():
|
184
|
+
self.run_command(["cp", str(source_cert), str(cert_path)], f"Creating {cert_file}")
|
185
|
+
self.run_command(["cp", str(source_key), str(key_path)], f"Creating {key_file}")
|
186
|
+
else:
|
187
|
+
print(f"⚠️ Source certificate {source_name} not found for {cert_file}")
|
188
|
+
success = False
|
189
|
+
|
190
|
+
return success
|
191
|
+
|
192
|
+
def validate_certificates(self) -> bool:
|
193
|
+
"""Validate all created certificates."""
|
194
|
+
print("\n🔍 Validating certificates...")
|
195
|
+
|
196
|
+
cert_files = [
|
197
|
+
"ca_cert.pem",
|
198
|
+
"server_cert.pem",
|
199
|
+
"admin_cert.pem",
|
200
|
+
"user_cert.pem",
|
201
|
+
"readonly_cert.pem",
|
202
|
+
"guest_cert.pem",
|
203
|
+
"proxy_cert.pem"
|
204
|
+
]
|
205
|
+
|
206
|
+
success = True
|
207
|
+
for cert_file in cert_files:
|
208
|
+
cert_path = self.certs_dir / cert_file
|
209
|
+
if cert_path.exists():
|
210
|
+
try:
|
211
|
+
result = subprocess.run(
|
212
|
+
["openssl", "x509", "-in", str(cert_path), "-text", "-noout"],
|
213
|
+
capture_output=True,
|
214
|
+
text=True,
|
215
|
+
check=True
|
216
|
+
)
|
217
|
+
print(f"✅ {cert_file}: Valid")
|
218
|
+
except subprocess.CalledProcessError:
|
219
|
+
print(f"❌ {cert_file}: Invalid")
|
220
|
+
success = False
|
221
|
+
else:
|
222
|
+
print(f"⚠️ {cert_file}: Not found")
|
223
|
+
|
224
|
+
return success
|
225
|
+
|
226
|
+
def create_all(self) -> bool:
|
227
|
+
"""Create all certificates."""
|
228
|
+
print("🔐 Creating All Certificates for Security Testing")
|
229
|
+
print("=" * 60)
|
230
|
+
|
231
|
+
success = True
|
232
|
+
|
233
|
+
# 1. Create CA certificate
|
234
|
+
if not self.create_ca_certificate():
|
235
|
+
success = False
|
236
|
+
print("❌ Cannot continue without CA certificate")
|
237
|
+
return False
|
238
|
+
|
239
|
+
# 2. Create server certificate
|
240
|
+
if not self.create_server_certificate():
|
241
|
+
success = False
|
242
|
+
|
243
|
+
# 3. Create client certificates
|
244
|
+
print("\n👥 Creating client certificates...")
|
245
|
+
client_certs = [
|
246
|
+
("admin", "admin-client"),
|
247
|
+
("user", "user-client"),
|
248
|
+
("readonly", "readonly-client"),
|
249
|
+
("guest", "guest-client"),
|
250
|
+
("proxy", "proxy-client")
|
251
|
+
]
|
252
|
+
|
253
|
+
for name, common_name in client_certs:
|
254
|
+
if not self.create_client_certificate(name, common_name):
|
255
|
+
success = False
|
256
|
+
|
257
|
+
# 4. Create legacy certificates
|
258
|
+
print("\n🔄 Creating legacy certificates...")
|
259
|
+
if not self.create_legacy_certificates():
|
260
|
+
success = False
|
261
|
+
|
262
|
+
# 5. Validate certificates
|
263
|
+
if not self.validate_certificates():
|
264
|
+
success = False
|
265
|
+
|
266
|
+
# Print summary
|
267
|
+
print("\n" + "=" * 60)
|
268
|
+
print("📊 CERTIFICATE CREATION SUMMARY")
|
269
|
+
print("=" * 60)
|
270
|
+
|
271
|
+
if success:
|
272
|
+
print("✅ All certificates created successfully!")
|
273
|
+
print(f"📁 Certificates directory: {self.certs_dir}")
|
274
|
+
print(f"🔑 Keys directory: {self.keys_dir}")
|
275
|
+
print("\n📋 Created certificates:")
|
276
|
+
|
277
|
+
cert_files = list(self.certs_dir.glob("*.pem")) + list(self.certs_dir.glob("*.crt"))
|
278
|
+
for cert_file in sorted(cert_files):
|
279
|
+
print(f" - {cert_file.name}")
|
280
|
+
|
281
|
+
key_files = list(self.keys_dir.glob("*.pem")) + list(self.keys_dir.glob("*.key"))
|
282
|
+
for key_file in sorted(key_files):
|
283
|
+
print(f" - {key_file.name}")
|
284
|
+
else:
|
285
|
+
print("❌ Some certificates failed to create")
|
286
|
+
print("Check the error messages above")
|
287
|
+
|
288
|
+
return success
|
289
|
+
|
290
|
+
|
291
|
+
def main():
|
292
|
+
"""Main function."""
|
293
|
+
creator = SimpleCertificateCreator()
|
294
|
+
|
295
|
+
try:
|
296
|
+
success = creator.create_all()
|
297
|
+
sys.exit(0 if success else 1)
|
298
|
+
except KeyboardInterrupt:
|
299
|
+
print("\n⚠️ Certificate creation interrupted by user")
|
300
|
+
sys.exit(1)
|
301
|
+
except Exception as e:
|
302
|
+
print(f"\n❌ Certificate creation failed: {e}")
|
303
|
+
sys.exit(1)
|
304
|
+
|
305
|
+
|
306
|
+
if __name__ == "__main__":
|
307
|
+
main()
|
@@ -0,0 +1,144 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Debug Request State - Проверка request.state
|
4
|
+
|
5
|
+
Этот скрипт проверяет, как middleware устанавливает информацию о пользователе в request.state.
|
6
|
+
|
7
|
+
Author: Vasiliy Zdanovskiy
|
8
|
+
email: vasilyvz@gmail.com
|
9
|
+
"""
|
10
|
+
|
11
|
+
import asyncio
|
12
|
+
import json
|
13
|
+
import sys
|
14
|
+
from pathlib import Path
|
15
|
+
|
16
|
+
# Add project root to path
|
17
|
+
project_root = Path(__file__).parent.parent.parent
|
18
|
+
sys.path.insert(0, str(project_root))
|
19
|
+
|
20
|
+
from fastapi import FastAPI, Request
|
21
|
+
from fastapi.testclient import TestClient
|
22
|
+
from mcp_proxy_adapter.api.app import create_app
|
23
|
+
|
24
|
+
|
25
|
+
async def debug_request_state():
|
26
|
+
"""Debug request state handling."""
|
27
|
+
|
28
|
+
print("🔍 ОТЛАДКА REQUEST.STATE")
|
29
|
+
print("=" * 50)
|
30
|
+
|
31
|
+
# Create test app with proper configuration
|
32
|
+
config_path = project_root / "mcp_proxy_adapter" / "examples" / "server_configs" / "config_http_token.json"
|
33
|
+
|
34
|
+
with open(config_path) as f:
|
35
|
+
config = json.load(f)
|
36
|
+
|
37
|
+
# Override global config for testing
|
38
|
+
import mcp_proxy_adapter.config
|
39
|
+
mcp_proxy_adapter.config.config = config
|
40
|
+
|
41
|
+
app = create_app(config)
|
42
|
+
client = TestClient(app)
|
43
|
+
|
44
|
+
print("📋 1. ТЕСТИРОВАНИЕ БЕЗ АУТЕНТИФИКАЦИИ")
|
45
|
+
print("-" * 30)
|
46
|
+
|
47
|
+
# Test without authentication
|
48
|
+
response = client.post("/cmd", json={
|
49
|
+
"jsonrpc": "2.0",
|
50
|
+
"method": "echo",
|
51
|
+
"params": {"message": "test"},
|
52
|
+
"id": 1
|
53
|
+
})
|
54
|
+
|
55
|
+
print(f"Status: {response.status_code}")
|
56
|
+
print(f"Response: {response.json()}")
|
57
|
+
|
58
|
+
print("\n📋 2. ТЕСТИРОВАНИЕ С ADMIN ТОКЕНОМ")
|
59
|
+
print("-" * 30)
|
60
|
+
|
61
|
+
# Test with admin token
|
62
|
+
response = client.post("/cmd",
|
63
|
+
json={
|
64
|
+
"jsonrpc": "2.0",
|
65
|
+
"method": "echo",
|
66
|
+
"params": {"message": "test"},
|
67
|
+
"id": 1
|
68
|
+
},
|
69
|
+
headers={"X-API-Key": "test-token-123"}
|
70
|
+
)
|
71
|
+
|
72
|
+
print(f"Status: {response.status_code}")
|
73
|
+
print(f"Response: {response.json()}")
|
74
|
+
|
75
|
+
print("\n📋 3. ТЕСТИРОВАНИЕ С USER ТОКЕНОМ")
|
76
|
+
print("-" * 30)
|
77
|
+
|
78
|
+
# Test with user token
|
79
|
+
response = client.post("/cmd",
|
80
|
+
json={
|
81
|
+
"jsonrpc": "2.0",
|
82
|
+
"method": "echo",
|
83
|
+
"params": {"message": "test"},
|
84
|
+
"id": 1
|
85
|
+
},
|
86
|
+
headers={"X-API-Key": "user-token-456"}
|
87
|
+
)
|
88
|
+
|
89
|
+
print(f"Status: {response.status_code}")
|
90
|
+
print(f"Response: {response.json()}")
|
91
|
+
|
92
|
+
print("\n📋 4. ТЕСТИРОВАНИЕ С READONLY ТОКЕНОМ")
|
93
|
+
print("-" * 30)
|
94
|
+
|
95
|
+
# Test with readonly token
|
96
|
+
response = client.post("/cmd",
|
97
|
+
json={
|
98
|
+
"jsonrpc": "2.0",
|
99
|
+
"method": "echo",
|
100
|
+
"params": {"message": "test"},
|
101
|
+
"id": 1
|
102
|
+
},
|
103
|
+
headers={"X-API-Key": "readonly-token-123"}
|
104
|
+
)
|
105
|
+
|
106
|
+
print(f"Status: {response.status_code}")
|
107
|
+
print(f"Response: {response.json()}")
|
108
|
+
|
109
|
+
print("\n📋 5. ТЕСТИРОВАНИЕ ROLE_TEST КОМАНДЫ")
|
110
|
+
print("-" * 30)
|
111
|
+
|
112
|
+
# Test role_test command with readonly token
|
113
|
+
response = client.post("/cmd",
|
114
|
+
json={
|
115
|
+
"jsonrpc": "2.0",
|
116
|
+
"method": "role_test",
|
117
|
+
"params": {"action": "write"},
|
118
|
+
"id": 1
|
119
|
+
},
|
120
|
+
headers={"X-API-Key": "readonly-token-123"}
|
121
|
+
)
|
122
|
+
|
123
|
+
print(f"Status: {response.status_code}")
|
124
|
+
print(f"Response: {response.json()}")
|
125
|
+
|
126
|
+
print("\n📋 6. АНАЛИЗ ПРОБЛЕМЫ")
|
127
|
+
print("-" * 30)
|
128
|
+
|
129
|
+
print("🔍 ПРОБЛЕМА: Readonly роль получает доступ к командам")
|
130
|
+
print("\n📋 ВОЗМОЖНЫЕ ПРИЧИНЫ:")
|
131
|
+
print("1. Framework middleware не устанавливает user info в request.state")
|
132
|
+
print("2. Нет проверки прав на уровне middleware")
|
133
|
+
print("3. Команды не проверяют права доступа")
|
134
|
+
print("4. Интеграция между middleware и командами не работает")
|
135
|
+
|
136
|
+
print("\n📋 РЕКОМЕНДАЦИИ:")
|
137
|
+
print("1. Добавить CommandPermissionMiddleware")
|
138
|
+
print("2. Убедиться, что framework middleware устанавливает user info")
|
139
|
+
print("3. Добавить проверку прав в команды")
|
140
|
+
print("4. Проверить интеграцию middleware")
|
141
|
+
|
142
|
+
|
143
|
+
if __name__ == "__main__":
|
144
|
+
asyncio.run(debug_request_state())
|