mcp-proxy-adapter 6.4.47__py3-none-any.whl → 6.6.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/api/handlers.py +58 -22
- mcp_proxy_adapter/api/middleware/unified_security.py +8 -12
- mcp_proxy_adapter/config.py +76 -117
- mcp_proxy_adapter/core/protocol_manager.py +25 -42
- mcp_proxy_adapter/core/security_integration.py +60 -97
- mcp_proxy_adapter/core/server_adapter.py +4 -0
- mcp_proxy_adapter/examples/config_builder.py +142 -428
- mcp_proxy_adapter/examples/config_builder_simple.py +271 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +186 -23
- mcp_proxy_adapter/examples/security_test_client.py +21 -7
- mcp_proxy_adapter/examples/test_config_builder.py +40 -0
- mcp_proxy_adapter/main.py +54 -27
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.4.47.dist-info → mcp_proxy_adapter-6.6.0.dist-info}/METADATA +1 -1
- {mcp_proxy_adapter-6.4.47.dist-info → mcp_proxy_adapter-6.6.0.dist-info}/RECORD +18 -17
- {mcp_proxy_adapter-6.4.47.dist-info → mcp_proxy_adapter-6.6.0.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.4.47.dist-info → mcp_proxy_adapter-6.6.0.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.4.47.dist-info → mcp_proxy_adapter-6.6.0.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@
|
|
2
2
|
Module with API request handlers.
|
3
3
|
"""
|
4
4
|
|
5
|
+
import asyncio
|
5
6
|
import json
|
6
7
|
import time
|
7
8
|
from typing import Any, Dict, List, Optional, Union
|
@@ -75,7 +76,16 @@ async def execute_command(
|
|
75
76
|
"permissions": getattr(request.state, "user_permissions", ["read"]),
|
76
77
|
}
|
77
78
|
|
78
|
-
|
79
|
+
# Add timeout to prevent hanging commands
|
80
|
+
try:
|
81
|
+
result = await asyncio.wait_for(
|
82
|
+
command_class.run(**params, context=context),
|
83
|
+
timeout=10.0 # 10 seconds timeout
|
84
|
+
)
|
85
|
+
except asyncio.TimeoutError:
|
86
|
+
execution_time = time.time() - start_time
|
87
|
+
log.error(f"⏰ Command '{command_name}' timed out after {execution_time:.3f} sec")
|
88
|
+
raise InternalError(f"Command execution timed out after 10 seconds")
|
79
89
|
|
80
90
|
execution_time = time.time() - start_time
|
81
91
|
|
@@ -136,7 +146,7 @@ async def handle_json_rpc(
|
|
136
146
|
request: Optional[Request] = None,
|
137
147
|
) -> Dict[str, Any]:
|
138
148
|
"""
|
139
|
-
Handles JSON-RPC request.
|
149
|
+
Handles JSON-RPC request with support for both standard JSON-RPC and simplified formats.
|
140
150
|
|
141
151
|
Args:
|
142
152
|
request_data: JSON-RPC request data.
|
@@ -148,40 +158,66 @@ async def handle_json_rpc(
|
|
148
158
|
# Create request logger if request_id is provided
|
149
159
|
log = RequestLogger(__name__, request_id) if request_id else logger
|
150
160
|
|
151
|
-
#
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
)
|
161
|
+
# Support both standard JSON-RPC and simplified formats
|
162
|
+
method = None
|
163
|
+
params = {}
|
164
|
+
json_rpc_id = None
|
165
|
+
|
166
|
+
# Check if it's a standard JSON-RPC request
|
167
|
+
if "jsonrpc" in request_data:
|
168
|
+
# Standard JSON-RPC format
|
169
|
+
if request_data.get("jsonrpc") != "2.0":
|
170
|
+
return _create_error_response(
|
171
|
+
InvalidRequestError("Invalid Request. Expected jsonrpc: 2.0"),
|
172
|
+
request_data.get("id"),
|
173
|
+
)
|
174
|
+
|
175
|
+
method = request_data.get("method")
|
176
|
+
params = request_data.get("params", {})
|
177
|
+
json_rpc_id = request_data.get("id")
|
178
|
+
|
179
|
+
if not method:
|
180
|
+
return _create_error_response(
|
181
|
+
InvalidRequestError("Invalid Request. Method is required"), json_rpc_id
|
182
|
+
)
|
183
|
+
else:
|
184
|
+
# Simplified format: {"command": "help"} or {"command": "echo", "params": {...}}
|
185
|
+
method = request_data.get("command")
|
186
|
+
params = request_data.get("params", {})
|
187
|
+
json_rpc_id = request_data.get("id", 1) # Default ID for simplified format
|
188
|
+
|
189
|
+
if not method:
|
190
|
+
return _create_error_response(
|
191
|
+
InvalidRequestError("Invalid Request. Command is required"), json_rpc_id
|
192
|
+
)
|
193
|
+
|
194
|
+
log.info(f"Using simplified format for command: {method}")
|
167
195
|
|
168
196
|
log.info(f"Executing JSON-RPC method: {method}")
|
169
197
|
|
170
198
|
try:
|
171
|
-
# Execute command
|
199
|
+
# Execute command with detailed logging
|
200
|
+
log.info(f"🔍 Starting command execution: {method}")
|
201
|
+
log.debug(f"📋 Command params: {params}")
|
202
|
+
|
172
203
|
result = await execute_command(method, params, request_id, request)
|
173
204
|
|
205
|
+
log.info(f"✅ Command {method} completed successfully")
|
206
|
+
|
174
207
|
# Form successful response
|
175
208
|
return {"jsonrpc": "2.0", "result": result, "id": json_rpc_id}
|
176
209
|
except MicroserviceError as e:
|
177
210
|
# Method execution error
|
178
|
-
log.error(f"Method execution error: {str(e)}")
|
211
|
+
log.error(f"❌ Method execution error: {str(e)}")
|
212
|
+
log.error(f"📊 Error type: {type(e).__name__}")
|
179
213
|
return _create_error_response(e, json_rpc_id)
|
180
214
|
except Exception as e:
|
181
215
|
# Internal server error
|
182
|
-
log.exception(f"Unhandled error in JSON-RPC handler: {e}")
|
216
|
+
log.exception(f"❌ Unhandled error in JSON-RPC handler: {e}")
|
217
|
+
log.error(f"📊 Exception type: {type(e).__name__}")
|
218
|
+
log.error(f"📊 Exception details: {repr(e)}")
|
183
219
|
return _create_error_response(
|
184
|
-
InternalError("Internal error", data={"error": str(e)}), json_rpc_id
|
220
|
+
InternalError("Internal error", data={"error": str(e), "error_type": type(e).__name__}), json_rpc_id
|
185
221
|
)
|
186
222
|
|
187
223
|
|
@@ -65,11 +65,10 @@ class UnifiedSecurityMiddleware(BaseHTTPMiddleware):
|
|
65
65
|
try:
|
66
66
|
security_config = config.get("security", {})
|
67
67
|
|
68
|
-
# Check if
|
69
|
-
|
70
|
-
permissions_enabled = permissions_config.get("enabled", False)
|
68
|
+
# Check if security is enabled - use mcp_security_framework if needed
|
69
|
+
security_enabled = security_config.get("enabled", False)
|
71
70
|
|
72
|
-
if
|
71
|
+
if security_enabled:
|
73
72
|
self.security_integration = create_security_integration(security_config)
|
74
73
|
# Use framework's FastAPI middleware
|
75
74
|
self.framework_middleware = (
|
@@ -80,7 +79,7 @@ class UnifiedSecurityMiddleware(BaseHTTPMiddleware):
|
|
80
79
|
# Instead, store the framework middleware for use in dispatch method.
|
81
80
|
logger.info("Framework middleware will be used in dispatch method")
|
82
81
|
else:
|
83
|
-
logger.info("
|
82
|
+
logger.info("Security disabled, skipping mcp_security_framework integration")
|
84
83
|
self.security_integration = None
|
85
84
|
self.framework_middleware = None
|
86
85
|
except Exception as e:
|
@@ -114,16 +113,13 @@ class UnifiedSecurityMiddleware(BaseHTTPMiddleware):
|
|
114
113
|
security_cfg = (
|
115
114
|
self.config.get("security", {}) if isinstance(self.config, dict) else {}
|
116
115
|
)
|
117
|
-
|
118
|
-
|
119
|
-
public_paths = set(
|
120
|
-
auth_cfg.get("public_paths", ["/health", "/docs", "/openapi.json"])
|
121
|
-
)
|
116
|
+
# Use new simplified structure
|
117
|
+
public_paths = set(["/health", "/docs", "/openapi.json"])
|
122
118
|
# JSON-RPC endpoint must not be public when API key is required
|
123
119
|
public_paths.discard("/api/jsonrpc")
|
124
120
|
path = request.url.path
|
125
|
-
methods = set(
|
126
|
-
api_keys: Dict[str, str] =
|
121
|
+
methods = set(["api_key"]) # Use token-based authentication
|
122
|
+
api_keys: Dict[str, str] = security_cfg.get("tokens", {}) or {}
|
127
123
|
|
128
124
|
# Enforce only for non-public paths when api_key method configured
|
129
125
|
if (
|
mcp_proxy_adapter/config.py
CHANGED
@@ -6,9 +6,12 @@ email: vasilyvz@gmail.com
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
import json
|
9
|
+
import logging
|
9
10
|
import os
|
10
11
|
from typing import Any, Dict, Optional, List
|
11
12
|
|
13
|
+
logger = logging.getLogger(__name__)
|
14
|
+
|
12
15
|
|
13
16
|
class Config:
|
14
17
|
"""
|
@@ -38,6 +41,7 @@ class Config:
|
|
38
41
|
"server": {
|
39
42
|
"host": "0.0.0.0",
|
40
43
|
"port": 8000,
|
44
|
+
"protocol": "http",
|
41
45
|
"debug": False,
|
42
46
|
"log_level": "INFO",
|
43
47
|
},
|
@@ -65,30 +69,6 @@ class Config:
|
|
65
69
|
"disabled_commands": [],
|
66
70
|
"custom_commands_path": "./commands",
|
67
71
|
},
|
68
|
-
"ssl": {
|
69
|
-
"enabled": False,
|
70
|
-
"mode": "https_only",
|
71
|
-
"cert_file": None,
|
72
|
-
"key_file": None,
|
73
|
-
"ca_cert": None,
|
74
|
-
"verify_client": False,
|
75
|
-
"client_cert_required": False,
|
76
|
-
"cipher_suites": [
|
77
|
-
"TLS_AES_256_GCM_SHA384",
|
78
|
-
"TLS_CHACHA20_POLY1305_SHA256",
|
79
|
-
],
|
80
|
-
"min_tls_version": "TLSv1.2",
|
81
|
-
"max_tls_version": "1.3",
|
82
|
-
"token_auth": {
|
83
|
-
"enabled": False,
|
84
|
-
"header_name": "Authorization",
|
85
|
-
"token_prefix": "Bearer",
|
86
|
-
"tokens_file": "tokens.json",
|
87
|
-
"token_expiry": 3600,
|
88
|
-
"jwt_secret": "",
|
89
|
-
"jwt_algorithm": "HS256",
|
90
|
-
},
|
91
|
-
},
|
92
72
|
"roles": {
|
93
73
|
"enabled": False,
|
94
74
|
"config_file": None,
|
@@ -111,6 +91,7 @@ class Config:
|
|
111
91
|
"ca_cert": None,
|
112
92
|
"verify_client": False,
|
113
93
|
"client_cert_required": False,
|
94
|
+
"chk_hostname": False, # Default to False when SSL is disabled
|
114
95
|
},
|
115
96
|
},
|
116
97
|
"proxy_registration": {
|
@@ -128,102 +109,18 @@ class Config:
|
|
128
109
|
},
|
129
110
|
"debug": {"enabled": False, "level": "WARNING"},
|
130
111
|
"security": {
|
131
|
-
"framework": "mcp_security_framework",
|
132
112
|
"enabled": False,
|
133
|
-
"
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
"enabled": False,
|
138
|
-
"methods": ["api_key"],
|
139
|
-
"api_keys": {},
|
140
|
-
"user_roles": {},
|
141
|
-
"jwt_secret": "",
|
142
|
-
"jwt_algorithm": "HS256",
|
143
|
-
"jwt_expiry_hours": 24,
|
144
|
-
"certificate_auth": False,
|
145
|
-
"certificate_roles_oid": "1.3.6.1.4.1.99999.1.1",
|
146
|
-
"certificate_permissions_oid": "1.3.6.1.4.1.99999.1.2",
|
147
|
-
"basic_auth": False,
|
148
|
-
"oauth2_config": None,
|
149
|
-
"public_paths": ["/health", "/docs", "/openapi.json"],
|
150
|
-
"security_headers": None,
|
113
|
+
"tokens": {
|
114
|
+
"admin": "admin-secret-key",
|
115
|
+
"user": "user-secret-key",
|
116
|
+
"readonly": "readonly-secret-key"
|
151
117
|
},
|
152
|
-
"
|
153
|
-
"
|
154
|
-
"
|
155
|
-
"
|
156
|
-
"ca_cert_file": None,
|
157
|
-
"client_cert_file": None,
|
158
|
-
"client_key_file": None,
|
159
|
-
"verify_mode": "CERT_NONE",
|
160
|
-
"min_tls_version": "TLSv1.2",
|
161
|
-
"max_tls_version": None,
|
162
|
-
"cipher_suite": None,
|
163
|
-
"check_hostname": True,
|
164
|
-
"check_expiry": True,
|
165
|
-
"expiry_warning_days": 30,
|
166
|
-
},
|
167
|
-
"certificates": {
|
168
|
-
"enabled": False,
|
169
|
-
"ca_cert_path": None,
|
170
|
-
"ca_key_path": None,
|
171
|
-
"cert_storage_path": "./certs",
|
172
|
-
"key_storage_path": "./keys",
|
173
|
-
"default_validity_days": 365,
|
174
|
-
"key_size": 2048,
|
175
|
-
"hash_algorithm": "sha256",
|
176
|
-
"crl_enabled": False,
|
177
|
-
"crl_path": None,
|
178
|
-
"crl_url": None,
|
179
|
-
"crl_validity_days": 30,
|
180
|
-
"auto_renewal": False,
|
181
|
-
"renewal_threshold_days": 30,
|
118
|
+
"roles": {
|
119
|
+
"admin": ["read", "write", "delete", "admin"],
|
120
|
+
"user": ["read", "write"],
|
121
|
+
"readonly": ["read"]
|
182
122
|
},
|
183
|
-
"
|
184
|
-
"enabled": False,
|
185
|
-
"roles_file": None,
|
186
|
-
"default_role": "guest",
|
187
|
-
"admin_role": "admin",
|
188
|
-
"role_hierarchy": {},
|
189
|
-
"permission_cache_enabled": False,
|
190
|
-
"permission_cache_ttl": 300,
|
191
|
-
"wildcard_permissions": False,
|
192
|
-
"strict_mode": False,
|
193
|
-
"roles": None,
|
194
|
-
},
|
195
|
-
"rate_limit": {
|
196
|
-
"enabled": False,
|
197
|
-
"default_requests_per_minute": 60,
|
198
|
-
"default_requests_per_hour": 1000,
|
199
|
-
"burst_limit": 2,
|
200
|
-
"window_size_seconds": 60,
|
201
|
-
"storage_backend": "memory",
|
202
|
-
"redis_config": None,
|
203
|
-
"cleanup_interval": 300,
|
204
|
-
"exempt_paths": ["/health", "/docs", "/openapi.json"],
|
205
|
-
"exempt_roles": ["admin"],
|
206
|
-
},
|
207
|
-
"logging": {
|
208
|
-
"enabled": True,
|
209
|
-
"level": "INFO",
|
210
|
-
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
211
|
-
"date_format": "%Y-%m-%d %H:%M:%S",
|
212
|
-
"file_path": None,
|
213
|
-
"max_file_size": 10,
|
214
|
-
"backup_count": 5,
|
215
|
-
"console_output": True,
|
216
|
-
"json_format": False,
|
217
|
-
"include_timestamp": True,
|
218
|
-
"include_level": True,
|
219
|
-
"include_module": True,
|
220
|
-
},
|
221
|
-
},
|
222
|
-
"protocols": {
|
223
|
-
"enabled": True,
|
224
|
-
"allowed_protocols": ["http", "jsonrpc"],
|
225
|
-
"default_protocol": "http",
|
226
|
-
"auto_discovery": True,
|
123
|
+
"roles_file": None
|
227
124
|
},
|
228
125
|
}
|
229
126
|
|
@@ -238,6 +135,10 @@ class Config:
|
|
238
135
|
|
239
136
|
# Load configuration from environment variables
|
240
137
|
self._load_env_variables()
|
138
|
+
|
139
|
+
# Apply hostname check logic based on SSL configuration
|
140
|
+
self._validate_security_config()
|
141
|
+
self._apply_hostname_check_logic()
|
241
142
|
|
242
143
|
def load_from_file(self, config_path: str) -> None:
|
243
144
|
"""
|
@@ -344,6 +245,12 @@ class Config:
|
|
344
245
|
current = current[part]
|
345
246
|
|
346
247
|
current[parts[-1]] = value
|
248
|
+
|
249
|
+
# Special handling for chk_hostname - mark it as user-set
|
250
|
+
if key == "transport.ssl.chk_hostname":
|
251
|
+
if "ssl" not in self.config_data.get("transport", {}):
|
252
|
+
self.config_data["transport"]["ssl"] = {}
|
253
|
+
self.config_data["transport"]["ssl"]["_chk_hostname_user_set"] = True
|
347
254
|
|
348
255
|
def save(self, path: Optional[str] = None) -> None:
|
349
256
|
"""
|
@@ -588,6 +495,58 @@ class Config:
|
|
588
495
|
|
589
496
|
return secure_config
|
590
497
|
|
498
|
+
def _validate_security_config(self) -> None:
|
499
|
+
"""
|
500
|
+
Validate security configuration and log warnings for incomplete setup.
|
501
|
+
"""
|
502
|
+
if not self.get("security.enabled", False):
|
503
|
+
return
|
504
|
+
|
505
|
+
# Check if security is enabled but no authentication methods are configured
|
506
|
+
tokens = self.get("security.tokens", {})
|
507
|
+
roles = self.get("security.roles", {})
|
508
|
+
roles_file = self.get("security.roles_file")
|
509
|
+
|
510
|
+
has_tokens = bool(tokens and any(tokens.values()))
|
511
|
+
has_roles = bool(roles and any(roles.values()))
|
512
|
+
has_roles_file = bool(roles_file and os.path.exists(roles_file))
|
513
|
+
|
514
|
+
if not (has_tokens or has_roles or has_roles_file):
|
515
|
+
logger.warning(
|
516
|
+
"Security is enabled but no authentication methods are configured. "
|
517
|
+
"Please configure tokens, roles, or roles_file in the security section."
|
518
|
+
)
|
519
|
+
|
520
|
+
def _apply_hostname_check_logic(self) -> None:
|
521
|
+
"""
|
522
|
+
Apply hostname check logic based on protocol configuration.
|
523
|
+
chk_hostname should be True for HTTPS/mTLS protocols, False for HTTP.
|
524
|
+
Only set default values if chk_hostname is not explicitly configured.
|
525
|
+
"""
|
526
|
+
protocol = self.get("server.protocol", "http")
|
527
|
+
ssl_enabled = self.get("transport.ssl.enabled", False)
|
528
|
+
|
529
|
+
# Check if chk_hostname is explicitly set by the user
|
530
|
+
# We check if it was set by looking for a special flag
|
531
|
+
transport_section = self.config_data.get("transport", {})
|
532
|
+
ssl_section = transport_section.get("ssl", {})
|
533
|
+
chk_hostname_explicitly_set = ssl_section.get("_chk_hostname_user_set", False)
|
534
|
+
|
535
|
+
# Set chk_hostname based on protocol only if not explicitly set
|
536
|
+
if not chk_hostname_explicitly_set:
|
537
|
+
if protocol in ["https", "mtls"]:
|
538
|
+
# For HTTPS/mTLS, enable hostname checking by default
|
539
|
+
self.set("transport.ssl.chk_hostname", True)
|
540
|
+
logger.debug(f"Set chk_hostname=True for protocol {protocol} (default)")
|
541
|
+
else:
|
542
|
+
# For HTTP, disable hostname checking
|
543
|
+
self.set("transport.ssl.chk_hostname", False)
|
544
|
+
logger.debug(f"Set chk_hostname=False for protocol {protocol} (default)")
|
545
|
+
else:
|
546
|
+
# Log the explicitly set value
|
547
|
+
chk_hostname_value = self.get("transport.ssl.chk_hostname")
|
548
|
+
logger.debug(f"Using explicitly set chk_hostname={chk_hostname_value} for protocol {protocol}")
|
549
|
+
|
591
550
|
|
592
551
|
# Singleton instance
|
593
552
|
config = Config()
|
@@ -56,54 +56,37 @@ class ProtocolManager:
|
|
56
56
|
f"ProtocolManager._load_config - current_config keys: {list(current_config.keys()) if hasattr(current_config, 'keys') else 'no keys'}"
|
57
57
|
)
|
58
58
|
|
59
|
-
# Get
|
60
|
-
logger.debug(f"ProtocolManager._load_config - before getting
|
59
|
+
# Get server protocol configuration (new simplified structure)
|
60
|
+
logger.debug(f"ProtocolManager._load_config - before getting server protocol")
|
61
61
|
try:
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
62
|
+
server_config = current_config.get("server", {})
|
63
|
+
server_protocol = server_config.get("protocol", "http")
|
64
|
+
logger.debug(f"ProtocolManager._load_config - server protocol: {server_protocol}")
|
65
|
+
|
66
|
+
# Set allowed protocols based on server protocol
|
67
|
+
if server_protocol == "http":
|
68
|
+
self.allowed_protocols = ["http"]
|
69
|
+
elif server_protocol == "https":
|
70
|
+
self.allowed_protocols = ["https"]
|
71
|
+
elif server_protocol == "mtls":
|
72
|
+
self.allowed_protocols = ["mtls", "https"] # mTLS also supports HTTPS
|
70
73
|
else:
|
71
|
-
|
72
|
-
|
73
|
-
)
|
74
|
+
# Fallback to HTTP
|
75
|
+
self.allowed_protocols = ["http"]
|
76
|
+
logger.warning(f"Unknown server protocol '{server_protocol}', defaulting to HTTP")
|
77
|
+
|
78
|
+
logger.debug(f"ProtocolManager._load_config - allowed protocols: {self.allowed_protocols}")
|
79
|
+
|
74
80
|
except Exception as e:
|
75
|
-
logger.debug(f"ProtocolManager._load_config - ERROR getting
|
76
|
-
|
81
|
+
logger.debug(f"ProtocolManager._load_config - ERROR getting server protocol: {e}")
|
82
|
+
# Fallback to HTTP
|
83
|
+
self.allowed_protocols = ["http"]
|
77
84
|
|
78
|
-
|
79
|
-
|
80
|
-
if hasattr(self.protocols_config, "get")
|
81
|
-
else True
|
82
|
-
)
|
83
|
-
|
84
|
-
# Get SSL configuration to determine allowed protocols
|
85
|
-
ssl_enabled = self._is_ssl_enabled(current_config)
|
86
|
-
|
87
|
-
# Set allowed protocols based on SSL configuration
|
88
|
-
if ssl_enabled:
|
89
|
-
# If SSL is enabled, allow both HTTP and HTTPS
|
90
|
-
self.allowed_protocols = self.protocols_config.get(
|
91
|
-
"allowed_protocols", ["http", "https"]
|
92
|
-
)
|
93
|
-
# Ensure HTTPS is in allowed protocols if SSL is enabled
|
94
|
-
if "https" not in self.allowed_protocols:
|
95
|
-
self.allowed_protocols.append("https")
|
96
|
-
else:
|
97
|
-
# If SSL is disabled, only allow HTTP
|
98
|
-
self.allowed_protocols = self.protocols_config.get(
|
99
|
-
"allowed_protocols", ["http"]
|
100
|
-
)
|
101
|
-
# Remove HTTPS from allowed protocols if SSL is disabled
|
102
|
-
if "https" in self.allowed_protocols:
|
103
|
-
self.allowed_protocols.remove("https")
|
85
|
+
# Protocol management is always enabled in new structure
|
86
|
+
self.enabled = True
|
104
87
|
|
105
88
|
logger.debug(
|
106
|
-
f"Protocol manager loaded config: enabled={self.enabled}, allowed_protocols={self.allowed_protocols}
|
89
|
+
f"Protocol manager loaded config: enabled={self.enabled}, allowed_protocols={self.allowed_protocols}"
|
107
90
|
)
|
108
91
|
|
109
92
|
def _is_ssl_enabled(self, current_config: Dict) -> bool:
|