mcp-proxy-adapter 2.0.1__py3-none-any.whl → 6.9.50__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.

Potentially problematic release.


This version of mcp-proxy-adapter might be problematic. Click here for more details.

Files changed (269) hide show
  1. mcp_proxy_adapter/__init__.py +47 -0
  2. mcp_proxy_adapter/__main__.py +13 -0
  3. mcp_proxy_adapter/api/__init__.py +0 -0
  4. mcp_proxy_adapter/api/app.py +66 -0
  5. mcp_proxy_adapter/api/core/__init__.py +18 -0
  6. mcp_proxy_adapter/api/core/app_factory.py +400 -0
  7. mcp_proxy_adapter/api/core/lifespan_manager.py +55 -0
  8. mcp_proxy_adapter/api/core/registration_context.py +356 -0
  9. mcp_proxy_adapter/api/core/registration_manager.py +307 -0
  10. mcp_proxy_adapter/api/core/registration_tasks.py +84 -0
  11. mcp_proxy_adapter/api/core/ssl_context_factory.py +88 -0
  12. mcp_proxy_adapter/api/handlers.py +181 -0
  13. mcp_proxy_adapter/api/middleware/__init__.py +21 -0
  14. mcp_proxy_adapter/api/middleware/base.py +54 -0
  15. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +73 -0
  16. mcp_proxy_adapter/api/middleware/error_handling.py +76 -0
  17. mcp_proxy_adapter/api/middleware/factory.py +147 -0
  18. mcp_proxy_adapter/api/middleware/logging.py +31 -0
  19. mcp_proxy_adapter/api/middleware/performance.py +51 -0
  20. mcp_proxy_adapter/api/middleware/protocol_middleware.py +140 -0
  21. mcp_proxy_adapter/api/middleware/transport_middleware.py +87 -0
  22. mcp_proxy_adapter/api/middleware/unified_security.py +223 -0
  23. mcp_proxy_adapter/api/middleware/user_info_middleware.py +132 -0
  24. mcp_proxy_adapter/api/openapi/__init__.py +21 -0
  25. mcp_proxy_adapter/api/openapi/command_integration.py +105 -0
  26. mcp_proxy_adapter/api/openapi/openapi_generator.py +40 -0
  27. mcp_proxy_adapter/api/openapi/openapi_registry.py +62 -0
  28. mcp_proxy_adapter/api/openapi/schema_loader.py +116 -0
  29. mcp_proxy_adapter/api/schemas.py +270 -0
  30. mcp_proxy_adapter/api/tool_integration.py +131 -0
  31. mcp_proxy_adapter/api/tools.py +163 -0
  32. mcp_proxy_adapter/cli/__init__.py +12 -0
  33. mcp_proxy_adapter/cli/commands/__init__.py +15 -0
  34. mcp_proxy_adapter/cli/commands/client.py +100 -0
  35. mcp_proxy_adapter/cli/commands/config_generate.py +105 -0
  36. mcp_proxy_adapter/cli/commands/config_validate.py +94 -0
  37. mcp_proxy_adapter/cli/commands/generate.py +259 -0
  38. mcp_proxy_adapter/cli/commands/server.py +174 -0
  39. mcp_proxy_adapter/cli/commands/sets.py +132 -0
  40. mcp_proxy_adapter/cli/commands/testconfig.py +177 -0
  41. mcp_proxy_adapter/cli/examples/__init__.py +8 -0
  42. mcp_proxy_adapter/cli/examples/http_basic.py +82 -0
  43. mcp_proxy_adapter/cli/examples/https_token.py +96 -0
  44. mcp_proxy_adapter/cli/examples/mtls_roles.py +103 -0
  45. mcp_proxy_adapter/cli/main.py +63 -0
  46. mcp_proxy_adapter/cli/parser.py +338 -0
  47. mcp_proxy_adapter/cli/validators.py +231 -0
  48. mcp_proxy_adapter/client/jsonrpc_client/__init__.py +9 -0
  49. mcp_proxy_adapter/client/jsonrpc_client/client.py +42 -0
  50. mcp_proxy_adapter/client/jsonrpc_client/command_api.py +45 -0
  51. mcp_proxy_adapter/client/jsonrpc_client/proxy_api.py +224 -0
  52. mcp_proxy_adapter/client/jsonrpc_client/queue_api.py +60 -0
  53. mcp_proxy_adapter/client/jsonrpc_client/transport.py +108 -0
  54. mcp_proxy_adapter/client/proxy.py +123 -0
  55. mcp_proxy_adapter/commands/__init__.py +66 -0
  56. mcp_proxy_adapter/commands/auth_validation_command.py +69 -0
  57. mcp_proxy_adapter/commands/base.py +389 -0
  58. mcp_proxy_adapter/commands/builtin_commands.py +30 -0
  59. mcp_proxy_adapter/commands/catalog/__init__.py +20 -0
  60. mcp_proxy_adapter/commands/catalog/catalog_loader.py +34 -0
  61. mcp_proxy_adapter/commands/catalog/catalog_manager.py +122 -0
  62. mcp_proxy_adapter/commands/catalog/catalog_syncer.py +149 -0
  63. mcp_proxy_adapter/commands/catalog/command_catalog.py +43 -0
  64. mcp_proxy_adapter/commands/catalog/dependency_manager.py +37 -0
  65. mcp_proxy_adapter/commands/catalog_manager.py +97 -0
  66. mcp_proxy_adapter/commands/cert_monitor_command.py +552 -0
  67. mcp_proxy_adapter/commands/certificate_management_command.py +562 -0
  68. mcp_proxy_adapter/commands/command_registry.py +298 -0
  69. mcp_proxy_adapter/commands/config_command.py +102 -0
  70. mcp_proxy_adapter/commands/dependency_container.py +40 -0
  71. mcp_proxy_adapter/commands/dependency_manager.py +143 -0
  72. mcp_proxy_adapter/commands/echo_command.py +48 -0
  73. mcp_proxy_adapter/commands/health_command.py +142 -0
  74. mcp_proxy_adapter/commands/help_command.py +175 -0
  75. mcp_proxy_adapter/commands/hooks.py +172 -0
  76. mcp_proxy_adapter/commands/key_management_command.py +484 -0
  77. mcp_proxy_adapter/commands/load_command.py +123 -0
  78. mcp_proxy_adapter/commands/plugins_command.py +246 -0
  79. mcp_proxy_adapter/commands/protocol_management_command.py +216 -0
  80. mcp_proxy_adapter/commands/proxy_registration_command.py +319 -0
  81. mcp_proxy_adapter/commands/queue_commands.py +750 -0
  82. mcp_proxy_adapter/commands/registration_status_command.py +76 -0
  83. mcp_proxy_adapter/commands/registry/__init__.py +18 -0
  84. mcp_proxy_adapter/commands/registry/command_info.py +103 -0
  85. mcp_proxy_adapter/commands/registry/command_loader.py +207 -0
  86. mcp_proxy_adapter/commands/registry/command_manager.py +119 -0
  87. mcp_proxy_adapter/commands/registry/command_registry.py +217 -0
  88. mcp_proxy_adapter/commands/reload_command.py +136 -0
  89. mcp_proxy_adapter/commands/result.py +157 -0
  90. mcp_proxy_adapter/commands/role_test_command.py +99 -0
  91. mcp_proxy_adapter/commands/roles_management_command.py +502 -0
  92. mcp_proxy_adapter/commands/security_command.py +472 -0
  93. mcp_proxy_adapter/commands/settings_command.py +113 -0
  94. mcp_proxy_adapter/commands/ssl_setup_command.py +306 -0
  95. mcp_proxy_adapter/commands/token_management_command.py +500 -0
  96. mcp_proxy_adapter/commands/transport_management_command.py +129 -0
  97. mcp_proxy_adapter/commands/unload_command.py +92 -0
  98. mcp_proxy_adapter/config.py +32 -0
  99. mcp_proxy_adapter/core/__init__.py +8 -0
  100. mcp_proxy_adapter/core/app_factory.py +560 -0
  101. mcp_proxy_adapter/core/app_runner.py +318 -0
  102. mcp_proxy_adapter/core/auth_validator.py +508 -0
  103. mcp_proxy_adapter/core/certificate/__init__.py +20 -0
  104. mcp_proxy_adapter/core/certificate/certificate_creator.py +372 -0
  105. mcp_proxy_adapter/core/certificate/certificate_extractor.py +185 -0
  106. mcp_proxy_adapter/core/certificate/certificate_utils.py +249 -0
  107. mcp_proxy_adapter/core/certificate/certificate_validator.py +481 -0
  108. mcp_proxy_adapter/core/certificate/ssl_context_manager.py +65 -0
  109. mcp_proxy_adapter/core/certificate_utils.py +249 -0
  110. mcp_proxy_adapter/core/client.py +608 -0
  111. mcp_proxy_adapter/core/client_manager.py +271 -0
  112. mcp_proxy_adapter/core/client_security.py +411 -0
  113. mcp_proxy_adapter/core/config/__init__.py +18 -0
  114. mcp_proxy_adapter/core/config/config.py +237 -0
  115. mcp_proxy_adapter/core/config/config_factory.py +22 -0
  116. mcp_proxy_adapter/core/config/config_loader.py +66 -0
  117. mcp_proxy_adapter/core/config/feature_manager.py +31 -0
  118. mcp_proxy_adapter/core/config/simple_config.py +204 -0
  119. mcp_proxy_adapter/core/config/simple_config_generator.py +131 -0
  120. mcp_proxy_adapter/core/config/simple_config_validator.py +476 -0
  121. mcp_proxy_adapter/core/config_converter.py +252 -0
  122. mcp_proxy_adapter/core/config_validator.py +211 -0
  123. mcp_proxy_adapter/core/crl_utils.py +362 -0
  124. mcp_proxy_adapter/core/errors.py +276 -0
  125. mcp_proxy_adapter/core/job_manager.py +54 -0
  126. mcp_proxy_adapter/core/logging.py +250 -0
  127. mcp_proxy_adapter/core/mtls_asgi.py +140 -0
  128. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  129. mcp_proxy_adapter/core/mtls_proxy.py +229 -0
  130. mcp_proxy_adapter/core/mtls_server.py +154 -0
  131. mcp_proxy_adapter/core/protocol_manager.py +232 -0
  132. mcp_proxy_adapter/core/proxy/__init__.py +19 -0
  133. mcp_proxy_adapter/core/proxy/auth_manager.py +26 -0
  134. mcp_proxy_adapter/core/proxy/proxy_registration_manager.py +160 -0
  135. mcp_proxy_adapter/core/proxy/registration_client.py +186 -0
  136. mcp_proxy_adapter/core/proxy/ssl_manager.py +101 -0
  137. mcp_proxy_adapter/core/proxy_client.py +184 -0
  138. mcp_proxy_adapter/core/proxy_registration.py +80 -0
  139. mcp_proxy_adapter/core/role_utils.py +103 -0
  140. mcp_proxy_adapter/core/security_adapter.py +343 -0
  141. mcp_proxy_adapter/core/security_factory.py +96 -0
  142. mcp_proxy_adapter/core/security_integration.py +342 -0
  143. mcp_proxy_adapter/core/server_adapter.py +251 -0
  144. mcp_proxy_adapter/core/server_engine.py +217 -0
  145. mcp_proxy_adapter/core/settings.py +260 -0
  146. mcp_proxy_adapter/core/signal_handler.py +107 -0
  147. mcp_proxy_adapter/core/ssl_utils.py +161 -0
  148. mcp_proxy_adapter/core/transport_manager.py +153 -0
  149. mcp_proxy_adapter/core/unified_config_adapter.py +471 -0
  150. mcp_proxy_adapter/core/utils.py +101 -0
  151. mcp_proxy_adapter/core/validation/__init__.py +21 -0
  152. mcp_proxy_adapter/core/validation/config_validator.py +219 -0
  153. mcp_proxy_adapter/core/validation/file_validator.py +131 -0
  154. mcp_proxy_adapter/core/validation/protocol_validator.py +205 -0
  155. mcp_proxy_adapter/core/validation/security_validator.py +140 -0
  156. mcp_proxy_adapter/core/validation/validation_result.py +27 -0
  157. mcp_proxy_adapter/custom_openapi.py +58 -0
  158. mcp_proxy_adapter/examples/__init__.py +16 -0
  159. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  160. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  161. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  162. mcp_proxy_adapter/examples/basic_framework/main.py +52 -0
  163. mcp_proxy_adapter/examples/bugfix_certificate_config.py +261 -0
  164. mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
  165. mcp_proxy_adapter/examples/check_config.py +413 -0
  166. mcp_proxy_adapter/examples/client_usage_example.py +164 -0
  167. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  168. mcp_proxy_adapter/examples/config_builder.py +234 -0
  169. mcp_proxy_adapter/examples/config_cli.py +282 -0
  170. mcp_proxy_adapter/examples/create_test_configs.py +174 -0
  171. mcp_proxy_adapter/examples/debug_request_state.py +130 -0
  172. mcp_proxy_adapter/examples/debug_role_chain.py +191 -0
  173. mcp_proxy_adapter/examples/demo_client.py +287 -0
  174. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  175. mcp_proxy_adapter/examples/full_application/commands/__init__.py +8 -0
  176. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +45 -0
  177. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +52 -0
  178. mcp_proxy_adapter/examples/full_application/commands/echo_command.py +32 -0
  179. mcp_proxy_adapter/examples/full_application/commands/help_command.py +54 -0
  180. mcp_proxy_adapter/examples/full_application/commands/list_command.py +57 -0
  181. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +5 -0
  182. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +29 -0
  183. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +27 -0
  184. mcp_proxy_adapter/examples/full_application/main.py +311 -0
  185. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +161 -0
  186. mcp_proxy_adapter/examples/full_application/run_mtls.py +252 -0
  187. mcp_proxy_adapter/examples/full_application/run_simple.py +152 -0
  188. mcp_proxy_adapter/examples/full_application/test_minimal_server.py +45 -0
  189. mcp_proxy_adapter/examples/full_application/test_server.py +163 -0
  190. mcp_proxy_adapter/examples/full_application/test_simple_server.py +62 -0
  191. mcp_proxy_adapter/examples/generate_config.py +502 -0
  192. mcp_proxy_adapter/examples/proxy_registration_example.py +335 -0
  193. mcp_proxy_adapter/examples/queue_demo_simple.py +632 -0
  194. mcp_proxy_adapter/examples/queue_integration_example.py +578 -0
  195. mcp_proxy_adapter/examples/queue_server_demo.py +82 -0
  196. mcp_proxy_adapter/examples/queue_server_example.py +85 -0
  197. mcp_proxy_adapter/examples/queue_server_simple.py +173 -0
  198. mcp_proxy_adapter/examples/required_certificates.py +208 -0
  199. mcp_proxy_adapter/examples/run_example.py +77 -0
  200. mcp_proxy_adapter/examples/run_full_test_suite.py +619 -0
  201. mcp_proxy_adapter/examples/run_proxy_server.py +153 -0
  202. mcp_proxy_adapter/examples/run_security_tests_fixed.py +435 -0
  203. mcp_proxy_adapter/examples/security_test/__init__.py +18 -0
  204. mcp_proxy_adapter/examples/security_test/auth_manager.py +14 -0
  205. mcp_proxy_adapter/examples/security_test/ssl_context_manager.py +28 -0
  206. mcp_proxy_adapter/examples/security_test/test_client.py +159 -0
  207. mcp_proxy_adapter/examples/security_test/test_result.py +22 -0
  208. mcp_proxy_adapter/examples/security_test_client.py +72 -0
  209. mcp_proxy_adapter/examples/setup/__init__.py +24 -0
  210. mcp_proxy_adapter/examples/setup/certificate_manager.py +215 -0
  211. mcp_proxy_adapter/examples/setup/config_generator.py +12 -0
  212. mcp_proxy_adapter/examples/setup/config_validator.py +118 -0
  213. mcp_proxy_adapter/examples/setup/environment_setup.py +62 -0
  214. mcp_proxy_adapter/examples/setup/test_files_generator.py +10 -0
  215. mcp_proxy_adapter/examples/setup/test_runner.py +89 -0
  216. mcp_proxy_adapter/examples/setup_test_environment.py +235 -0
  217. mcp_proxy_adapter/examples/simple_protocol_test.py +125 -0
  218. mcp_proxy_adapter/examples/test_chk_hostname_automated.py +211 -0
  219. mcp_proxy_adapter/examples/test_config.py +205 -0
  220. mcp_proxy_adapter/examples/test_config_builder.py +110 -0
  221. mcp_proxy_adapter/examples/test_examples.py +308 -0
  222. mcp_proxy_adapter/examples/test_framework_complete.py +267 -0
  223. mcp_proxy_adapter/examples/test_mcp_server.py +187 -0
  224. mcp_proxy_adapter/examples/test_protocol_examples.py +337 -0
  225. mcp_proxy_adapter/examples/universal_client.py +674 -0
  226. mcp_proxy_adapter/examples/update_config_certificates.py +135 -0
  227. mcp_proxy_adapter/examples/validate_generator_compatibility.py +385 -0
  228. mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +61 -0
  229. mcp_proxy_adapter/integrations/__init__.py +25 -0
  230. mcp_proxy_adapter/integrations/queuemgr_integration.py +462 -0
  231. mcp_proxy_adapter/main.py +311 -0
  232. mcp_proxy_adapter/openapi.py +375 -0
  233. mcp_proxy_adapter/schemas/base_schema.json +114 -0
  234. mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
  235. mcp_proxy_adapter/schemas/roles.json +37 -0
  236. mcp_proxy_adapter/schemas/roles_schema.json +162 -0
  237. mcp_proxy_adapter/version.py +5 -0
  238. mcp_proxy_adapter-6.9.50.dist-info/METADATA +1088 -0
  239. mcp_proxy_adapter-6.9.50.dist-info/RECORD +242 -0
  240. {mcp_proxy_adapter-2.0.1.dist-info → mcp_proxy_adapter-6.9.50.dist-info}/WHEEL +1 -1
  241. mcp_proxy_adapter-6.9.50.dist-info/entry_points.txt +14 -0
  242. mcp_proxy_adapter-6.9.50.dist-info/top_level.txt +1 -0
  243. adapters/__init__.py +0 -16
  244. analyzers/__init__.py +0 -14
  245. analyzers/docstring_analyzer.py +0 -199
  246. analyzers/type_analyzer.py +0 -151
  247. cli/__init__.py +0 -12
  248. cli/__main__.py +0 -79
  249. cli/command_runner.py +0 -233
  250. dispatchers/__init__.py +0 -14
  251. dispatchers/base_dispatcher.py +0 -85
  252. dispatchers/json_rpc_dispatcher.py +0 -198
  253. generators/__init__.py +0 -14
  254. generators/endpoint_generator.py +0 -172
  255. generators/openapi_generator.py +0 -254
  256. generators/rest_api_generator.py +0 -207
  257. mcp_proxy_adapter-2.0.1.dist-info/METADATA +0 -272
  258. mcp_proxy_adapter-2.0.1.dist-info/RECORD +0 -28
  259. mcp_proxy_adapter-2.0.1.dist-info/licenses/LICENSE +0 -21
  260. mcp_proxy_adapter-2.0.1.dist-info/top_level.txt +0 -7
  261. openapi_schema/__init__.py +0 -38
  262. openapi_schema/command_registry.py +0 -312
  263. openapi_schema/rest_schema.py +0 -510
  264. openapi_schema/rpc_generator.py +0 -307
  265. openapi_schema/rpc_schema.py +0 -416
  266. validators/__init__.py +0 -14
  267. validators/base_validator.py +0 -23
  268. validators/docstring_validator.py +0 -75
  269. validators/metadata_validator.py +0 -76
