mcp-proxy-adapter 4.1.1__py3-none-any.whl → 6.0.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.
Files changed (101) hide show
  1. mcp_proxy_adapter/__main__.py +12 -0
  2. mcp_proxy_adapter/api/app.py +138 -11
  3. mcp_proxy_adapter/api/handlers.py +16 -1
  4. mcp_proxy_adapter/api/middleware/__init__.py +30 -29
  5. mcp_proxy_adapter/api/middleware/auth_adapter.py +235 -0
  6. mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
  7. mcp_proxy_adapter/api/middleware/factory.py +219 -0
  8. mcp_proxy_adapter/api/middleware/logging.py +32 -6
  9. mcp_proxy_adapter/api/middleware/mtls_adapter.py +305 -0
  10. mcp_proxy_adapter/api/middleware/mtls_middleware.py +296 -0
  11. mcp_proxy_adapter/api/middleware/protocol_middleware.py +135 -0
  12. mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +241 -0
  13. mcp_proxy_adapter/api/middleware/roles_adapter.py +365 -0
  14. mcp_proxy_adapter/api/middleware/roles_middleware.py +381 -0
  15. mcp_proxy_adapter/api/middleware/security.py +376 -0
  16. mcp_proxy_adapter/api/middleware/token_auth_middleware.py +261 -0
  17. mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
  18. mcp_proxy_adapter/commands/__init__.py +13 -4
  19. mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
  20. mcp_proxy_adapter/commands/base.py +61 -30
  21. mcp_proxy_adapter/commands/builtin_commands.py +89 -0
  22. mcp_proxy_adapter/commands/catalog_manager.py +838 -0
  23. mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
  24. mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
  25. mcp_proxy_adapter/commands/command_registry.py +703 -354
  26. mcp_proxy_adapter/commands/dependency_manager.py +245 -0
  27. mcp_proxy_adapter/commands/health_command.py +7 -0
  28. mcp_proxy_adapter/commands/hooks.py +200 -167
  29. mcp_proxy_adapter/commands/key_management_command.py +506 -0
  30. mcp_proxy_adapter/commands/load_command.py +176 -0
  31. mcp_proxy_adapter/commands/plugins_command.py +235 -0
  32. mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
  33. mcp_proxy_adapter/commands/proxy_registration_command.py +268 -0
  34. mcp_proxy_adapter/commands/reload_command.py +48 -50
  35. mcp_proxy_adapter/commands/result.py +1 -0
  36. mcp_proxy_adapter/commands/roles_management_command.py +697 -0
  37. mcp_proxy_adapter/commands/ssl_setup_command.py +483 -0
  38. mcp_proxy_adapter/commands/token_management_command.py +529 -0
  39. mcp_proxy_adapter/commands/transport_management_command.py +144 -0
  40. mcp_proxy_adapter/commands/unload_command.py +158 -0
  41. mcp_proxy_adapter/config.py +99 -2
  42. mcp_proxy_adapter/core/auth_validator.py +606 -0
  43. mcp_proxy_adapter/core/certificate_utils.py +827 -0
  44. mcp_proxy_adapter/core/config_converter.py +405 -0
  45. mcp_proxy_adapter/core/config_validator.py +218 -0
  46. mcp_proxy_adapter/core/logging.py +11 -0
  47. mcp_proxy_adapter/core/protocol_manager.py +226 -0
  48. mcp_proxy_adapter/core/proxy_registration.py +270 -0
  49. mcp_proxy_adapter/core/role_utils.py +426 -0
  50. mcp_proxy_adapter/core/security_adapter.py +373 -0
  51. mcp_proxy_adapter/core/security_factory.py +239 -0
  52. mcp_proxy_adapter/core/settings.py +1 -0
  53. mcp_proxy_adapter/core/ssl_utils.py +233 -0
  54. mcp_proxy_adapter/core/transport_manager.py +292 -0
  55. mcp_proxy_adapter/custom_openapi.py +22 -11
  56. mcp_proxy_adapter/examples/basic_server/config.json +58 -23
  57. mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +54 -0
  58. mcp_proxy_adapter/examples/basic_server/config_http.json +70 -0
  59. mcp_proxy_adapter/examples/basic_server/config_http_only.json +52 -0
  60. mcp_proxy_adapter/examples/basic_server/config_https.json +58 -0
  61. mcp_proxy_adapter/examples/basic_server/config_mtls.json +58 -0
  62. mcp_proxy_adapter/examples/basic_server/config_ssl.json +46 -0
  63. mcp_proxy_adapter/examples/basic_server/server.py +12 -1
  64. mcp_proxy_adapter/examples/custom_commands/__init__.py +1 -1
  65. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +339 -23
  66. mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +105 -0
  67. mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +129 -0
  68. mcp_proxy_adapter/examples/custom_commands/config.json +101 -18
  69. mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +46 -0
  70. mcp_proxy_adapter/examples/custom_commands/config_https_only.json +46 -0
  71. mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +33 -0
  72. mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +46 -0
  73. mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +33 -0
  74. mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +33 -0
  75. mcp_proxy_adapter/examples/custom_commands/full_help_response.json +1 -0
  76. mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +629 -0
  77. mcp_proxy_adapter/examples/custom_commands/get_openapi.py +103 -0
  78. mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +129 -0
  79. mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +278 -0
  80. mcp_proxy_adapter/examples/custom_commands/server.py +92 -68
  81. mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +75 -0
  82. mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +299 -0
  83. mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +278 -0
  84. mcp_proxy_adapter/examples/custom_commands/test_openapi.py +27 -0
  85. mcp_proxy_adapter/examples/custom_commands/test_registry.py +23 -0
  86. mcp_proxy_adapter/examples/custom_commands/test_simple.py +19 -0
  87. mcp_proxy_adapter/examples/custom_project_example/README.md +103 -0
  88. mcp_proxy_adapter/examples/custom_project_example/README_EN.md +103 -0
  89. mcp_proxy_adapter/examples/simple_custom_commands/README.md +149 -0
  90. mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +149 -0
  91. mcp_proxy_adapter/main.py +175 -0
  92. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  93. mcp_proxy_adapter/tests/unit/test_config.py +53 -0
  94. mcp_proxy_adapter/version.py +1 -1
  95. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/METADATA +2 -1
  96. mcp_proxy_adapter-6.0.0.dist-info/RECORD +179 -0
  97. mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
  98. mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
  99. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/WHEEL +0 -0
  100. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/licenses/LICENSE +0 -0
  101. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,483 @@
