mcp-proxy-adapter 6.3.4__py3-none-any.whl → 6.3.5__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/__init__.py +9 -5
- mcp_proxy_adapter/__main__.py +1 -1
- mcp_proxy_adapter/api/app.py +227 -176
- mcp_proxy_adapter/api/handlers.py +68 -60
- mcp_proxy_adapter/api/middleware/__init__.py +7 -5
- mcp_proxy_adapter/api/middleware/base.py +19 -16
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
- mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
- mcp_proxy_adapter/api/middleware/factory.py +50 -52
- mcp_proxy_adapter/api/middleware/logging.py +46 -30
- mcp_proxy_adapter/api/middleware/performance.py +19 -16
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
- mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
- mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
- mcp_proxy_adapter/api/schemas.py +69 -43
- mcp_proxy_adapter/api/tool_integration.py +83 -63
- mcp_proxy_adapter/api/tools.py +60 -50
- mcp_proxy_adapter/commands/__init__.py +15 -6
- mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
- mcp_proxy_adapter/commands/base.py +108 -112
- mcp_proxy_adapter/commands/builtin_commands.py +28 -18
- mcp_proxy_adapter/commands/catalog_manager.py +394 -265
- mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
- mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
- mcp_proxy_adapter/commands/command_registry.py +275 -226
- mcp_proxy_adapter/commands/config_command.py +48 -33
- mcp_proxy_adapter/commands/dependency_container.py +22 -23
- mcp_proxy_adapter/commands/dependency_manager.py +65 -56
- mcp_proxy_adapter/commands/echo_command.py +15 -15
- mcp_proxy_adapter/commands/health_command.py +31 -29
- mcp_proxy_adapter/commands/help_command.py +97 -61
- mcp_proxy_adapter/commands/hooks.py +65 -49
- mcp_proxy_adapter/commands/key_management_command.py +148 -147
- mcp_proxy_adapter/commands/load_command.py +58 -40
- mcp_proxy_adapter/commands/plugins_command.py +80 -54
- mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
- mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
- mcp_proxy_adapter/commands/reload_command.py +43 -37
- mcp_proxy_adapter/commands/result.py +26 -33
- mcp_proxy_adapter/commands/role_test_command.py +26 -26
- mcp_proxy_adapter/commands/roles_management_command.py +176 -173
- mcp_proxy_adapter/commands/security_command.py +134 -122
- mcp_proxy_adapter/commands/settings_command.py +47 -56
- mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
- mcp_proxy_adapter/commands/token_management_command.py +129 -158
- mcp_proxy_adapter/commands/transport_management_command.py +41 -36
- mcp_proxy_adapter/commands/unload_command.py +42 -37
- mcp_proxy_adapter/config.py +36 -35
- mcp_proxy_adapter/core/__init__.py +19 -21
- mcp_proxy_adapter/core/app_factory.py +30 -9
- mcp_proxy_adapter/core/app_runner.py +81 -64
- mcp_proxy_adapter/core/auth_validator.py +176 -182
- mcp_proxy_adapter/core/certificate_utils.py +469 -426
- mcp_proxy_adapter/core/client.py +155 -126
- mcp_proxy_adapter/core/client_manager.py +60 -54
- mcp_proxy_adapter/core/client_security.py +108 -88
- mcp_proxy_adapter/core/config_converter.py +176 -143
- mcp_proxy_adapter/core/config_validator.py +12 -4
- mcp_proxy_adapter/core/crl_utils.py +21 -7
- mcp_proxy_adapter/core/errors.py +64 -20
- mcp_proxy_adapter/core/logging.py +34 -29
- mcp_proxy_adapter/core/mtls_asgi.py +29 -25
- mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
- mcp_proxy_adapter/core/protocol_manager.py +154 -104
- mcp_proxy_adapter/core/proxy_client.py +202 -144
- mcp_proxy_adapter/core/proxy_registration.py +7 -3
- mcp_proxy_adapter/core/role_utils.py +139 -125
- mcp_proxy_adapter/core/security_adapter.py +88 -77
- mcp_proxy_adapter/core/security_factory.py +50 -44
- mcp_proxy_adapter/core/security_integration.py +72 -24
- mcp_proxy_adapter/core/server_adapter.py +68 -64
- mcp_proxy_adapter/core/server_engine.py +71 -53
- mcp_proxy_adapter/core/settings.py +68 -58
- mcp_proxy_adapter/core/ssl_utils.py +69 -56
- mcp_proxy_adapter/core/transport_manager.py +72 -60
- mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
- mcp_proxy_adapter/core/utils.py +4 -2
- mcp_proxy_adapter/custom_openapi.py +107 -99
- mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/commands/__init__.py +1 -1
- mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
- mcp_proxy_adapter/examples/debug_request_state.py +38 -19
- mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
- mcp_proxy_adapter/examples/demo_client.py +48 -36
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
- mcp_proxy_adapter/examples/generate_certificates.py +31 -16
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
- mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
- mcp_proxy_adapter/examples/run_example.py +23 -5
- mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
- mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
- mcp_proxy_adapter/examples/run_security_tests.py +103 -41
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
- mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/security_test_client.py +196 -127
- mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
- mcp_proxy_adapter/examples/test_config.py +19 -4
- mcp_proxy_adapter/examples/test_config_generator.py +23 -7
- mcp_proxy_adapter/examples/test_examples.py +84 -56
- mcp_proxy_adapter/examples/universal_client.py +119 -62
- mcp_proxy_adapter/openapi.py +108 -115
- mcp_proxy_adapter/utils/config_generator.py +429 -274
- mcp_proxy_adapter/version.py +1 -2
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
- mcp_proxy_adapter-6.3.4.dist-info/RECORD +0 -143
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -21,11 +21,17 @@ logger = logging.getLogger(__name__)
|
|
21
21
|
|
22
22
|
class SecurityResult(CommandResult):
|
23
23
|
"""Result class for security operations."""
|
24
|
-
|
25
|
-
def __init__(
|
24
|
+
|
25
|
+
def __init__(
|
26
|
+
self,
|
27
|
+
operation: str,
|
28
|
+
success: bool,
|
29
|
+
data: Dict[str, Any] = None,
|
30
|
+
error: str = None,
|
31
|
+
):
|
26
32
|
"""
|
27
33
|
Initialize security result.
|
28
|
-
|
34
|
+
|
29
35
|
Args:
|
30
36
|
operation: Security operation performed
|
31
37
|
success: Whether operation was successful
|
@@ -36,42 +42,48 @@ class SecurityResult(CommandResult):
|
|
36
42
|
self.success = success
|
37
43
|
self.data = data or {}
|
38
44
|
self.error = error
|
39
|
-
|
45
|
+
|
40
46
|
def to_dict(self) -> Dict[str, Any]:
|
41
47
|
"""Convert to dictionary."""
|
42
48
|
return {
|
43
49
|
"operation": self.operation,
|
44
50
|
"success": self.success,
|
45
51
|
"data": self.data,
|
46
|
-
"error": self.error
|
52
|
+
"error": self.error,
|
47
53
|
}
|
48
|
-
|
54
|
+
|
49
55
|
@classmethod
|
50
56
|
def get_schema(cls) -> Dict[str, Any]:
|
51
57
|
"""Get result schema."""
|
52
58
|
return {
|
53
59
|
"type": "object",
|
54
60
|
"properties": {
|
55
|
-
"operation": {
|
56
|
-
|
61
|
+
"operation": {
|
62
|
+
"type": "string",
|
63
|
+
"description": "Security operation performed",
|
64
|
+
},
|
65
|
+
"success": {
|
66
|
+
"type": "boolean",
|
67
|
+
"description": "Whether operation was successful",
|
68
|
+
},
|
57
69
|
"data": {"type": "object", "description": "Operation data"},
|
58
|
-
"error": {"type": "string", "description": "Error message if any"}
|
70
|
+
"error": {"type": "string", "description": "Error message if any"},
|
59
71
|
},
|
60
|
-
"required": ["operation", "success"]
|
72
|
+
"required": ["operation", "success"],
|
61
73
|
}
|
62
74
|
|
63
75
|
|
64
76
|
class SecurityCommand(Command):
|
65
77
|
"""
|
66
78
|
Security command using mcp_security_framework.
|
67
|
-
|
79
|
+
|
68
80
|
Provides direct access to security framework functionality:
|
69
81
|
- Authentication (API key, JWT, certificate)
|
70
82
|
- Certificate management
|
71
83
|
- Permission management
|
72
84
|
- Rate limiting
|
73
85
|
"""
|
74
|
-
|
86
|
+
|
75
87
|
# Command metadata
|
76
88
|
name = "security"
|
77
89
|
version = "1.0.0"
|
@@ -81,20 +93,22 @@ class SecurityCommand(Command):
|
|
81
93
|
email = "team@mcp-proxy-adapter.com"
|
82
94
|
source_url = "https://github.com/mcp-proxy-adapter"
|
83
95
|
result_class = SecurityResult
|
84
|
-
|
96
|
+
|
85
97
|
def __init__(self, config: Dict[str, Any]):
|
86
98
|
"""Initialize security command."""
|
87
99
|
super().__init__()
|
88
100
|
self.config = config
|
89
101
|
self.security_integration = create_security_integration(config)
|
90
|
-
|
102
|
+
|
91
103
|
if not self.security_integration:
|
92
|
-
logger.warning(
|
93
|
-
|
104
|
+
logger.warning(
|
105
|
+
"Security framework not available, security command will fail"
|
106
|
+
)
|
107
|
+
|
94
108
|
async def execute(self, **kwargs) -> CommandResult:
|
95
109
|
"""
|
96
110
|
Execute security command.
|
97
|
-
|
111
|
+
|
98
112
|
Args:
|
99
113
|
**kwargs: Command parameters including:
|
100
114
|
- action: Action to perform (auth, cert, permission, rate_limit, status)
|
@@ -107,7 +121,7 @@ class SecurityCommand(Command):
|
|
107
121
|
- permission: Permission to check
|
108
122
|
- role: Role for operations
|
109
123
|
- identifier: Identifier for rate limiting
|
110
|
-
|
124
|
+
|
111
125
|
Returns:
|
112
126
|
CommandResult with security operation status
|
113
127
|
"""
|
@@ -115,11 +129,11 @@ class SecurityCommand(Command):
|
|
115
129
|
return SecurityResult(
|
116
130
|
operation="security",
|
117
131
|
success=False,
|
118
|
-
error="Security framework not available"
|
132
|
+
error="Security framework not available",
|
119
133
|
)
|
120
|
-
|
134
|
+
|
121
135
|
action = kwargs.get("action", "status")
|
122
|
-
|
136
|
+
|
123
137
|
try:
|
124
138
|
if action == "auth":
|
125
139
|
return await self._handle_auth(kwargs)
|
@@ -133,32 +147,28 @@ class SecurityCommand(Command):
|
|
133
147
|
return await self._handle_status(kwargs)
|
134
148
|
else:
|
135
149
|
return SecurityResult(
|
136
|
-
operation=action,
|
137
|
-
success=False,
|
138
|
-
error=f"Unknown action: {action}"
|
150
|
+
operation=action, success=False, error=f"Unknown action: {action}"
|
139
151
|
)
|
140
|
-
|
152
|
+
|
141
153
|
except Exception as e:
|
142
154
|
logger.error(f"Security command error: {e}")
|
143
155
|
return SecurityResult(
|
144
156
|
operation=action,
|
145
157
|
success=False,
|
146
|
-
error=f"Security operation failed: {str(e)}"
|
158
|
+
error=f"Security operation failed: {str(e)}",
|
147
159
|
)
|
148
|
-
|
160
|
+
|
149
161
|
async def _handle_auth(self, kwargs: Dict[str, Any]) -> SecurityResult:
|
150
162
|
"""Handle authentication operations."""
|
151
163
|
method = kwargs.get("method", "api_key")
|
152
|
-
|
164
|
+
|
153
165
|
if method == "api_key":
|
154
166
|
api_key = kwargs.get("api_key")
|
155
167
|
if not api_key:
|
156
168
|
return SecurityResult(
|
157
|
-
operation="auth_api_key",
|
158
|
-
success=False,
|
159
|
-
error="API key required"
|
169
|
+
operation="auth_api_key", success=False, error="API key required"
|
160
170
|
)
|
161
|
-
|
171
|
+
|
162
172
|
result = await self.security_integration.authenticate_api_key(api_key)
|
163
173
|
return SecurityResult(
|
164
174
|
operation="auth_api_key",
|
@@ -166,20 +176,18 @@ class SecurityCommand(Command):
|
|
166
176
|
data={
|
167
177
|
"user_id": result.user_id,
|
168
178
|
"roles": result.roles,
|
169
|
-
"permissions": result.permissions
|
179
|
+
"permissions": result.permissions,
|
170
180
|
},
|
171
|
-
error=result.error_message if not result.is_valid else None
|
181
|
+
error=result.error_message if not result.is_valid else None,
|
172
182
|
)
|
173
|
-
|
183
|
+
|
174
184
|
elif method == "jwt":
|
175
185
|
token = kwargs.get("token")
|
176
186
|
if not token:
|
177
187
|
return SecurityResult(
|
178
|
-
operation="auth_jwt",
|
179
|
-
success=False,
|
180
|
-
error="JWT token required"
|
188
|
+
operation="auth_jwt", success=False, error="JWT token required"
|
181
189
|
)
|
182
|
-
|
190
|
+
|
183
191
|
result = await self.security_integration.authenticate_jwt(token)
|
184
192
|
return SecurityResult(
|
185
193
|
operation="auth_jwt",
|
@@ -187,287 +195,291 @@ class SecurityCommand(Command):
|
|
187
195
|
data={
|
188
196
|
"user_id": result.user_id,
|
189
197
|
"roles": result.roles,
|
190
|
-
"permissions": result.permissions
|
198
|
+
"permissions": result.permissions,
|
191
199
|
},
|
192
|
-
error=result.error_message if not result.is_valid else None
|
200
|
+
error=result.error_message if not result.is_valid else None,
|
193
201
|
)
|
194
|
-
|
202
|
+
|
195
203
|
elif method == "certificate":
|
196
204
|
cert_path = kwargs.get("cert_path")
|
197
205
|
if not cert_path:
|
198
206
|
return SecurityResult(
|
199
207
|
operation="auth_certificate",
|
200
208
|
success=False,
|
201
|
-
error="Certificate path required"
|
209
|
+
error="Certificate path required",
|
202
210
|
)
|
203
|
-
|
211
|
+
|
204
212
|
# Read certificate data
|
205
213
|
try:
|
206
|
-
with open(cert_path,
|
214
|
+
with open(cert_path, "rb") as f:
|
207
215
|
cert_data = f.read()
|
208
|
-
|
209
|
-
result = await self.security_integration.authenticate_certificate(
|
216
|
+
|
217
|
+
result = await self.security_integration.authenticate_certificate(
|
218
|
+
cert_data
|
219
|
+
)
|
210
220
|
return SecurityResult(
|
211
221
|
operation="auth_certificate",
|
212
222
|
success=result.is_valid,
|
213
223
|
data={
|
214
224
|
"user_id": result.user_id,
|
215
225
|
"roles": result.roles,
|
216
|
-
"permissions": result.permissions
|
226
|
+
"permissions": result.permissions,
|
217
227
|
},
|
218
|
-
error=result.error_message if not result.is_valid else None
|
228
|
+
error=result.error_message if not result.is_valid else None,
|
219
229
|
)
|
220
230
|
except Exception as e:
|
221
231
|
return SecurityResult(
|
222
232
|
operation="auth_certificate",
|
223
233
|
success=False,
|
224
|
-
error=f"Failed to read certificate: {str(e)}"
|
234
|
+
error=f"Failed to read certificate: {str(e)}",
|
225
235
|
)
|
226
|
-
|
236
|
+
|
227
237
|
else:
|
228
238
|
return SecurityResult(
|
229
239
|
operation="auth",
|
230
240
|
success=False,
|
231
|
-
error=f"Unknown authentication method: {method}"
|
241
|
+
error=f"Unknown authentication method: {method}",
|
232
242
|
)
|
233
|
-
|
243
|
+
|
234
244
|
async def _handle_certificate(self, kwargs: Dict[str, Any]) -> SecurityResult:
|
235
245
|
"""Handle certificate operations."""
|
236
246
|
cert_action = kwargs.get("cert_action", "validate")
|
237
|
-
|
247
|
+
|
238
248
|
if cert_action == "create_ca":
|
239
249
|
common_name = kwargs.get("common_name")
|
240
250
|
if not common_name:
|
241
251
|
return SecurityResult(
|
242
252
|
operation="cert_create_ca",
|
243
253
|
success=False,
|
244
|
-
error="Common name required"
|
254
|
+
error="Common name required",
|
245
255
|
)
|
246
|
-
|
256
|
+
|
247
257
|
try:
|
248
|
-
cert_pair = await self.security_integration.create_ca_certificate(
|
258
|
+
cert_pair = await self.security_integration.create_ca_certificate(
|
259
|
+
common_name
|
260
|
+
)
|
249
261
|
return SecurityResult(
|
250
262
|
operation="cert_create_ca",
|
251
263
|
success=True,
|
252
264
|
data={
|
253
265
|
"cert_path": str(cert_pair.cert_path),
|
254
266
|
"key_path": str(cert_pair.key_path),
|
255
|
-
"common_name": common_name
|
256
|
-
}
|
267
|
+
"common_name": common_name,
|
268
|
+
},
|
257
269
|
)
|
258
270
|
except Exception as e:
|
259
271
|
return SecurityResult(
|
260
272
|
operation="cert_create_ca",
|
261
273
|
success=False,
|
262
|
-
error=f"Failed to create CA certificate: {str(e)}"
|
274
|
+
error=f"Failed to create CA certificate: {str(e)}",
|
263
275
|
)
|
264
|
-
|
276
|
+
|
265
277
|
elif cert_action == "create_client":
|
266
278
|
common_name = kwargs.get("common_name")
|
267
279
|
if not common_name:
|
268
280
|
return SecurityResult(
|
269
281
|
operation="cert_create_client",
|
270
282
|
success=False,
|
271
|
-
error="Common name required"
|
283
|
+
error="Common name required",
|
272
284
|
)
|
273
|
-
|
285
|
+
|
274
286
|
try:
|
275
|
-
cert_pair = await self.security_integration.create_client_certificate(
|
287
|
+
cert_pair = await self.security_integration.create_client_certificate(
|
288
|
+
common_name
|
289
|
+
)
|
276
290
|
return SecurityResult(
|
277
291
|
operation="cert_create_client",
|
278
292
|
success=True,
|
279
293
|
data={
|
280
294
|
"cert_path": str(cert_pair.cert_path),
|
281
295
|
"key_path": str(cert_pair.key_path),
|
282
|
-
"common_name": common_name
|
283
|
-
}
|
296
|
+
"common_name": common_name,
|
297
|
+
},
|
284
298
|
)
|
285
299
|
except Exception as e:
|
286
300
|
return SecurityResult(
|
287
301
|
operation="cert_create_client",
|
288
302
|
success=False,
|
289
|
-
error=f"Failed to create client certificate: {str(e)}"
|
303
|
+
error=f"Failed to create client certificate: {str(e)}",
|
290
304
|
)
|
291
|
-
|
305
|
+
|
292
306
|
elif cert_action == "validate":
|
293
307
|
cert_path = kwargs.get("cert_path")
|
294
308
|
if not cert_path:
|
295
309
|
return SecurityResult(
|
296
310
|
operation="cert_validate",
|
297
311
|
success=False,
|
298
|
-
error="Certificate path required"
|
312
|
+
error="Certificate path required",
|
299
313
|
)
|
300
|
-
|
314
|
+
|
301
315
|
try:
|
302
|
-
is_valid = await self.security_integration.validate_certificate(
|
316
|
+
is_valid = await self.security_integration.validate_certificate(
|
317
|
+
cert_path
|
318
|
+
)
|
303
319
|
return SecurityResult(
|
304
320
|
operation="cert_validate",
|
305
321
|
success=is_valid,
|
306
|
-
data={"cert_path": cert_path, "valid": is_valid}
|
322
|
+
data={"cert_path": cert_path, "valid": is_valid},
|
307
323
|
)
|
308
324
|
except Exception as e:
|
309
325
|
return SecurityResult(
|
310
326
|
operation="cert_validate",
|
311
327
|
success=False,
|
312
|
-
error=f"Failed to validate certificate: {str(e)}"
|
328
|
+
error=f"Failed to validate certificate: {str(e)}",
|
313
329
|
)
|
314
|
-
|
330
|
+
|
315
331
|
elif cert_action == "extract_roles":
|
316
332
|
cert_path = kwargs.get("cert_path")
|
317
333
|
if not cert_path:
|
318
334
|
return SecurityResult(
|
319
335
|
operation="cert_extract_roles",
|
320
336
|
success=False,
|
321
|
-
error="Certificate path required"
|
337
|
+
error="Certificate path required",
|
322
338
|
)
|
323
|
-
|
339
|
+
|
324
340
|
try:
|
325
|
-
roles = await self.security_integration.extract_roles_from_certificate(
|
341
|
+
roles = await self.security_integration.extract_roles_from_certificate(
|
342
|
+
cert_path
|
343
|
+
)
|
326
344
|
return SecurityResult(
|
327
345
|
operation="cert_extract_roles",
|
328
346
|
success=True,
|
329
|
-
data={"cert_path": cert_path, "roles": roles}
|
347
|
+
data={"cert_path": cert_path, "roles": roles},
|
330
348
|
)
|
331
349
|
except Exception as e:
|
332
350
|
return SecurityResult(
|
333
351
|
operation="cert_extract_roles",
|
334
352
|
success=False,
|
335
|
-
error=f"Failed to extract roles: {str(e)}"
|
353
|
+
error=f"Failed to extract roles: {str(e)}",
|
336
354
|
)
|
337
|
-
|
355
|
+
|
338
356
|
else:
|
339
357
|
return SecurityResult(
|
340
358
|
operation="cert",
|
341
359
|
success=False,
|
342
|
-
error=f"Unknown certificate action: {cert_action}"
|
360
|
+
error=f"Unknown certificate action: {cert_action}",
|
343
361
|
)
|
344
|
-
|
362
|
+
|
345
363
|
async def _handle_permission(self, kwargs: Dict[str, Any]) -> SecurityResult:
|
346
364
|
"""Handle permission operations."""
|
347
365
|
perm_action = kwargs.get("perm_action", "check")
|
348
366
|
user_id = kwargs.get("user_id")
|
349
|
-
|
367
|
+
|
350
368
|
if not user_id:
|
351
369
|
return SecurityResult(
|
352
|
-
operation="permission",
|
353
|
-
success=False,
|
354
|
-
error="User ID required"
|
370
|
+
operation="permission", success=False, error="User ID required"
|
355
371
|
)
|
356
|
-
|
372
|
+
|
357
373
|
if perm_action == "check":
|
358
374
|
permission = kwargs.get("permission")
|
359
375
|
if not permission:
|
360
376
|
return SecurityResult(
|
361
377
|
operation="permission_check",
|
362
378
|
success=False,
|
363
|
-
error="Permission required"
|
379
|
+
error="Permission required",
|
364
380
|
)
|
365
|
-
|
381
|
+
|
366
382
|
try:
|
367
|
-
has_permission = await self.security_integration.check_permission(
|
383
|
+
has_permission = await self.security_integration.check_permission(
|
384
|
+
user_id, permission
|
385
|
+
)
|
368
386
|
return SecurityResult(
|
369
387
|
operation="permission_check",
|
370
388
|
success=True,
|
371
389
|
data={
|
372
390
|
"user_id": user_id,
|
373
391
|
"permission": permission,
|
374
|
-
"has_permission": has_permission
|
375
|
-
}
|
392
|
+
"has_permission": has_permission,
|
393
|
+
},
|
376
394
|
)
|
377
395
|
except Exception as e:
|
378
396
|
return SecurityResult(
|
379
397
|
operation="permission_check",
|
380
398
|
success=False,
|
381
|
-
error=f"Failed to check permission: {str(e)}"
|
399
|
+
error=f"Failed to check permission: {str(e)}",
|
382
400
|
)
|
383
|
-
|
401
|
+
|
384
402
|
elif perm_action == "get_roles":
|
385
403
|
try:
|
386
404
|
roles = await self.security_integration.get_user_roles(user_id)
|
387
405
|
return SecurityResult(
|
388
406
|
operation="permission_get_roles",
|
389
407
|
success=True,
|
390
|
-
data={"user_id": user_id, "roles": roles}
|
408
|
+
data={"user_id": user_id, "roles": roles},
|
391
409
|
)
|
392
410
|
except Exception as e:
|
393
411
|
return SecurityResult(
|
394
412
|
operation="permission_get_roles",
|
395
413
|
success=False,
|
396
|
-
error=f"Failed to get user roles: {str(e)}"
|
414
|
+
error=f"Failed to get user roles: {str(e)}",
|
397
415
|
)
|
398
|
-
|
416
|
+
|
399
417
|
elif perm_action == "add_role":
|
400
418
|
role = kwargs.get("role")
|
401
419
|
if not role:
|
402
420
|
return SecurityResult(
|
403
421
|
operation="permission_add_role",
|
404
422
|
success=False,
|
405
|
-
error="Role required"
|
423
|
+
error="Role required",
|
406
424
|
)
|
407
|
-
|
425
|
+
|
408
426
|
try:
|
409
427
|
success = await self.security_integration.add_user_role(user_id, role)
|
410
428
|
return SecurityResult(
|
411
429
|
operation="permission_add_role",
|
412
430
|
success=success,
|
413
|
-
data={"user_id": user_id, "role": role, "added": success}
|
431
|
+
data={"user_id": user_id, "role": role, "added": success},
|
414
432
|
)
|
415
433
|
except Exception as e:
|
416
434
|
return SecurityResult(
|
417
435
|
operation="permission_add_role",
|
418
436
|
success=False,
|
419
|
-
error=f"Failed to add role: {str(e)}"
|
437
|
+
error=f"Failed to add role: {str(e)}",
|
420
438
|
)
|
421
|
-
|
439
|
+
|
422
440
|
else:
|
423
441
|
return SecurityResult(
|
424
442
|
operation="permission",
|
425
443
|
success=False,
|
426
|
-
error=f"Unknown permission action: {perm_action}"
|
444
|
+
error=f"Unknown permission action: {perm_action}",
|
427
445
|
)
|
428
|
-
|
446
|
+
|
429
447
|
async def _handle_rate_limit(self, kwargs: Dict[str, Any]) -> SecurityResult:
|
430
448
|
"""Handle rate limiting operations."""
|
431
449
|
identifier = kwargs.get("identifier")
|
432
450
|
if not identifier:
|
433
451
|
return SecurityResult(
|
434
|
-
operation="rate_limit",
|
435
|
-
success=False,
|
436
|
-
error="Identifier required"
|
452
|
+
operation="rate_limit", success=False, error="Identifier required"
|
437
453
|
)
|
438
|
-
|
454
|
+
|
439
455
|
try:
|
440
456
|
# Check rate limit
|
441
457
|
is_allowed = await self.security_integration.check_rate_limit(identifier)
|
442
|
-
|
458
|
+
|
443
459
|
if is_allowed:
|
444
460
|
# Increment counter
|
445
461
|
await self.security_integration.increment_rate_limit(identifier)
|
446
|
-
|
462
|
+
|
447
463
|
# Get rate limit info
|
448
464
|
info = await self.security_integration.get_rate_limit_info(identifier)
|
449
|
-
|
465
|
+
|
450
466
|
return SecurityResult(
|
451
467
|
operation="rate_limit_check",
|
452
468
|
success=True,
|
453
|
-
data={
|
454
|
-
"identifier": identifier,
|
455
|
-
"allowed": is_allowed,
|
456
|
-
"info": info
|
457
|
-
}
|
469
|
+
data={"identifier": identifier, "allowed": is_allowed, "info": info},
|
458
470
|
)
|
459
471
|
except Exception as e:
|
460
472
|
return SecurityResult(
|
461
473
|
operation="rate_limit_check",
|
462
474
|
success=False,
|
463
|
-
error=f"Failed to check rate limit: {str(e)}"
|
475
|
+
error=f"Failed to check rate limit: {str(e)}",
|
464
476
|
)
|
465
|
-
|
477
|
+
|
466
478
|
async def _handle_status(self, kwargs: Dict[str, Any]) -> SecurityResult:
|
467
479
|
"""Handle status operations."""
|
468
480
|
try:
|
469
481
|
security_config = self.security_integration.get_security_config()
|
470
|
-
|
482
|
+
|
471
483
|
return SecurityResult(
|
472
484
|
operation="status",
|
473
485
|
success=True,
|
@@ -478,12 +490,12 @@ class SecurityCommand(Command):
|
|
478
490
|
"ssl_enabled": security_config.ssl.enabled,
|
479
491
|
"permissions_enabled": security_config.permissions.enabled,
|
480
492
|
"rate_limit_enabled": security_config.rate_limit.enabled,
|
481
|
-
"certificates_enabled": security_config.certificates.enabled
|
482
|
-
}
|
493
|
+
"certificates_enabled": security_config.certificates.enabled,
|
494
|
+
},
|
483
495
|
)
|
484
496
|
except Exception as e:
|
485
497
|
return SecurityResult(
|
486
498
|
operation="status",
|
487
499
|
success=False,
|
488
|
-
error=f"Failed to get status: {str(e)}"
|
500
|
+
error=f"Failed to get status: {str(e)}",
|
489
501
|
)
|