mcp-proxy-adapter 4.1.1__py3-none-any.whl → 6.1.0__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 +12 -0
- mcp_proxy_adapter/api/app.py +254 -33
- mcp_proxy_adapter/api/handlers.py +32 -6
- mcp_proxy_adapter/api/middleware/__init__.py +36 -30
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
- mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
- mcp_proxy_adapter/api/middleware/factory.py +243 -0
- mcp_proxy_adapter/api/middleware/logging.py +32 -6
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +135 -0
- mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
- mcp_proxy_adapter/api/middleware/unified_security.py +152 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +83 -0
- mcp_proxy_adapter/commands/__init__.py +19 -4
- mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
- mcp_proxy_adapter/commands/base.py +66 -32
- mcp_proxy_adapter/commands/builtin_commands.py +95 -0
- mcp_proxy_adapter/commands/catalog_manager.py +838 -0
- mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
- mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
- mcp_proxy_adapter/commands/command_registry.py +711 -354
- mcp_proxy_adapter/commands/dependency_manager.py +245 -0
- mcp_proxy_adapter/commands/echo_command.py +81 -0
- mcp_proxy_adapter/commands/health_command.py +7 -0
- mcp_proxy_adapter/commands/help_command.py +21 -14
- mcp_proxy_adapter/commands/hooks.py +200 -167
- mcp_proxy_adapter/commands/key_management_command.py +506 -0
- mcp_proxy_adapter/commands/load_command.py +176 -0
- mcp_proxy_adapter/commands/plugins_command.py +235 -0
- mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
- mcp_proxy_adapter/commands/proxy_registration_command.py +409 -0
- mcp_proxy_adapter/commands/reload_command.py +48 -50
- mcp_proxy_adapter/commands/result.py +1 -0
- mcp_proxy_adapter/commands/role_test_command.py +141 -0
- mcp_proxy_adapter/commands/roles_management_command.py +697 -0
- mcp_proxy_adapter/commands/security_command.py +488 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +483 -0
- mcp_proxy_adapter/commands/token_management_command.py +529 -0
- mcp_proxy_adapter/commands/transport_management_command.py +144 -0
- mcp_proxy_adapter/commands/unload_command.py +158 -0
- mcp_proxy_adapter/config.py +159 -2
- mcp_proxy_adapter/core/app_factory.py +326 -0
- mcp_proxy_adapter/core/auth_validator.py +606 -0
- mcp_proxy_adapter/core/certificate_utils.py +827 -0
- mcp_proxy_adapter/core/client_security.py +384 -0
- mcp_proxy_adapter/core/config_converter.py +405 -0
- mcp_proxy_adapter/core/config_validator.py +218 -0
- mcp_proxy_adapter/core/logging.py +19 -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 +235 -0
- mcp_proxy_adapter/core/proxy_client.py +602 -0
- mcp_proxy_adapter/core/proxy_registration.py +522 -0
- mcp_proxy_adapter/core/role_utils.py +426 -0
- mcp_proxy_adapter/core/security_adapter.py +370 -0
- mcp_proxy_adapter/core/security_factory.py +239 -0
- mcp_proxy_adapter/core/security_integration.py +277 -0
- mcp_proxy_adapter/core/server_adapter.py +345 -0
- mcp_proxy_adapter/core/server_engine.py +364 -0
- mcp_proxy_adapter/core/settings.py +1 -0
- mcp_proxy_adapter/core/ssl_utils.py +233 -0
- mcp_proxy_adapter/core/transport_manager.py +292 -0
- mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
- mcp_proxy_adapter/custom_openapi.py +22 -11
- 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/__pycache__/security_configurations.cpython-312.pyc +0 -0
- mcp_proxy_adapter/examples/__pycache__/security_test_client.cpython-312.pyc +0 -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 +39 -0
- mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +25 -0
- mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +39 -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_examples.py +344 -0
- mcp_proxy_adapter/examples/universal_client.py +628 -0
- mcp_proxy_adapter/main.py +186 -0
- mcp_proxy_adapter/utils/config_generator.py +639 -0
- mcp_proxy_adapter/version.py +2 -1
- mcp_proxy_adapter-6.1.0.dist-info/METADATA +205 -0
- mcp_proxy_adapter-6.1.0.dist-info/RECORD +193 -0
- mcp_proxy_adapter-6.1.0.dist-info/entry_points.txt +2 -0
- {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.1.0.dist-info}/licenses/LICENSE +2 -2
- mcp_proxy_adapter/api/middleware/auth.py +0 -146
- mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
- mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
- 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 -35
- mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
- mcp_proxy_adapter/examples/basic_server/server.py +0 -103
- 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 -250
- 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/config.json +0 -35
- 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/hooks.py +0 -230
- mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
- mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/server.py +0 -228
- mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
- 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/schemas/base_schema.json +0 -114
- mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
- 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 -217
- mcp_proxy_adapter-4.1.1.dist-info/METADATA +0 -200
- mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
- {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.1.0.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.1.0.dist-info}/top_level.txt +0 -0
@@ -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())
|
@@ -0,0 +1,205 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Debug Role Chain - Анализ цепочки блокировки ролей
|
4
|
+
|
5
|
+
Этот скрипт анализирует всю цепочку от аутентификации до блокировки доступа.
|
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 mcp_security_framework import SecurityManager, AuthManager, PermissionManager
|
21
|
+
from mcp_security_framework.schemas.config import SecurityConfig, AuthConfig, PermissionConfig
|
22
|
+
|
23
|
+
|
24
|
+
async def debug_role_chain():
|
25
|
+
"""Debug the complete role chain from authentication to blocking."""
|
26
|
+
|
27
|
+
print("🔍 АНАЛИЗ ЦЕПОЧКИ БЛОКИРОВКИ РОЛЕЙ")
|
28
|
+
print("=" * 60)
|
29
|
+
|
30
|
+
# Load configuration
|
31
|
+
config_path = project_root / "mcp_proxy_adapter" / "examples" / "server_configs" / "config_http_token.json"
|
32
|
+
|
33
|
+
with open(config_path) as f:
|
34
|
+
config = json.load(f)
|
35
|
+
|
36
|
+
security_config = config.get("security", {})
|
37
|
+
|
38
|
+
print("📋 1. КОНФИГУРАЦИЯ API КЛЮЧЕЙ")
|
39
|
+
print("-" * 30)
|
40
|
+
api_keys = security_config.get("auth", {}).get("api_keys", {})
|
41
|
+
for key, value in api_keys.items():
|
42
|
+
print(f" {key}: {value}")
|
43
|
+
|
44
|
+
print("\n📋 2. КОНФИГУРАЦИЯ РОЛЕЙ")
|
45
|
+
print("-" * 30)
|
46
|
+
roles_config = security_config.get("permissions", {}).get("roles", {})
|
47
|
+
for role, permissions in roles_config.items():
|
48
|
+
print(f" {role}: {permissions}")
|
49
|
+
|
50
|
+
print("\n📋 3. СОЗДАНИЕ КОМПОНЕНТОВ БЕЗОПАСНОСТИ")
|
51
|
+
print("-" * 30)
|
52
|
+
|
53
|
+
# Create permission config
|
54
|
+
perm_config = PermissionConfig(
|
55
|
+
roles_file=str(project_root / "mcp_proxy_adapter" / "examples" / "server_configs" / "roles.json"),
|
56
|
+
default_role="guest",
|
57
|
+
admin_role="admin",
|
58
|
+
role_hierarchy=security_config.get("permissions", {}).get("role_hierarchy", {}),
|
59
|
+
permission_cache_enabled=True,
|
60
|
+
permission_cache_ttl=300,
|
61
|
+
wildcard_permissions=False,
|
62
|
+
strict_mode=True,
|
63
|
+
roles=roles_config
|
64
|
+
)
|
65
|
+
|
66
|
+
# Create auth config
|
67
|
+
auth_config = AuthConfig(
|
68
|
+
enabled=security_config.get("auth", {}).get("enabled", True),
|
69
|
+
methods=security_config.get("auth", {}).get("methods", ["api_key"]),
|
70
|
+
api_keys=api_keys,
|
71
|
+
user_roles=security_config.get("auth", {}).get("user_roles", {}),
|
72
|
+
jwt_secret=security_config.get("auth", {}).get("jwt_secret"),
|
73
|
+
jwt_algorithm=security_config.get("auth", {}).get("jwt_algorithm", "HS256"),
|
74
|
+
jwt_expiry_hours=security_config.get("auth", {}).get("jwt_expiry_hours", 24),
|
75
|
+
certificate_auth=security_config.get("auth", {}).get("certificate_auth", False),
|
76
|
+
certificate_roles_oid=security_config.get("auth", {}).get("certificate_roles_oid"),
|
77
|
+
certificate_permissions_oid=security_config.get("auth", {}).get("certificate_permissions_oid"),
|
78
|
+
basic_auth=security_config.get("auth", {}).get("basic_auth", False),
|
79
|
+
oauth2_config=security_config.get("auth", {}).get("oauth2_config"),
|
80
|
+
public_paths=security_config.get("auth", {}).get("public_paths", [])
|
81
|
+
)
|
82
|
+
|
83
|
+
# Create security config
|
84
|
+
security_config_obj = SecurityConfig(
|
85
|
+
auth=auth_config,
|
86
|
+
permissions=perm_config
|
87
|
+
)
|
88
|
+
|
89
|
+
print("✅ Конфигурации созданы")
|
90
|
+
|
91
|
+
print("\n📋 4. ИНИЦИАЛИЗАЦИЯ МЕНЕДЖЕРОВ")
|
92
|
+
print("-" * 30)
|
93
|
+
|
94
|
+
# Initialize managers
|
95
|
+
permission_manager = PermissionManager(perm_config)
|
96
|
+
auth_manager = AuthManager(auth_config, permission_manager)
|
97
|
+
security_manager = SecurityManager(security_config_obj)
|
98
|
+
|
99
|
+
print("✅ Менеджеры инициализированы")
|
100
|
+
|
101
|
+
print("\n📋 5. ТЕСТИРОВАНИЕ АУТЕНТИФИКАЦИИ")
|
102
|
+
print("-" * 30)
|
103
|
+
|
104
|
+
# Test authentication with different tokens
|
105
|
+
test_tokens = {
|
106
|
+
"admin": "test-token-123",
|
107
|
+
"user": "user-token-456",
|
108
|
+
"readonly": "readonly-token-123",
|
109
|
+
"invalid": "invalid-token-999"
|
110
|
+
}
|
111
|
+
|
112
|
+
auth_results = {}
|
113
|
+
|
114
|
+
for role, token in test_tokens.items():
|
115
|
+
print(f"\n🔐 Тестирование токена для роли '{role}': {token}")
|
116
|
+
|
117
|
+
try:
|
118
|
+
result = auth_manager.authenticate_api_key(token)
|
119
|
+
auth_results[role] = result
|
120
|
+
|
121
|
+
print(f" ✅ Аутентификация: {'УСПЕШНА' if result.is_valid else 'НЕУДАЧНА'}")
|
122
|
+
if result.is_valid:
|
123
|
+
print(f" 👤 Пользователь: {result.username}")
|
124
|
+
print(f" 🏷️ Роли: {result.roles}")
|
125
|
+
print(f" 🔑 Метод: {result.auth_method}")
|
126
|
+
else:
|
127
|
+
print(f" ❌ Ошибка: {result.error_message}")
|
128
|
+
|
129
|
+
except Exception as e:
|
130
|
+
print(f" ❌ Исключение: {e}")
|
131
|
+
auth_results[role] = None
|
132
|
+
|
133
|
+
print("\n📋 6. ТЕСТИРОВАНИЕ ПРАВ ДОСТУПА")
|
134
|
+
print("-" * 30)
|
135
|
+
|
136
|
+
# Test permissions for different actions
|
137
|
+
test_actions = ["read", "write", "manage", "delete"]
|
138
|
+
|
139
|
+
for role, auth_result in auth_results.items():
|
140
|
+
if auth_result and auth_result.is_valid:
|
141
|
+
print(f"\n🔒 Тестирование прав для роли '{role}' (роли: {auth_result.roles})")
|
142
|
+
|
143
|
+
for action in test_actions:
|
144
|
+
try:
|
145
|
+
# Check permissions using permission manager
|
146
|
+
validation_result = permission_manager.validate_access(
|
147
|
+
auth_result.roles,
|
148
|
+
[action]
|
149
|
+
)
|
150
|
+
|
151
|
+
status = "✅ РАЗРЕШЕНО" if validation_result.is_valid else "❌ ЗАБЛОКИРОВАНО"
|
152
|
+
print(f" {action}: {status}")
|
153
|
+
|
154
|
+
if not validation_result.is_valid:
|
155
|
+
print(f" 📝 Причина: {validation_result.error_message}")
|
156
|
+
print(f" 🎯 Эффективные права: {validation_result.effective_permissions}")
|
157
|
+
print(f" ❌ Отсутствующие права: {validation_result.missing_permissions}")
|
158
|
+
|
159
|
+
except Exception as e:
|
160
|
+
print(f" {action}: ❌ ОШИБКА - {e}")
|
161
|
+
|
162
|
+
print("\n📋 7. ТЕСТИРОВАНИЕ ПОЛНОЙ ЦЕПОЧКИ")
|
163
|
+
print("-" * 30)
|
164
|
+
|
165
|
+
# Test complete request validation
|
166
|
+
for role, token in test_tokens.items():
|
167
|
+
print(f"\n🔄 Полная цепочка для роли '{role}'")
|
168
|
+
|
169
|
+
request_data = {
|
170
|
+
"api_key": token,
|
171
|
+
"required_permissions": ["write"],
|
172
|
+
"client_ip": "127.0.0.1"
|
173
|
+
}
|
174
|
+
|
175
|
+
try:
|
176
|
+
result = security_manager.validate_request(request_data)
|
177
|
+
|
178
|
+
status = "✅ УСПЕШНО" if result.is_valid else "❌ ЗАБЛОКИРОВАНО"
|
179
|
+
print(f" Результат: {status}")
|
180
|
+
|
181
|
+
if not result.is_valid:
|
182
|
+
print(f" 📝 Причина: {result.error_message}")
|
183
|
+
|
184
|
+
except Exception as e:
|
185
|
+
print(f" ❌ ОШИБКА: {e}")
|
186
|
+
|
187
|
+
print("\n📋 8. АНАЛИЗ ПРОБЛЕМЫ")
|
188
|
+
print("-" * 30)
|
189
|
+
|
190
|
+
print("🔍 ПРОБЛЕМА: Readonly роль получает доступ к write операциям")
|
191
|
+
print("\n📋 ВОЗМОЖНЫЕ ПРИЧИНЫ:")
|
192
|
+
print("1. Middleware не передает информацию о пользователе в request.state")
|
193
|
+
print("2. Framework middleware не блокирует доступ на уровне middleware")
|
194
|
+
print("3. Команда role_test не получает правильный контекст пользователя")
|
195
|
+
print("4. Интеграция между middleware и командами не работает")
|
196
|
+
|
197
|
+
print("\n📋 РЕКОМЕНДАЦИИ:")
|
198
|
+
print("1. Проверить, как framework middleware устанавливает user info")
|
199
|
+
print("2. Добавить проверку прав на уровне middleware")
|
200
|
+
print("3. Убедиться, что request.state содержит user info")
|
201
|
+
print("4. Проверить интеграцию между middleware и командами")
|
202
|
+
|
203
|
+
|
204
|
+
if __name__ == "__main__":
|
205
|
+
asyncio.run(debug_role_chain())
|