@@ -0,0 +1,552 @@
1
+ """
2
+ Certificate Monitor Command
3
+
4
+ This module provides commands for certificate monitoring including expiry checks,
5
+ health monitoring, alert setup, and auto-renewal.
6
+
7
+ Author: MCP Proxy Adapter Team
8
+ Version: 1.0.0
9
+ """
10
+
11
+ import logging
12
+ import os
13
+ import json
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
+ from mcp_proxy_adapter.core.logging import get_global_logger
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ class CertMonitorResult:
27
+ """
28
+ Result class for certificate monitoring operations.
29
+
30
+ Contains monitoring information and operation status.
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ cert_path: str,
36
+ check_type: str,
37
+ status: str,
38
+ expiry_date: Optional[str] = None,
39
+ days_until_expiry: Optional[int] = None,
40
+ health_score: Optional[int] = None,
41
+ alerts: Optional[List[str]] = None,
42
+ auto_renewal_status: Optional[str] = None,
43
+ error: Optional[str] = None,
44
+ ):
45
+ """
46
+ Initialize certificate monitor result.
47
+
48
+ Args:
49
+ cert_path: Path to certificate file
50
+ check_type: Type of check performed (expiry, health, alert, auto_renewal)
51
+ status: Overall status (healthy, warning, critical, error)
52
+ expiry_date: Certificate expiry date
53
+ days_until_expiry: Days until certificate expires
54
+ health_score: Health score (0-100)
55
+ alerts: List of alert messages
56
+ auto_renewal_status: Auto-renewal status
57
+ error: Error message if any
58
+ """
59
+ self.cert_path = cert_path
60
+ self.check_type = check_type
61
+ self.status = status
62
+ self.expiry_date = expiry_date
63
+ self.days_until_expiry = days_until_expiry
64
+ self.health_score = health_score
65
+ self.alerts = alerts or []
66
+ self.auto_renewal_status = auto_renewal_status
67
+ self.error = error
68
+
69
+
70
+ @classmethod
71
+
72
+
73
+ class CertMonitorCommand(Command):
74
+ """
75
+ Command for certificate monitoring.
76
+
77
+ Provides methods for monitoring certificate expiry, health, alerts, and auto-renewal.
78
+ """
79
+
80
+ # Command metadata
81
+ name = "cert_monitor"
82
+ version = "1.0.0"
83
+ descr = "Certificate expiry monitoring and health checks"
84
+ category = "security"
85
+ author = "MCP Proxy Adapter Team"
86
+ email = "team@mcp-proxy-adapter.com"
87
+ source_url = "https://github.com/mcp-proxy-adapter"
88
+ result_class = CertMonitorResult
89
+
90
+ def __init__(self):
91
+ """Initialize certificate monitor command."""
92
+ super().__init__()
93
+ self.certificate_utils = CertificateUtils()
94
+ self.auth_validator = AuthValidator()
95
+
96
+ async def execute(self, **kwargs) -> CommandResult:
97
+ """
98
+ Execute certificate monitor command.
99
+
100
+ Args:
101
+ **kwargs: Command parameters including:
102
+ - action: Action to perform (cert_expiry_check, cert_health_check, cert_alert_setup, cert_auto_renew)
103
+ - cert_path: Certificate file path for individual checks
104
+ - warning_days: Days before expiry to start warning
105
+ - critical_days: Days before expiry for critical status
106
+ - alert_config: Alert configuration for setup
107
+ - auto_renew_config: Auto-renewal configuration
108
+
109
+ Returns:
110
+ CommandResult with monitoring operation status
111
+ """
112
+ action = kwargs.get("action", "cert_expiry_check")
113
+
114
+ if action == "cert_expiry_check":
115
+ cert_path = kwargs.get("cert_path")
116
+ warning_days = kwargs.get("warning_days", 30)
117
+ critical_days = kwargs.get("critical_days", 7)
118
+ return await self.cert_expiry_check(cert_path, warning_days, critical_days)
119
+ elif action == "cert_health_check":
120
+ cert_path = kwargs.get("cert_path")
121
+ return await self.cert_health_check(cert_path)
122
+ elif action == "cert_alert_setup":
123
+ cert_path = kwargs.get("cert_path")
124
+ alert_config = kwargs.get("alert_config", {})
125
+ return await self.cert_alert_setup(cert_path, alert_config)
126
+ elif action == "cert_auto_renew":
127
+ cert_path = kwargs.get("cert_path")
128
+ auto_renew_config = kwargs.get("auto_renew_config", {})
129
+ return await self.cert_auto_renew(cert_path, auto_renew_config)
130
+ else:
131
+ return ErrorResult(
132
+ message=f"Unknown action: {action}. Supported actions: cert_expiry_check, cert_health_check, cert_alert_setup, cert_auto_renew"
133
+ )
134
+
135
+ async def cert_expiry_check(
136
+ self, cert_path: str, warning_days: int = 30, critical_days: int = 7
137
+ ) -> CommandResult:
138
+ """
139
+ Check certificate expiry date.
140
+
141
+ Args:
142
+ cert_path: Path to certificate file
143
+ warning_days: Days before expiry to start warning
144
+ critical_days: Days before expiry for critical status
145
+
146
+ Returns:
147
+ CommandResult with expiry check results
148
+ """
149
+ try:
150
+ get_global_logger().info(f"Performing certificate expiry check for {cert_path}")
151
+
152
+ # Check if certificate file exists
153
+ if not os.path.exists(cert_path):
154
+ return ErrorResult(message=f"Certificate file not found: {cert_path}")
155
+
156
+ # Get certificate info
157
+ cert_info = self.certificate_utils.get_certificate_info(cert_path)
158
+ if not cert_info:
159
+ return ErrorResult(message="Could not read certificate information")
160
+
161
+ expiry_date = cert_info.get("expiry_date")
162
+ if not expiry_date:
163
+ return ErrorResult(
164
+ message="Could not determine certificate expiry date"
165
+ )
166
+
167
+ try:
168
+ # Calculate days until expiry
169
+ expiry_datetime = datetime.fromisoformat(
170
+ expiry_date.replace("Z", "+00:00")
171
+ )
172
+ days_until_expiry = (
173
+ expiry_datetime - datetime.now(expiry_datetime.tzinfo)
174
+ ).days
175
+ except ValueError:
176
+ return ErrorResult(message="Invalid expiry date format")
177
+
178
+ # Determine status
179
+ is_expired = days_until_expiry < 0
180
+ if is_expired:
181
+ health_status = "expired"
182
+ elif days_until_expiry <= critical_days:
183
+ health_status = "critical"
184
+ elif days_until_expiry <= warning_days:
185
+ health_status = "warning"
186
+ else:
187
+ health_status = "healthy"
188
+
189
+ get_global_logger().info(
190
+ f"Certificate expiry check completed: {health_status} ({days_until_expiry} days)"
191
+ )
192
+
193
+ return SuccessResult(
194
+ data={
195
+ "monitor_result": {
196
+ "is_expired": is_expired,
197
+ "health_status": health_status,
198
+ "days_until_expiry": days_until_expiry,
199
+ "expiry_date": expiry_date,
200
+ "warning_days": warning_days,
201
+ "critical_days": critical_days,
202
+ }
203
+ }
204
+ )
205
+
206
+ except Exception as e:
207
+ get_global_logger().error(f"Certificate expiry check failed: {e}")
208
+ return ErrorResult(message=f"Certificate expiry check failed: {str(e)}")
209
+
210
+ async def cert_health_check(self, cert_path: str) -> CommandResult:
211
+ """
212
+ Perform comprehensive health check on certificate.
213
+
214
+ Args:
215
+ cert_path: Path to certificate file
216
+
217
+ Returns:
218
+ CommandResult with health check results
219
+ """
220
+ try:
221
+ get_global_logger().info(f"Performing certificate health check for {cert_path}")
222
+
223
+ # Check if certificate file exists
224
+ if not os.path.exists(cert_path):
225
+ return ErrorResult(message=f"Certificate file not found: {cert_path}")
226
+
227
+ # Get certificate info
228
+ cert_info = self.certificate_utils.get_certificate_info(cert_path)
229
+ if not cert_info:
230
+ return ErrorResult(message="Could not read certificate information")
231
+
232
+ # Validate certificate
233
+ validation = self.auth_validator.validate_certificate(cert_path)
234
+
235
+ # Calculate health score
236
+ health_score = 100
237
+ alerts = []
238
+
239
+ # Check if certificate is valid
240
+ if not validation.is_valid:
241
+ health_score -= 50
242
+ alerts.append(
243
+ f"Certificate validation failed: {validation.error_message}"
244
+ )
245
+
246
+ # Check expiry
247
+ expiry_date = cert_info.get("expiry_date")
248
+ if expiry_date:
249
+ try:
250
+ expiry_datetime = datetime.fromisoformat(
251
+ expiry_date.replace("Z", "+00:00")
252
+ )
253
+ days_until_expiry = (
254
+ expiry_datetime - datetime.now(expiry_datetime.tzinfo)
255
+ ).days
256
+
257
+ if days_until_expiry < 0:
258
+ health_score -= 30
259
+ alerts.append("Certificate has expired")
260
+ elif days_until_expiry <= 7:
261
+ health_score -= 20
262
+ alerts.append(
263
+ f"Certificate expires in {days_until_expiry} days"
264
+ )
265
+ elif days_until_expiry <= 30:
266
+ health_score -= 10
267
+ alerts.append(
268
+ f"Certificate expires in {days_until_expiry} days"
269
+ )
270
+ except ValueError:
271
+ health_score -= 10
272
+ alerts.append("Invalid expiry date format")
273
+
274
+ # Check key strength
275
+ key_size = cert_info.get("key_size", 0)
276
+ if key_size < 2048:
277
+ health_score -= 15
278
+ alerts.append(
279
+ f"Key size {key_size} bits is below recommended 2048 bits"
280
+ )
281
+
282
+ # Determine overall status
283
+ if health_score >= 80:
284
+ overall_status = "healthy"
285
+ elif health_score >= 50:
286
+ overall_status = "warning"
287
+ else:
288
+ overall_status = "critical"
289
+
290
+ get_global_logger().info(
291
+ f"Certificate health check completed: {overall_status} (score: {health_score})"
292
+ )
293
+
294
+ return SuccessResult(
295
+ data={
296
+ "monitor_result": {
297
+ "health_score": health_score,
298
+ "alerts": alerts,
299
+ "expiry_date": expiry_date,
300
+ },
301
+ "health_checks": {"validation": {"passed": validation.is_valid}},
302
+ "overall_status": overall_status,
303
+ }
304
+ )
305
+
306
+ except Exception as e:
307
+ get_global_logger().error(f"Certificate health check failed: {e}")
308
+ return ErrorResult(message=f"Certificate health check failed: {str(e)}")
309
+
310
+ async def cert_alert_setup(
311
+ self, cert_path: str, alert_config: Dict[str, Any]
312
+ ) -> CommandResult:
313
+ """
314
+ Set up certificate monitoring alerts.
315
+
316
+ Args:
317
+ cert_path: Path to certificate file
318
+ alert_config: Alert configuration dictionary
319
+
320
+ Returns:
321
+ CommandResult with alert setup status
322
+ """
323
+ try:
324
+ get_global_logger().info(f"Setting up certificate monitoring alerts for {cert_path}")
325
+
326
+ # Check if certificate file exists
327
+ if not os.path.exists(cert_path):
328
+ return ErrorResult(message=f"Certificate file not found: {cert_path}")
329
+
330
+ # Validate alert configuration
331
+ if not isinstance(alert_config, dict):
332
+ return ErrorResult(message="Alert configuration must be a dictionary")
333
+
334
+ # Check if alerts are disabled
335
+ if not alert_config.get("enabled", True):
336
+ return SuccessResult(
337
+ data={
338
+ "monitor_result": {"alerts_enabled": False},
339
+ "message": "Alerts disabled",
340
+ }
341
+ )
342
+
343
+ # Validate required fields
344
+ required_fields = ["warning_days", "critical_days"]
345
+ for field in required_fields:
346
+ if field not in alert_config:
347
+ return ErrorResult(
348
+ message=f"Missing required field in alert config: {field}"
349
+ )
350
+
351
+ if alert_config["warning_days"] <= 0 or alert_config["critical_days"] <= 0:
352
+ return ErrorResult(message="Warning and critical days must be positive")
353
+
354
+ if alert_config["warning_days"] <= alert_config["critical_days"]:
355
+ return ErrorResult(
356
+ message="Warning days must be greater than critical days"
357
+ )
358
+
359
+ # Check notification channels
360
+ notification_channels = alert_config.get("notification_channels", [])
361
+ if not notification_channels:
362
+ return ErrorResult(
363
+ message="At least one notification channel must be specified"
364
+ )
365
+
366
+ # Test alert configuration
367
+ test_result = await self._test_alert_config(alert_config)
368
+ if not test_result["success"]:
369
+ return ErrorResult(
370
+ message=f"Alert configuration test failed: {test_result['error']}"
371
+ )
372
+
373
+ # Save alert configuration
374
+ config_path = "/tmp/cert_alert_config.json"
375
+ with open(config_path, "w") as f:
376
+ json.dump(alert_config, f, indent=2)
377
+
378
+ get_global_logger().info(f"Alert configuration saved to {config_path}")
379
+
380
+ return SuccessResult(
381
+ data={
382
+ "monitor_result": {"alerts_enabled": True},
383
+ "alert_config": alert_config,
384
+ "config_path": config_path,
385
+ "setup_date": datetime.now().isoformat(),
386
+ "message": "Alerts configured successfully",
387
+ }
388
+ )
389
+
390
+ except Exception as e:
391
+ get_global_logger().error(f"Alert setup failed: {e}")
392
+ return ErrorResult(message=f"Alert setup failed: {str(e)}")
393
+
394
+ async def cert_auto_renew(
395
+ self, cert_path: str, auto_renew_config: Dict[str, Any]
396
+ ) -> CommandResult:
397
+ """
398
+ Set up certificate auto-renewal.
399
+
400
+ Args:
401
+ cert_path: Path to certificate file
402
+ auto_renew_config: Auto-renewal configuration dictionary
403
+
404
+ Returns:
405
+ CommandResult with auto-renewal setup status
406
+ """
407
+ try:
408
+ get_global_logger().info(f"Setting up certificate auto-renewal for {cert_path}")
409
+
410
+ # Check if certificate file exists
411
+ if not os.path.exists(cert_path):
412
+ return ErrorResult(message=f"Certificate file not found: {cert_path}")
413
+
414
+ # Validate auto-renewal configuration
415
+ if not isinstance(auto_renew_config, dict):
416
+ return ErrorResult(
417
+ message="Auto-renewal configuration must be a dictionary"
418
+ )
419
+
420
+ # Check if auto-renewal is disabled
421
+ if not auto_renew_config.get("enabled", True):
422
+ return SuccessResult(
423
+ data={
424
+ "monitor_result": {"auto_renewal_enabled": False},
425
+ "message": "Auto-renewal disabled",
426
+ }
427
+ )
428
+
429
+ # Validate required fields
430
+ required_fields = ["renew_before_days", "ca_cert_path", "ca_key_path"]
431
+ for field in required_fields:
432
+ if field not in auto_renew_config:
433
+ return ErrorResult(
434
+ message=f"Missing required field in auto-renewal config: {field}"
435
+ )
436
+
437
+ if auto_renew_config["renew_before_days"] <= 0:
438
+ return ErrorResult(message="Renew before days must be positive")
439
+
440
+ # Check CA files
441
+ ca_cert_path = auto_renew_config["ca_cert_path"]
442
+ ca_key_path = auto_renew_config["ca_key_path"]
443
+
444
+ if not os.path.exists(ca_cert_path):
445
+ return ErrorResult(message=f"CA certificate not found: {ca_cert_path}")
446
+
447
+ if not os.path.exists(ca_key_path):
448
+ return ErrorResult(message=f"CA private key not found: {ca_key_path}")
449
+
450
+ # Check output directory
451
+ output_dir = auto_renew_config.get("output_dir")
452
+ if not output_dir:
453
+ return ErrorResult(message="Output directory must be specified")
454
+
455
+ # Test renewal configuration
456
+ test_result = await self._test_renewal_config(cert_path, auto_renew_config)
457
+ if not test_result["success"]:
458
+ return ErrorResult(
459
+ message=f"Renewal configuration test failed: {test_result['error']}"
460
+ )
461
+
462
+ # Save auto-renewal configuration
463
+ config_path = "/tmp/cert_auto_renew_config.json"
464
+ with open(config_path, "w") as f:
465
+ json.dump(auto_renew_config, f, indent=2)
466
+
467
+ get_global_logger().info(f"Auto-renewal configuration saved to {config_path}")
468
+
469
+ return SuccessResult(
470
+ data={
471
+ "monitor_result": {"auto_renewal_enabled": True},
472
+ "auto_renew_config": auto_renew_config,
473
+ "config_path": config_path,
474
+ "setup_date": datetime.now().isoformat(),
475
+ "message": "Auto-renewal configured successfully",
476
+ }
477
+ )
478
+
479
+ except Exception as e:
480
+ get_global_logger().error(f"Auto-renewal setup failed: {e}")
481
+ return ErrorResult(message=f"Auto-renewal setup failed: {str(e)}")
482
+
483
+
484
+ async def _test_alert_config(self, alert_config: Dict[str, Any]) -> Dict[str, Any]:
485
+ """
486
+ Test alert configuration.
487
+
488
+ Args:
489
+ alert_config: Alert configuration to test
490
+
491
+ Returns:
492
+ Test result dictionary
493
+ """
494
+ try:
495
+ # Test email configuration if present
496
+ if "email_recipients" in alert_config:
497
+ recipients = alert_config["email_recipients"]
498
+ if not isinstance(recipients, list) or not recipients:
499
+ return {"success": False, "error": "Invalid email recipients"}
500
+
501
+ # Test webhook configuration if present
502
+ if "webhook_url" in alert_config:
503
+ webhook_url = alert_config["webhook_url"]
504
+ if not isinstance(webhook_url, str) or not webhook_url:
505
+ return {"success": False, "error": "Invalid webhook URL"}
506
+
507
+ return {"success": True}
508
+
509
+ except Exception as e:
510
+ return {"success": False, "error": str(e)}
511
+
512
+ async def _test_renewal_config(
513
+ self, cert_path: str, renewal_config: Dict[str, Any]
514
+ ) -> Dict[str, Any]:
515
+ """
516
+ Test renewal configuration.
517
+
518
+ Args:
519
+ cert_path: Path to certificate file
520
+ renewal_config: Renewal configuration to test
521
+
522
+ Returns:
523
+ Test result dictionary
524
+ """
525
+ try:
526
+ # Get certificate info
527
+ cert_info = self.certificate_utils.get_certificate_info(cert_path)
528
+ if not cert_info:
529
+ return {
530
+ "success": False,
531
+ "error": "Could not read certificate information",
532
+ }
533
+
534
+ # Check CA certificate
535
+ ca_cert_path = renewal_config.get("ca_cert_path")
536
+ if not ca_cert_path or not os.path.exists(ca_cert_path):
537
+ return {"success": False, "error": "CA certificate not found"}
538
+
539
+ # Check CA key
540
+ ca_key_path = renewal_config.get("ca_key_path")
541
+ if not ca_key_path or not os.path.exists(ca_key_path):
542
+ return {"success": False, "error": "CA private key not found"}
543
+
544
+ # Check output directory
545
+ output_dir = renewal_config.get("output_dir")
546
+ if not output_dir or not os.path.exists(output_dir):
547
+ return {"success": False, "error": "Output directory not found"}
548
+
549
+ return {"success": True}
550
+
551
+ except Exception as e:
552
+ return {"success": False, "error": str(e)}