1
+ """
2
+ SSL Setup Command
3
+
4
+ This module provides commands for SSL configuration and management including
5
+ setup, status checking, testing, and configuration management.
6
+
7
+ Author: MCP Proxy Adapter Team
8
+ Version: 1.0.0
9
+ """
10
+
11
+ import logging
12
+ import os
13
+ import ssl
14
+ from typing import Dict, List, Optional, Any
15
+ from pathlib import Path
16
+
17
+ from .base import Command
18
+ from .result import CommandResult, SuccessResult, ErrorResult
19
+ from ..core.certificate_utils import CertificateUtils
20
+ from ..core.auth_validator import AuthValidator
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ class SSLSetupResult:
26
+ """
27
+ Result class for SSL setup operations.
28
+
29
+ Contains SSL configuration status and details.
30
+ """
31
+
32
+ def __init__(self, ssl_enabled: bool, cert_path: Optional[str] = None,
33
+ key_path: Optional[str] = None, config: Optional[Dict] = None,
34
+ status: str = "unknown", error: Optional[str] = None):
35
+ """
36
+ Initialize SSL setup result.
37
+
38
+ Args:
39
+ ssl_enabled: Whether SSL is enabled
40
+ cert_path: Path to certificate file
41
+ key_path: Path to private key file
42
+ config: SSL configuration
43
+ status: SSL status (enabled, disabled, error)
44
+ error: Error message if any
45
+ """
46
+ self.ssl_enabled = ssl_enabled
47
+ self.cert_path = cert_path
48
+ self.key_path = key_path
49
+ self.config = config or {}
50
+ self.status = status
51
+ self.error = error
52
+
53
+ def to_dict(self) -> Dict[str, Any]:
54
+ """
55
+ Convert to dictionary format.
56
+
57
+ Returns:
58
+ Dictionary representation
59
+ """
60
+ return {
61
+ "ssl_enabled": self.ssl_enabled,
62
+ "cert_path": self.cert_path,
63
+ "key_path": self.key_path,
64
+ "config": self.config,
65
+ "status": self.status,
66
+ "error": self.error
67
+ }
68
+
69
+ def get_schema(self) -> Dict[str, Any]:
70
+ """
71
+ Get JSON schema for this result.
72
+
73
+ Returns:
74
+ JSON schema dictionary
75
+ """
76
+ return {
77
+ "type": "object",
78
+ "properties": {
79
+ "ssl_enabled": {"type": "boolean", "description": "Whether SSL is enabled"},
80
+ "cert_path": {"type": "string", "description": "Path to certificate file"},
81
+ "key_path": {"type": "string", "description": "Path to private key file"},
82
+ "config": {"type": "object", "description": "SSL configuration"},
83
+ "status": {"type": "string", "enum": ["enabled", "disabled", "error"],
84
+ "description": "SSL status"},
85
+ "error": {"type": "string", "description": "Error message if any"}
86
+ },
87
+ "required": ["ssl_enabled", "status"]
88
+ }
89
+
90
+
91
+ class SSLSetupCommand(Command):
92
+ """
93
+ Command for SSL setup and configuration.
94
+
95
+ Provides methods for SSL setup, status checking, testing, and configuration.
96
+ """
97
+
98
+ # Command metadata
99
+ name = "ssl_setup"
100
+ version = "1.0.0"
101
+ descr = "SSL setup and configuration management"
102
+ category = "security"
103
+ author = "MCP Proxy Adapter Team"
104
+ email = "team@mcp-proxy-adapter.com"
105
+ source_url = "https://github.com/mcp-proxy-adapter"
106
+ result_class = SSLSetupResult
107
+
108
+ def __init__(self):
109
+ """Initialize SSL setup command."""
110
+ super().__init__()
111
+ self.certificate_utils = CertificateUtils()
112
+ self.auth_validator = AuthValidator()
113
+
114
+ async def execute(self, **kwargs) -> CommandResult:
115
+ """
116
+ Execute SSL setup command.
117
+
118
+ Args:
119
+ **kwargs: Command parameters including:
120
+ - action: Action to perform (ssl_setup, ssl_status, ssl_test, ssl_config)
121
+ - ssl_config: SSL configuration for ssl_setup action
122
+ - cert_file: Certificate file path for ssl_test action
123
+ - key_file: Key file path for ssl_test action
124
+ - action: Action for ssl_config (get, set, update, reset)
125
+ - config_data: Configuration data for ssl_config action
126
+
127
+ Returns:
128
+ CommandResult with SSL operation status
129
+ """
130
+ action = kwargs.get("action", "ssl_status")
131
+
132
+ if action == "ssl_setup":
133
+ ssl_config = kwargs.get("ssl_config", {})
134
+ return await self.ssl_setup(ssl_config)
135
+ elif action == "ssl_status":
136
+ return await self.ssl_status()
137
+ elif action == "ssl_test":
138
+ cert_file = kwargs.get("cert_file")
139
+ key_file = kwargs.get("key_file")
140
+ return await self.ssl_test(cert_file, key_file)
141
+ elif action == "ssl_config":
142
+ config_action = kwargs.get("config_action", "get")
143
+ config_data = kwargs.get("config_data", {})
144
+ return await self.ssl_config(config_action, config_data)
145
+ else:
146
+ return ErrorResult(
147
+ message=f"Unknown action: {action}. Supported actions: ssl_setup, ssl_status, ssl_test, ssl_config"
148
+ )
149
+
150
+ async def ssl_setup(self, ssl_config: Dict[str, Any]) -> CommandResult:
151
+ """
152
+ Setup SSL configuration.
153
+
154
+ Args:
155
+ ssl_config: SSL configuration dictionary containing:
156
+ - enabled: Whether to enable SSL
157
+ - cert_file: Path to certificate file
158
+ - key_file: Path to private key file
159
+ - ca_file: Path to CA certificate file (optional)
160
+ - verify_mode: SSL verification mode (optional)
161
+ - cipher_suites: List of allowed cipher suites (optional)
162
+
163
+ Returns:
164
+ CommandResult with SSL setup status
165
+ """
166
+ try:
167
+ logger.info("Setting up SSL configuration")
168
+
169
+ # Validate SSL configuration
170
+ if not isinstance(ssl_config, dict):
171
+ return ErrorResult(
172
+ message="SSL configuration must be a dictionary"
173
+ )
174
+
175
+ enabled = ssl_config.get("enabled", False)
176
+ if not enabled:
177
+ result = SSLSetupResult(
178
+ ssl_enabled=False,
179
+ status="disabled",
180
+ config=ssl_config
181
+ )
182
+ return SuccessResult(data=result.to_dict())
183
+
184
+ # Validate required files
185
+ cert_file = ssl_config.get("cert_file")
186
+ key_file = ssl_config.get("key_file")
187
+
188
+ if not cert_file or not key_file:
189
+ return ErrorResult(
190
+ message="Certificate and key files are required when SSL is enabled"
191
+ )
192
+
193
+ # Check if files exist
194
+ if not os.path.exists(cert_file):
195
+ return ErrorResult(
196
+ message=f"Certificate file not found: {cert_file}"
197
+ )
198
+
199
+ if not os.path.exists(key_file):
200
+ return ErrorResult(
201
+ message=f"Private key file not found: {key_file}"
202
+ )
203
+
204
+ # Validate certificate and key
205
+ cert_validation = self.auth_validator.validate_certificate(cert_file)
206
+ if not cert_validation.is_valid:
207
+ return ErrorResult(
208
+ message=f"Certificate validation failed: {cert_validation.error_message}"
209
+ )
210
+
211
+ # Test SSL configuration
212
+ test_result = await self._test_ssl_config(cert_file, key_file)
213
+ if not test_result["success"]:
214
+ return ErrorResult(
215
+ message=f"SSL configuration test failed: {test_result['error']}"
216
+ )
217
+
218
+ result = SSLSetupResult(
219
+ ssl_enabled=True,
220
+ cert_path=cert_file,
221
+ key_path=key_file,
222
+ config=ssl_config,
223
+ status="enabled"
224
+ )
225
+
226
+ logger.info("SSL configuration setup completed successfully")
227
+ return SuccessResult(data=result.to_dict())
228
+
229
+ except Exception as e:
230
+ logger.error(f"SSL setup failed: {e}")
231
+ return ErrorResult(
232
+ message=f"SSL setup failed: {str(e)}"
233
+ )
234
+
235
+ async def ssl_status(self) -> CommandResult:
236
+ """
237
+ Get current SSL status.
238
+
239
+ Returns:
240
+ CommandResult with SSL status information
241
+ """
242
+ try:
243
+ logger.info("Checking SSL status")
244
+
245
+ # Check if SSL is configured in the application
246
+ from ..config import Config
247
+ config = Config()
248
+
249
+ ssl_config = config.get("ssl", {})
250
+ enabled = ssl_config.get("enabled", False)
251
+
252
+ if not enabled:
253
+ result = SSLSetupResult(
254
+ ssl_enabled=False,
255
+ status="disabled",
256
+ config=ssl_config
257
+ )
258
+ return SuccessResult(data=result.to_dict())
259
+
260
+ cert_file = ssl_config.get("cert_file")
261
+ key_file = ssl_config.get("key_file")
262
+
263
+ # Check file existence
264
+ cert_exists = os.path.exists(cert_file) if cert_file else False
265
+ key_exists = os.path.exists(key_file) if key_file else False
266
+
267
+ if not cert_exists or not key_exists:
268
+ result = SSLSetupResult(
269
+ ssl_enabled=False,
270
+ status="error",
271
+ cert_path=cert_file,
272
+ key_path=key_file,
273
+ config=ssl_config,
274
+ error="Certificate or key file not found"
275
+ )
276
+ return SuccessResult(data=result.to_dict())
277
+
278
+ # Validate certificate
279
+ cert_validation = self.auth_validator.validate_certificate(cert_file)
280
+ if not cert_validation.is_valid:
281
+ result = SSLSetupResult(
282
+ ssl_enabled=False,
283
+ status="error",
284
+ cert_path=cert_file,
285
+ key_path=key_file,
286
+ config=ssl_config,
287
+ error=f"Certificate validation failed: {cert_validation.error_message}"
288
+ )
289
+ return SuccessResult(data=result.to_dict())
290
+
291
+ result = SSLSetupResult(
292
+ ssl_enabled=True,
293
+ cert_path=cert_file,
294
+ key_path=key_file,
295
+ config=ssl_config,
296
+ status="enabled"
297
+ )
298
+
299
+ logger.info("SSL status check completed")
300
+ return SuccessResult(data=result.to_dict())
301
+
302
+ except Exception as e:
303
+ logger.error(f"SSL status check failed: {e}")
304
+ return ErrorResult(
305
+ message=f"SSL status check failed: {str(e)}"
306
+ )
307
+
308
+ async def ssl_test(self, cert_file: str, key_file: str) -> CommandResult:
309
+ """
310
+ Test SSL configuration with certificate and key files.
311
+
312
+ Args:
313
+ cert_file: Path to certificate file
314
+ key_file: Path to private key file
315
+
316
+ Returns:
317
+ CommandResult with test results
318
+ """
319
+ try:
320
+ logger.info(f"Testing SSL configuration with cert: {cert_file}, key: {key_file}")
321
+
322
+ # Validate parameters
323
+ if not cert_file or not key_file:
324
+ return ErrorResult(
325
+ message="Certificate and key file paths are required"
326
+ )
327
+
328
+ # Check file existence
329
+ if not os.path.exists(cert_file):
330
+ return ErrorResult(
331
+ message=f"Certificate file not found: {cert_file}"
332
+ )
333
+
334
+ if not os.path.exists(key_file):
335
+ return ErrorResult(
336
+ message=f"Private key file not found: {key_file}"
337
+ )
338
+
339
+ # Test SSL configuration
340
+ test_result = await self._test_ssl_config(cert_file, key_file)
341
+
342
+ if test_result["success"]:
343
+ logger.info("SSL configuration test passed")
344
+ return SuccessResult(
345
+ data={
346
+ "test_passed": True,
347
+ "cert_file": cert_file,
348
+ "key_file": key_file,
349
+ "details": test_result["details"]
350
+ }
351
+ )
352
+ else:
353
+ logger.error(f"SSL configuration test failed: {test_result['error']}")
354
+ return ErrorResult(
355
+ message=test_result["error"]
356
+ )
357
+
358
+ except Exception as e:
359
+ logger.error(f"SSL test failed: {e}")
360
+ return ErrorResult(
361
+ message=f"SSL test failed: {str(e)}"
362
+ )
363
+
364
+ async def ssl_config(self, action: str, config_data: Dict[str, Any]) -> CommandResult:
365
+ """
366
+ Manage SSL configuration.
367
+
368
+ Args:
369
+ action: Action to perform (get, set, update, reset)
370
+ config_data: Configuration data for the action
371
+
372
+ Returns:
373
+ CommandResult with configuration operation result
374
+ """
375
+ try:
376
+ logger.info(f"Performing SSL config action: {action}")
377
+
378
+ from ..config import Config
379
+ config = Config()
380
+
381
+ if action == "get":
382
+ ssl_config = config.get("ssl", {})
383
+ return SuccessResult(
384
+ data={"ssl_config": ssl_config}
385
+ )
386
+
387
+ elif action == "set":
388
+ # Validate configuration
389
+ if not isinstance(config_data, dict):
390
+ return ErrorResult(
391
+ message="Configuration data must be a dictionary"
392
+ )
393
+
394
+ # Update configuration
395
+ config.update_config({"ssl": config_data})
396
+ return SuccessResult(
397
+ data={"message": "SSL configuration updated", "ssl_config": config_data}
398
+ )
399
+
400
+ elif action == "update":
401
+ # Get current configuration
402
+ current_config = config.get("ssl", {})
403
+
404
+ # Update with new data
405
+ current_config.update(config_data)
406
+
407
+ # Update configuration
408
+ config.update_config({"ssl": current_config})
409
+ return SuccessResult(
410
+ data={"message": "SSL configuration updated", "ssl_config": current_config}
411
+ )
412
+
413
+ elif action == "reset":
414
+ # Reset to default configuration
415
+ default_config = {
416
+ "enabled": False,
417
+ "cert_file": None,
418
+ "key_file": None,
419
+ "ca_file": None,
420
+ "verify_mode": "CERT_REQUIRED",
421
+ "cipher_suites": []
422
+ }
423
+
424
+ config.update_config({"ssl": default_config})
425
+ return SuccessResult(
426
+ data={"message": "SSL configuration reset to defaults", "ssl_config": default_config}
427
+ )
428
+
429
+ else:
430
+ return ErrorResult(
431
+ message=f"Unknown action: {action}. Supported actions: get, set, update, reset"
432
+ )
433
+
434
+ except Exception as e:
435
+ logger.error(f"SSL config action failed: {e}")
436
+ return ErrorResult(
437
+ message=f"SSL config action failed: {str(e)}"
438
+ )
439
+
440
+ async def _test_ssl_config(self, cert_file: str, key_file: str) -> Dict[str, Any]:
441
+ """
442
+ Test SSL configuration internally.
443
+
444
+ Args:
445
+ cert_file: Path to certificate file
446
+ key_file: Path to private key file
447
+
448
+ Returns:
449
+ Dictionary with test results
450
+ """
451
+ try:
452
+ # Create SSL context
453
+ context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
454
+ context.check_hostname = False
455
+ context.verify_mode = ssl.CERT_NONE
456
+
457
+ # Load certificate and key
458
+ context.load_cert_chain(cert_file, key_file)
459
+
460
+ # Test basic SSL functionality
461
+ details = {
462
+ "ssl_version": ssl.OPENSSL_VERSION,
463
+ "certificate_loaded": True,
464
+ "private_key_loaded": True,
465
+ "context_created": True
466
+ }
467
+
468
+ return {
469
+ "success": True,
470
+ "details": details
471
+ }
472
+
473
+ except Exception as e:
474
+ return {
475
+ "success": False,
476
+ "error": str(e),
477
+ "details": {
478
+ "ssl_version": ssl.OPENSSL_VERSION,
479
+ "certificate_loaded": False,
480
+ "private_key_loaded": False,
481
+ "context_created": False
482
+ }
483
+ }