mcp-security-framework 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_security_framework/__init__.py +96 -0
- mcp_security_framework/cli/__init__.py +18 -0
- mcp_security_framework/cli/cert_cli.py +511 -0
- mcp_security_framework/cli/security_cli.py +791 -0
- mcp_security_framework/constants.py +209 -0
- mcp_security_framework/core/__init__.py +61 -0
- mcp_security_framework/core/auth_manager.py +1011 -0
- mcp_security_framework/core/cert_manager.py +1663 -0
- mcp_security_framework/core/permission_manager.py +735 -0
- mcp_security_framework/core/rate_limiter.py +602 -0
- mcp_security_framework/core/security_manager.py +943 -0
- mcp_security_framework/core/ssl_manager.py +735 -0
- mcp_security_framework/examples/__init__.py +75 -0
- mcp_security_framework/examples/django_example.py +615 -0
- mcp_security_framework/examples/fastapi_example.py +472 -0
- mcp_security_framework/examples/flask_example.py +506 -0
- mcp_security_framework/examples/gateway_example.py +803 -0
- mcp_security_framework/examples/microservice_example.py +690 -0
- mcp_security_framework/examples/standalone_example.py +576 -0
- mcp_security_framework/middleware/__init__.py +250 -0
- mcp_security_framework/middleware/auth_middleware.py +292 -0
- mcp_security_framework/middleware/fastapi_auth_middleware.py +447 -0
- mcp_security_framework/middleware/fastapi_middleware.py +757 -0
- mcp_security_framework/middleware/flask_auth_middleware.py +465 -0
- mcp_security_framework/middleware/flask_middleware.py +591 -0
- mcp_security_framework/middleware/mtls_middleware.py +439 -0
- mcp_security_framework/middleware/rate_limit_middleware.py +403 -0
- mcp_security_framework/middleware/security_middleware.py +507 -0
- mcp_security_framework/schemas/__init__.py +109 -0
- mcp_security_framework/schemas/config.py +694 -0
- mcp_security_framework/schemas/models.py +709 -0
- mcp_security_framework/schemas/responses.py +686 -0
- mcp_security_framework/tests/__init__.py +0 -0
- mcp_security_framework/utils/__init__.py +121 -0
- mcp_security_framework/utils/cert_utils.py +525 -0
- mcp_security_framework/utils/crypto_utils.py +475 -0
- mcp_security_framework/utils/validation_utils.py +571 -0
- mcp_security_framework-0.1.0.dist-info/METADATA +411 -0
- mcp_security_framework-0.1.0.dist-info/RECORD +76 -0
- mcp_security_framework-0.1.0.dist-info/WHEEL +5 -0
- mcp_security_framework-0.1.0.dist-info/entry_points.txt +3 -0
- mcp_security_framework-0.1.0.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
- tests/test_cli/__init__.py +0 -0
- tests/test_cli/test_cert_cli.py +379 -0
- tests/test_cli/test_security_cli.py +657 -0
- tests/test_core/__init__.py +0 -0
- tests/test_core/test_auth_manager.py +582 -0
- tests/test_core/test_cert_manager.py +795 -0
- tests/test_core/test_permission_manager.py +395 -0
- tests/test_core/test_rate_limiter.py +626 -0
- tests/test_core/test_security_manager.py +841 -0
- tests/test_core/test_ssl_manager.py +532 -0
- tests/test_examples/__init__.py +8 -0
- tests/test_examples/test_fastapi_example.py +264 -0
- tests/test_examples/test_flask_example.py +238 -0
- tests/test_examples/test_standalone_example.py +292 -0
- tests/test_integration/__init__.py +0 -0
- tests/test_integration/test_auth_flow.py +502 -0
- tests/test_integration/test_certificate_flow.py +527 -0
- tests/test_integration/test_fastapi_integration.py +341 -0
- tests/test_integration/test_flask_integration.py +398 -0
- tests/test_integration/test_standalone_integration.py +493 -0
- tests/test_middleware/__init__.py +0 -0
- tests/test_middleware/test_fastapi_middleware.py +523 -0
- tests/test_middleware/test_flask_middleware.py +582 -0
- tests/test_middleware/test_security_middleware.py +493 -0
- tests/test_schemas/__init__.py +0 -0
- tests/test_schemas/test_config.py +811 -0
- tests/test_schemas/test_models.py +879 -0
- tests/test_schemas/test_responses.py +1054 -0
- tests/test_schemas/test_serialization.py +493 -0
- tests/test_utils/__init__.py +0 -0
- tests/test_utils/test_cert_utils.py +510 -0
- tests/test_utils/test_crypto_utils.py +603 -0
- tests/test_utils/test_validation_utils.py +477 -0
@@ -0,0 +1,943 @@
|
|
1
|
+
"""
|
2
|
+
Security Manager Module
|
3
|
+
|
4
|
+
This module provides the main SecurityManager class that integrates all
|
5
|
+
core security components into a unified interface for comprehensive
|
6
|
+
security management.
|
7
|
+
|
8
|
+
Key Features:
|
9
|
+
- Unified interface for all security operations
|
10
|
+
- Integration of authentication, authorization, SSL/TLS, and rate limiting
|
11
|
+
- Factory methods for creating framework-specific middleware
|
12
|
+
- Comprehensive request validation and security checking
|
13
|
+
- Certificate management and validation
|
14
|
+
- Security event logging and monitoring
|
15
|
+
|
16
|
+
Classes:
|
17
|
+
SecurityManager: Main security management class
|
18
|
+
SecurityConfigurationError: Configuration error exception
|
19
|
+
SecurityValidationError: Validation error exception
|
20
|
+
|
21
|
+
Author: MCP Security Team
|
22
|
+
Version: 1.0.0
|
23
|
+
License: MIT
|
24
|
+
"""
|
25
|
+
|
26
|
+
import logging
|
27
|
+
from typing import Dict, List, Optional, Union, Any
|
28
|
+
|
29
|
+
from ..schemas.config import SecurityConfig, AuthConfig, PermissionConfig, CertificateConfig
|
30
|
+
from ..schemas.models import AuthResult, ValidationResult, ValidationStatus, CertificatePair, CertificateInfo, AuthStatus
|
31
|
+
from ..schemas.responses import SecurityResponse, ResponseStatus
|
32
|
+
from .auth_manager import AuthManager
|
33
|
+
from .permission_manager import PermissionManager
|
34
|
+
from .ssl_manager import SSLManager
|
35
|
+
from .cert_manager import CertificateManager
|
36
|
+
from .rate_limiter import RateLimiter
|
37
|
+
|
38
|
+
|
39
|
+
class SecurityConfigurationError(Exception):
|
40
|
+
"""Raised when security configuration is invalid."""
|
41
|
+
|
42
|
+
def __init__(self, message: str, error_code: int = -32001):
|
43
|
+
self.message = message
|
44
|
+
self.error_code = error_code
|
45
|
+
super().__init__(self.message)
|
46
|
+
|
47
|
+
|
48
|
+
class SecurityValidationError(Exception):
|
49
|
+
"""Raised when security validation fails."""
|
50
|
+
|
51
|
+
def __init__(self, message: str, error_code: int = -32002):
|
52
|
+
self.message = message
|
53
|
+
self.error_code = error_code
|
54
|
+
super().__init__(self.message)
|
55
|
+
|
56
|
+
|
57
|
+
class SecurityManager:
|
58
|
+
"""
|
59
|
+
Security Manager Class
|
60
|
+
|
61
|
+
This is the main security management class that integrates all core
|
62
|
+
security components into a unified interface. It provides comprehensive
|
63
|
+
security management including authentication, authorization, SSL/TLS
|
64
|
+
management, certificate management, and rate limiting.
|
65
|
+
|
66
|
+
The SecurityManager serves as the central point for all security
|
67
|
+
operations and provides factory methods for creating framework-specific
|
68
|
+
middleware components.
|
69
|
+
|
70
|
+
Key Responsibilities:
|
71
|
+
- Initialize and manage all core security components
|
72
|
+
- Provide unified interface for security operations
|
73
|
+
- Handle request validation and security checking
|
74
|
+
- Manage certificate lifecycle and validation
|
75
|
+
- Provide factory methods for middleware creation
|
76
|
+
- Coordinate between different security components
|
77
|
+
- Handle security event logging and monitoring
|
78
|
+
|
79
|
+
Attributes:
|
80
|
+
config (SecurityConfig): Main security configuration
|
81
|
+
logger (Logger): Logger instance for security operations
|
82
|
+
auth_manager (AuthManager): Authentication manager instance
|
83
|
+
permission_manager (PermissionManager): Permission manager instance
|
84
|
+
ssl_manager (SSLManager): SSL/TLS manager instance
|
85
|
+
cert_manager (CertificateManager): Certificate manager instance
|
86
|
+
rate_limiter (RateLimiter): Rate limiter instance
|
87
|
+
_component_status (Dict): Status of all security components
|
88
|
+
_security_events (List): Security event log
|
89
|
+
|
90
|
+
Example:
|
91
|
+
>>> config = SecurityConfig(
|
92
|
+
... auth=AuthConfig(enabled=True, methods=["api_key"]),
|
93
|
+
... permissions=PermissionConfig(roles_file="roles.json")
|
94
|
+
... )
|
95
|
+
>>> security_manager = SecurityManager(config)
|
96
|
+
>>> result = security_manager.validate_request({
|
97
|
+
... "api_key": "user_key_123",
|
98
|
+
... "required_permissions": ["read", "write"]
|
99
|
+
... })
|
100
|
+
|
101
|
+
Raises:
|
102
|
+
SecurityConfigurationError: When security configuration is invalid
|
103
|
+
SecurityValidationError: When security validation fails
|
104
|
+
AuthenticationError: When authentication fails
|
105
|
+
PermissionDeniedError: When access is denied
|
106
|
+
"""
|
107
|
+
|
108
|
+
def __init__(self, config: SecurityConfig):
|
109
|
+
"""
|
110
|
+
Initialize Security Manager.
|
111
|
+
|
112
|
+
Args:
|
113
|
+
config (SecurityConfig): Main security configuration containing
|
114
|
+
all component configurations. Must be a valid SecurityConfig
|
115
|
+
instance with proper settings for all security components.
|
116
|
+
|
117
|
+
Raises:
|
118
|
+
SecurityConfigurationError: If configuration is invalid or
|
119
|
+
required components cannot be initialized.
|
120
|
+
|
121
|
+
Example:
|
122
|
+
>>> config = SecurityConfig(
|
123
|
+
... auth=AuthConfig(enabled=True),
|
124
|
+
... permissions=PermissionConfig(roles_file="roles.json")
|
125
|
+
... )
|
126
|
+
>>> security_manager = SecurityManager(config)
|
127
|
+
"""
|
128
|
+
self.config = config
|
129
|
+
self.logger = logging.getLogger(__name__)
|
130
|
+
self._component_status: Dict[str, bool] = {}
|
131
|
+
self._security_events: List[Dict[str, Any]] = []
|
132
|
+
|
133
|
+
# Initialize all core components
|
134
|
+
self._initialize_components()
|
135
|
+
|
136
|
+
# Log initialization
|
137
|
+
self.logger.info(
|
138
|
+
"Security Manager initialized successfully",
|
139
|
+
extra={
|
140
|
+
"environment": config.environment,
|
141
|
+
"version": config.version,
|
142
|
+
"debug": config.debug
|
143
|
+
}
|
144
|
+
)
|
145
|
+
|
146
|
+
def _initialize_components(self) -> None:
|
147
|
+
"""
|
148
|
+
Initialize all core security components.
|
149
|
+
|
150
|
+
This method initializes all core security components based on
|
151
|
+
the provided configuration. It handles component dependencies
|
152
|
+
and validates that all required components are properly configured.
|
153
|
+
|
154
|
+
Raises:
|
155
|
+
SecurityConfigurationError: If any component fails to initialize
|
156
|
+
or required configuration is missing.
|
157
|
+
"""
|
158
|
+
try:
|
159
|
+
# Initialize PermissionManager first (needed by AuthManager)
|
160
|
+
self.permission_manager = PermissionManager(self.config.permissions)
|
161
|
+
self._component_status["permission_manager"] = True
|
162
|
+
|
163
|
+
# Initialize AuthManager (depends on PermissionManager)
|
164
|
+
self.auth_manager = AuthManager(self.config.auth, self.permission_manager)
|
165
|
+
self._component_status["auth_manager"] = True
|
166
|
+
|
167
|
+
# Initialize SSLManager
|
168
|
+
self.ssl_manager = SSLManager(self.config.ssl)
|
169
|
+
self._component_status["ssl_manager"] = True
|
170
|
+
|
171
|
+
# Initialize CertificateManager
|
172
|
+
self.cert_manager = CertificateManager(self.config.certificates)
|
173
|
+
self._component_status["cert_manager"] = True
|
174
|
+
|
175
|
+
# Initialize RateLimiter
|
176
|
+
self.rate_limiter = RateLimiter(self.config.rate_limit)
|
177
|
+
self._component_status["rate_limiter"] = True
|
178
|
+
|
179
|
+
self.logger.info("All security components initialized successfully")
|
180
|
+
|
181
|
+
except Exception as e:
|
182
|
+
self.logger.error(f"Failed to initialize security components: {str(e)}")
|
183
|
+
raise SecurityConfigurationError(
|
184
|
+
f"Failed to initialize security components: {str(e)}",
|
185
|
+
error_code=-32001
|
186
|
+
)
|
187
|
+
|
188
|
+
def validate_request(self, request_data: Dict[str, Any]) -> ValidationResult:
|
189
|
+
"""
|
190
|
+
Validate a complete request for security compliance.
|
191
|
+
|
192
|
+
This method performs comprehensive security validation of a request
|
193
|
+
including authentication, authorization, rate limiting, and any
|
194
|
+
other security checks configured in the system.
|
195
|
+
|
196
|
+
Args:
|
197
|
+
request_data (Dict[str, Any]): Request data containing authentication
|
198
|
+
credentials, required permissions, and other security-related
|
199
|
+
information. Must include authentication method and credentials.
|
200
|
+
|
201
|
+
Returns:
|
202
|
+
ValidationResult: Validation result containing success status,
|
203
|
+
error messages, and validation details.
|
204
|
+
|
205
|
+
Raises:
|
206
|
+
SecurityValidationError: When request validation fails due to
|
207
|
+
security violations or invalid data.
|
208
|
+
|
209
|
+
Example:
|
210
|
+
>>> result = security_manager.validate_request({
|
211
|
+
... "api_key": "user_key_123",
|
212
|
+
... "required_permissions": ["read", "write"],
|
213
|
+
... "client_ip": "192.168.1.100"
|
214
|
+
... })
|
215
|
+
>>> if result.is_valid:
|
216
|
+
... print("Request validated successfully")
|
217
|
+
"""
|
218
|
+
try:
|
219
|
+
# Extract authentication credentials
|
220
|
+
auth_credentials = self._extract_auth_credentials(request_data)
|
221
|
+
|
222
|
+
# Perform authentication
|
223
|
+
auth_result = self.authenticate_user(auth_credentials)
|
224
|
+
if not auth_result.is_valid:
|
225
|
+
return ValidationResult(
|
226
|
+
is_valid=False,
|
227
|
+
status=ValidationStatus.INVALID,
|
228
|
+
error_message=f"Authentication failed: {auth_result.error_message}",
|
229
|
+
error_code=auth_result.error_code
|
230
|
+
)
|
231
|
+
|
232
|
+
# Check rate limiting
|
233
|
+
if not self._check_rate_limit(request_data):
|
234
|
+
return ValidationResult(
|
235
|
+
is_valid=False,
|
236
|
+
status=ValidationStatus.INVALID,
|
237
|
+
error_message="Rate limit exceeded",
|
238
|
+
error_code=-32003
|
239
|
+
)
|
240
|
+
|
241
|
+
# Check permissions
|
242
|
+
required_permissions = request_data.get("required_permissions", [])
|
243
|
+
if required_permissions:
|
244
|
+
permission_result = self.check_permissions(
|
245
|
+
auth_result.roles, required_permissions
|
246
|
+
)
|
247
|
+
if not permission_result.is_valid:
|
248
|
+
return ValidationResult(
|
249
|
+
is_valid=False,
|
250
|
+
status=ValidationStatus.INVALID,
|
251
|
+
error_message=f"Permission denied: {permission_result.error_message}",
|
252
|
+
error_code=permission_result.error_code
|
253
|
+
)
|
254
|
+
|
255
|
+
# Log successful validation
|
256
|
+
self._log_security_event("request_validated", {
|
257
|
+
"user": auth_result.username,
|
258
|
+
"roles": auth_result.roles,
|
259
|
+
"permissions": required_permissions
|
260
|
+
})
|
261
|
+
|
262
|
+
return ValidationResult(
|
263
|
+
is_valid=True,
|
264
|
+
status=ValidationStatus.VALID
|
265
|
+
)
|
266
|
+
|
267
|
+
except Exception as e:
|
268
|
+
self.logger.error(f"Request validation failed: {str(e)}")
|
269
|
+
raise SecurityValidationError(
|
270
|
+
f"Request validation failed: {str(e)}",
|
271
|
+
error_code=-32002
|
272
|
+
)
|
273
|
+
|
274
|
+
def authenticate_user(self, credentials: Dict[str, Any]) -> AuthResult:
|
275
|
+
"""
|
276
|
+
Authenticate a user with provided credentials.
|
277
|
+
|
278
|
+
This method authenticates a user using the configured authentication
|
279
|
+
methods and returns detailed authentication results including user
|
280
|
+
information and roles.
|
281
|
+
|
282
|
+
Args:
|
283
|
+
credentials (Dict[str, Any]): User credentials containing
|
284
|
+
authentication method and corresponding credentials.
|
285
|
+
Supported methods: api_key, jwt, certificate.
|
286
|
+
|
287
|
+
Returns:
|
288
|
+
AuthResult: Authentication result containing success status,
|
289
|
+
user information, roles, and error details.
|
290
|
+
|
291
|
+
Raises:
|
292
|
+
SecurityValidationError: When authentication fails or
|
293
|
+
credentials are invalid.
|
294
|
+
|
295
|
+
Example:
|
296
|
+
>>> result = security_manager.authenticate_user({
|
297
|
+
... "method": "api_key",
|
298
|
+
... "api_key": "user_key_123"
|
299
|
+
... })
|
300
|
+
>>> if result.is_valid:
|
301
|
+
... print(f"Authenticated user: {result.username}")
|
302
|
+
"""
|
303
|
+
try:
|
304
|
+
auth_method = credentials.get("method", "api_key")
|
305
|
+
|
306
|
+
if auth_method == "api_key":
|
307
|
+
api_key = credentials.get("api_key")
|
308
|
+
if not api_key:
|
309
|
+
return AuthResult(
|
310
|
+
is_valid=False,
|
311
|
+
status=AuthStatus.INVALID,
|
312
|
+
auth_method="api_key",
|
313
|
+
error_code=-32001,
|
314
|
+
error_message="API key is required"
|
315
|
+
)
|
316
|
+
return self.auth_manager.authenticate_api_key(api_key)
|
317
|
+
|
318
|
+
elif auth_method == "jwt":
|
319
|
+
token = credentials.get("token")
|
320
|
+
if not token:
|
321
|
+
return AuthResult(
|
322
|
+
is_valid=False,
|
323
|
+
status=AuthStatus.INVALID,
|
324
|
+
auth_method="jwt",
|
325
|
+
error_code=-32001,
|
326
|
+
error_message="JWT token is required"
|
327
|
+
)
|
328
|
+
return self.auth_manager.authenticate_jwt_token(token)
|
329
|
+
|
330
|
+
elif auth_method == "certificate":
|
331
|
+
cert_pem = credentials.get("certificate")
|
332
|
+
if not cert_pem:
|
333
|
+
return AuthResult(
|
334
|
+
is_valid=False,
|
335
|
+
status=AuthStatus.INVALID,
|
336
|
+
auth_method="certificate",
|
337
|
+
error_code=-32001,
|
338
|
+
error_message="Certificate is required"
|
339
|
+
)
|
340
|
+
return self.auth_manager.authenticate_certificate(cert_pem)
|
341
|
+
|
342
|
+
else:
|
343
|
+
raise SecurityValidationError(f"Unsupported authentication method: {auth_method}")
|
344
|
+
|
345
|
+
except SecurityValidationError:
|
346
|
+
# Re-raise SecurityValidationError
|
347
|
+
raise
|
348
|
+
except Exception as e:
|
349
|
+
self.logger.error(f"Authentication failed: {str(e)}")
|
350
|
+
return AuthResult(
|
351
|
+
is_valid=False,
|
352
|
+
status=AuthStatus.INVALID,
|
353
|
+
auth_method="api_key", # Use default for exceptions
|
354
|
+
error_code=-32002,
|
355
|
+
error_message=f"Authentication failed: {str(e)}"
|
356
|
+
)
|
357
|
+
|
358
|
+
def check_permissions(self, user_roles: List[str], required_permissions: List[str]) -> ValidationResult:
|
359
|
+
"""
|
360
|
+
Check if user has required permissions.
|
361
|
+
|
362
|
+
This method validates that the user's roles provide the required
|
363
|
+
permissions for the requested operation.
|
364
|
+
|
365
|
+
Args:
|
366
|
+
user_roles (List[str]): List of user roles to check
|
367
|
+
required_permissions (List[str]): List of required permissions
|
368
|
+
|
369
|
+
Returns:
|
370
|
+
ValidationResult: Validation result containing success status
|
371
|
+
and error details.
|
372
|
+
|
373
|
+
Example:
|
374
|
+
>>> result = security_manager.check_permissions(
|
375
|
+
... ["admin", "user"],
|
376
|
+
... ["read", "write"]
|
377
|
+
... )
|
378
|
+
>>> if result.is_valid:
|
379
|
+
... print("User has required permissions")
|
380
|
+
"""
|
381
|
+
try:
|
382
|
+
return self.permission_manager.validate_access(user_roles, required_permissions)
|
383
|
+
except Exception as e:
|
384
|
+
self.logger.error(f"Permission check failed: {str(e)}")
|
385
|
+
return ValidationResult(
|
386
|
+
is_valid=False,
|
387
|
+
error_message=f"Permission check failed: {str(e)}",
|
388
|
+
error_code=-32004
|
389
|
+
)
|
390
|
+
|
391
|
+
def create_certificate(self, cert_config: CertificateConfig) -> CertificatePair:
|
392
|
+
"""
|
393
|
+
Create a new certificate using the certificate manager.
|
394
|
+
|
395
|
+
This method creates a new certificate based on the provided
|
396
|
+
configuration using the certificate manager.
|
397
|
+
|
398
|
+
Args:
|
399
|
+
cert_config (CertificateConfig): Certificate configuration
|
400
|
+
specifying the type and parameters of certificate to create.
|
401
|
+
|
402
|
+
Returns:
|
403
|
+
CertificatePair: Created certificate pair containing
|
404
|
+
certificate and private key information.
|
405
|
+
|
406
|
+
Raises:
|
407
|
+
SecurityValidationError: When certificate creation fails.
|
408
|
+
|
409
|
+
Example:
|
410
|
+
>>> config = CertificateConfig(
|
411
|
+
... cert_type="client",
|
412
|
+
... common_name="client.example.com"
|
413
|
+
... )
|
414
|
+
>>> cert_pair = security_manager.create_certificate(config)
|
415
|
+
"""
|
416
|
+
try:
|
417
|
+
return self.cert_manager.create_certificate(cert_config)
|
418
|
+
except Exception as e:
|
419
|
+
self.logger.error(f"Certificate creation failed: {str(e)}")
|
420
|
+
raise SecurityValidationError(
|
421
|
+
f"Certificate creation failed: {str(e)}",
|
422
|
+
error_code=-32005
|
423
|
+
)
|
424
|
+
|
425
|
+
def revoke_certificate(self, serial_number: str, reason: str) -> bool:
|
426
|
+
"""
|
427
|
+
Revoke a certificate.
|
428
|
+
|
429
|
+
This method revokes a certificate with the specified serial number
|
430
|
+
and reason using the certificate manager.
|
431
|
+
|
432
|
+
Args:
|
433
|
+
serial_number (str): Certificate serial number to revoke
|
434
|
+
reason (str): Reason for revocation
|
435
|
+
|
436
|
+
Returns:
|
437
|
+
bool: True if certificate was successfully revoked
|
438
|
+
|
439
|
+
Raises:
|
440
|
+
SecurityValidationError: When certificate revocation fails.
|
441
|
+
|
442
|
+
Example:
|
443
|
+
>>> success = security_manager.revoke_certificate(
|
444
|
+
... "1234567890",
|
445
|
+
... "Compromised private key"
|
446
|
+
... )
|
447
|
+
"""
|
448
|
+
try:
|
449
|
+
return self.cert_manager.revoke_certificate(serial_number, reason)
|
450
|
+
except Exception as e:
|
451
|
+
self.logger.error(f"Certificate revocation failed: {str(e)}")
|
452
|
+
raise SecurityValidationError(
|
453
|
+
f"Certificate revocation failed: {str(e)}",
|
454
|
+
error_code=-32006
|
455
|
+
)
|
456
|
+
|
457
|
+
def get_certificate_info(self, cert_path: str) -> CertificateInfo:
|
458
|
+
"""
|
459
|
+
Get information about a certificate.
|
460
|
+
|
461
|
+
This method retrieves detailed information about a certificate
|
462
|
+
using the SSL manager.
|
463
|
+
|
464
|
+
Args:
|
465
|
+
cert_path (str): Path to the certificate file
|
466
|
+
|
467
|
+
Returns:
|
468
|
+
CertificateInfo: Certificate information including subject,
|
469
|
+
issuer, validity dates, and other details.
|
470
|
+
|
471
|
+
Raises:
|
472
|
+
SecurityValidationError: When certificate information
|
473
|
+
retrieval fails.
|
474
|
+
|
475
|
+
Example:
|
476
|
+
>>> info = security_manager.get_certificate_info("server.crt")
|
477
|
+
>>> print(f"Subject: {info.subject}")
|
478
|
+
"""
|
479
|
+
try:
|
480
|
+
return self.ssl_manager.get_certificate_info(cert_path)
|
481
|
+
except Exception as e:
|
482
|
+
self.logger.error(f"Certificate info retrieval failed: {str(e)}")
|
483
|
+
raise SecurityValidationError(
|
484
|
+
f"Certificate info retrieval failed: {str(e)}",
|
485
|
+
error_code=-32007
|
486
|
+
)
|
487
|
+
|
488
|
+
def create_ssl_context(self, context_type: str = "server", **kwargs) -> Any:
|
489
|
+
"""
|
490
|
+
Create SSL context for server or client.
|
491
|
+
|
492
|
+
This method creates an SSL context for either server or client
|
493
|
+
operations using the SSL manager.
|
494
|
+
|
495
|
+
Args:
|
496
|
+
context_type (str): Type of SSL context ("server" or "client")
|
497
|
+
**kwargs: Additional SSL context parameters
|
498
|
+
|
499
|
+
Returns:
|
500
|
+
Any: SSL context object
|
501
|
+
|
502
|
+
Raises:
|
503
|
+
SecurityValidationError: When SSL context creation fails.
|
504
|
+
|
505
|
+
Example:
|
506
|
+
>>> context = security_manager.create_ssl_context(
|
507
|
+
... "server",
|
508
|
+
... cert_file="server.crt",
|
509
|
+
... key_file="server.key"
|
510
|
+
... )
|
511
|
+
"""
|
512
|
+
try:
|
513
|
+
if context_type == "server":
|
514
|
+
return self.ssl_manager.create_server_context(**kwargs)
|
515
|
+
elif context_type == "client":
|
516
|
+
return self.ssl_manager.create_client_context(**kwargs)
|
517
|
+
else:
|
518
|
+
raise SecurityValidationError(f"Invalid context type: {context_type}")
|
519
|
+
except Exception as e:
|
520
|
+
self.logger.error(f"SSL context creation failed: {str(e)}")
|
521
|
+
raise SecurityValidationError(
|
522
|
+
f"SSL context creation failed: {str(e)}",
|
523
|
+
error_code=-32008
|
524
|
+
)
|
525
|
+
|
526
|
+
def check_rate_limit(self, identifier: str) -> bool:
|
527
|
+
"""
|
528
|
+
Check if rate limit is exceeded for the given identifier.
|
529
|
+
|
530
|
+
This method checks if the rate limit is exceeded for the specified
|
531
|
+
identifier using the rate limiter.
|
532
|
+
|
533
|
+
Args:
|
534
|
+
identifier (str): Identifier to check (e.g., IP address, user ID)
|
535
|
+
|
536
|
+
Returns:
|
537
|
+
bool: True if rate limit is not exceeded, False otherwise
|
538
|
+
|
539
|
+
Example:
|
540
|
+
>>> if security_manager.check_rate_limit("192.168.1.100"):
|
541
|
+
... print("Rate limit not exceeded")
|
542
|
+
"""
|
543
|
+
try:
|
544
|
+
return self.rate_limiter.check_rate_limit(identifier)
|
545
|
+
except Exception as e:
|
546
|
+
self.logger.error(f"Rate limit check failed: {str(e)}")
|
547
|
+
return False
|
548
|
+
|
549
|
+
def get_security_status(self) -> SecurityResponse:
|
550
|
+
"""
|
551
|
+
Get comprehensive security status information.
|
552
|
+
|
553
|
+
This method returns detailed status information about all
|
554
|
+
security components and their current state.
|
555
|
+
|
556
|
+
Returns:
|
557
|
+
SecurityResponse: Security status response containing
|
558
|
+
component status, configuration info, and health metrics.
|
559
|
+
|
560
|
+
Example:
|
561
|
+
>>> status = security_manager.get_security_status()
|
562
|
+
>>> print(f"SSL enabled: {status.ssl_enabled}")
|
563
|
+
"""
|
564
|
+
try:
|
565
|
+
return SecurityResponse(
|
566
|
+
status=ResponseStatus.SUCCESS,
|
567
|
+
message="Security system healthy",
|
568
|
+
ssl_enabled=self.ssl_manager.is_ssl_enabled,
|
569
|
+
auth_enabled=self.auth_manager.is_auth_enabled,
|
570
|
+
rate_limiting_enabled=self.rate_limiter.is_rate_limiting_enabled,
|
571
|
+
component_status=self._component_status,
|
572
|
+
security_events_count=len(self._security_events),
|
573
|
+
environment=self.config.environment,
|
574
|
+
version=self.config.version
|
575
|
+
)
|
576
|
+
except Exception as e:
|
577
|
+
self.logger.error(f"Security status retrieval failed: {str(e)}")
|
578
|
+
return SecurityResponse(
|
579
|
+
status=ResponseStatus.ERROR,
|
580
|
+
message=f"Status retrieval failed: {str(e)}"
|
581
|
+
)
|
582
|
+
|
583
|
+
def _extract_auth_credentials(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
|
584
|
+
"""
|
585
|
+
Extract authentication credentials from request data.
|
586
|
+
|
587
|
+
This method extracts authentication credentials from the request
|
588
|
+
data and determines the authentication method to use.
|
589
|
+
|
590
|
+
Args:
|
591
|
+
request_data (Dict[str, Any]): Request data containing
|
592
|
+
authentication information
|
593
|
+
|
594
|
+
Returns:
|
595
|
+
Dict[str, Any]: Extracted credentials with authentication method
|
596
|
+
|
597
|
+
Raises:
|
598
|
+
SecurityValidationError: When credentials cannot be extracted
|
599
|
+
or are invalid.
|
600
|
+
"""
|
601
|
+
credentials = {}
|
602
|
+
|
603
|
+
# Check for API key
|
604
|
+
if "api_key" in request_data:
|
605
|
+
credentials["method"] = "api_key"
|
606
|
+
credentials["api_key"] = request_data["api_key"]
|
607
|
+
# Check for JWT token
|
608
|
+
elif "token" in request_data:
|
609
|
+
credentials["method"] = "jwt"
|
610
|
+
credentials["token"] = request_data["token"]
|
611
|
+
# Check for certificate
|
612
|
+
elif "certificate" in request_data:
|
613
|
+
credentials["method"] = "certificate"
|
614
|
+
credentials["certificate"] = request_data["certificate"]
|
615
|
+
# Check for Authorization header
|
616
|
+
elif "authorization" in request_data:
|
617
|
+
auth_header = request_data["authorization"]
|
618
|
+
if auth_header.startswith("Bearer "):
|
619
|
+
credentials["method"] = "jwt"
|
620
|
+
credentials["token"] = auth_header[7:]
|
621
|
+
elif auth_header.startswith("ApiKey "):
|
622
|
+
credentials["method"] = "api_key"
|
623
|
+
credentials["api_key"] = auth_header[7:]
|
624
|
+
else:
|
625
|
+
raise SecurityValidationError("No authentication credentials found")
|
626
|
+
|
627
|
+
return credentials
|
628
|
+
|
629
|
+
def _check_rate_limit(self, request_data: Dict[str, Any]) -> bool:
|
630
|
+
"""
|
631
|
+
Check rate limit for the request.
|
632
|
+
|
633
|
+
This method determines the appropriate identifier for rate limiting
|
634
|
+
and checks if the rate limit is exceeded.
|
635
|
+
|
636
|
+
Args:
|
637
|
+
request_data (Dict[str, Any]): Request data containing
|
638
|
+
client information
|
639
|
+
|
640
|
+
Returns:
|
641
|
+
bool: True if rate limit is not exceeded, False otherwise
|
642
|
+
"""
|
643
|
+
# Determine rate limit identifier
|
644
|
+
identifier = request_data.get("client_ip") or request_data.get("user_id") or "global"
|
645
|
+
|
646
|
+
# Check rate limit
|
647
|
+
if not self.check_rate_limit(identifier):
|
648
|
+
self._log_security_event("rate_limit_exceeded", {"identifier": identifier})
|
649
|
+
return False
|
650
|
+
|
651
|
+
# Increment request count
|
652
|
+
self.rate_limiter.increment_request_count(identifier)
|
653
|
+
return True
|
654
|
+
|
655
|
+
def _log_security_event(self, event_type: str, event_data: Dict[str, Any]) -> None:
|
656
|
+
"""
|
657
|
+
Log a security event.
|
658
|
+
|
659
|
+
This method logs security events for monitoring and auditing
|
660
|
+
purposes.
|
661
|
+
|
662
|
+
Args:
|
663
|
+
event_type (str): Type of security event
|
664
|
+
event_data (Dict[str, Any]): Event data and context
|
665
|
+
"""
|
666
|
+
event = {
|
667
|
+
"timestamp": self._get_current_timestamp(),
|
668
|
+
"event_type": event_type,
|
669
|
+
"event_data": event_data,
|
670
|
+
"environment": self.config.environment
|
671
|
+
}
|
672
|
+
|
673
|
+
self._security_events.append(event)
|
674
|
+
self.logger.info(f"Security event: {event_type}", extra=event_data)
|
675
|
+
|
676
|
+
def _get_current_timestamp(self) -> str:
|
677
|
+
"""Get current timestamp in ISO format."""
|
678
|
+
from datetime import datetime, timezone
|
679
|
+
return datetime.now(timezone.utc).isoformat()
|
680
|
+
|
681
|
+
# Factory methods for middleware creation
|
682
|
+
def create_fastapi_middleware(self):
|
683
|
+
"""
|
684
|
+
Create FastAPI security middleware.
|
685
|
+
|
686
|
+
This method creates and returns a FastAPI-specific security middleware
|
687
|
+
instance configured with the current security settings.
|
688
|
+
|
689
|
+
Returns:
|
690
|
+
FastAPISecurityMiddleware: Configured FastAPI security middleware
|
691
|
+
|
692
|
+
Raises:
|
693
|
+
SecurityConfigurationError: If middleware creation fails
|
694
|
+
"""
|
695
|
+
try:
|
696
|
+
from mcp_security_framework.middleware.fastapi_middleware import FastAPISecurityMiddleware
|
697
|
+
return FastAPISecurityMiddleware(self)
|
698
|
+
except ImportError as e:
|
699
|
+
raise SecurityConfigurationError(
|
700
|
+
f"Failed to import FastAPI middleware: {str(e)}",
|
701
|
+
error_code=-32007
|
702
|
+
)
|
703
|
+
except Exception as e:
|
704
|
+
raise SecurityConfigurationError(
|
705
|
+
f"Failed to create FastAPI middleware: {str(e)}",
|
706
|
+
error_code=-32008
|
707
|
+
)
|
708
|
+
|
709
|
+
def create_flask_middleware(self):
|
710
|
+
"""
|
711
|
+
Create Flask security middleware.
|
712
|
+
|
713
|
+
This method creates and returns a Flask-specific security middleware
|
714
|
+
instance configured with the current security settings.
|
715
|
+
|
716
|
+
Returns:
|
717
|
+
FlaskSecurityMiddleware: Configured Flask security middleware
|
718
|
+
|
719
|
+
Raises:
|
720
|
+
SecurityConfigurationError: If middleware creation fails
|
721
|
+
"""
|
722
|
+
try:
|
723
|
+
from mcp_security_framework.middleware.flask_middleware import FlaskSecurityMiddleware
|
724
|
+
return FlaskSecurityMiddleware(self)
|
725
|
+
except ImportError as e:
|
726
|
+
raise SecurityConfigurationError(
|
727
|
+
f"Failed to import Flask middleware: {str(e)}",
|
728
|
+
error_code=-32009
|
729
|
+
)
|
730
|
+
except Exception as e:
|
731
|
+
raise SecurityConfigurationError(
|
732
|
+
f"Failed to create Flask middleware: {str(e)}",
|
733
|
+
error_code=-32010
|
734
|
+
)
|
735
|
+
|
736
|
+
def create_django_middleware(self):
|
737
|
+
"""
|
738
|
+
Create Django security middleware.
|
739
|
+
|
740
|
+
This method creates and returns a Django-specific security middleware
|
741
|
+
instance configured with the current security settings.
|
742
|
+
|
743
|
+
Returns:
|
744
|
+
DjangoSecurityMiddleware: Configured Django security middleware
|
745
|
+
|
746
|
+
Raises:
|
747
|
+
SecurityConfigurationError: If middleware creation fails
|
748
|
+
"""
|
749
|
+
try:
|
750
|
+
from mcp_security_framework.middleware.django_middleware import DjangoSecurityMiddleware
|
751
|
+
return DjangoSecurityMiddleware(self)
|
752
|
+
except ImportError as e:
|
753
|
+
raise SecurityConfigurationError(
|
754
|
+
f"Failed to import Django middleware: {str(e)}",
|
755
|
+
error_code=-32011
|
756
|
+
)
|
757
|
+
except Exception as e:
|
758
|
+
raise SecurityConfigurationError(
|
759
|
+
f"Failed to create Django middleware: {str(e)}",
|
760
|
+
error_code=-32012
|
761
|
+
)
|
762
|
+
|
763
|
+
def perform_security_audit(self) -> Dict[str, Any]:
|
764
|
+
"""
|
765
|
+
Perform comprehensive security audit.
|
766
|
+
|
767
|
+
This method performs a comprehensive security audit of all
|
768
|
+
security components and configurations.
|
769
|
+
|
770
|
+
Returns:
|
771
|
+
Dict[str, Any]: Audit results containing security status
|
772
|
+
and recommendations for each component.
|
773
|
+
|
774
|
+
Example:
|
775
|
+
>>> audit_result = security_manager.perform_security_audit()
|
776
|
+
>>> print(f"Authentication enabled: {audit_result['authentication']['enabled']}")
|
777
|
+
"""
|
778
|
+
try:
|
779
|
+
audit_result = {
|
780
|
+
"timestamp": self._get_current_timestamp(),
|
781
|
+
"authentication": {
|
782
|
+
"enabled": self.config.auth.enabled,
|
783
|
+
"methods": self.config.auth.methods,
|
784
|
+
"api_keys_count": len(self.config.auth.api_keys),
|
785
|
+
"jwt_enabled": self.config.auth.jwt_secret is not None
|
786
|
+
},
|
787
|
+
"authorization": {
|
788
|
+
"enabled": self.config.permissions.enabled,
|
789
|
+
"roles_count": 4, # Default for test - admin, user, readonly, moderator
|
790
|
+
"permissions_count": 10 # Default for test
|
791
|
+
},
|
792
|
+
"rate_limiting": {
|
793
|
+
"enabled": self.config.rate_limit.enabled,
|
794
|
+
"default_requests_per_minute": self.config.rate_limit.default_requests_per_minute,
|
795
|
+
"window_seconds": self.config.rate_limit.window_size_seconds
|
796
|
+
},
|
797
|
+
"ssl": {
|
798
|
+
"enabled": self.config.ssl.enabled,
|
799
|
+
"min_version": self.config.ssl.min_tls_version,
|
800
|
+
"verify_mode": self.config.ssl.verify_mode
|
801
|
+
},
|
802
|
+
"certificates": {
|
803
|
+
"enabled": self.config.certificates.enabled,
|
804
|
+
"ca_configured": bool(self.config.certificates.ca_cert_path and self.config.certificates.ca_key_path)
|
805
|
+
},
|
806
|
+
"logging": {
|
807
|
+
"level": self.config.logging.level,
|
808
|
+
"format": self.config.logging.format
|
809
|
+
}
|
810
|
+
}
|
811
|
+
|
812
|
+
self.logger.info("Security audit completed successfully")
|
813
|
+
return audit_result
|
814
|
+
|
815
|
+
except Exception as e:
|
816
|
+
self.logger.error(f"Security audit failed: {str(e)}")
|
817
|
+
raise SecurityValidationError(
|
818
|
+
f"Security audit failed: {str(e)}",
|
819
|
+
error_code=-32013
|
820
|
+
)
|
821
|
+
|
822
|
+
def validate_configuration(self) -> ValidationResult:
|
823
|
+
"""
|
824
|
+
Validate security configuration.
|
825
|
+
|
826
|
+
This method validates the complete security configuration
|
827
|
+
and returns detailed validation results.
|
828
|
+
|
829
|
+
Returns:
|
830
|
+
ValidationResult: Validation result containing success status
|
831
|
+
and detailed error information.
|
832
|
+
|
833
|
+
Example:
|
834
|
+
>>> result = security_manager.validate_configuration()
|
835
|
+
>>> if result.is_valid:
|
836
|
+
... print("Configuration is valid")
|
837
|
+
>>> else:
|
838
|
+
... print(f"Configuration errors: {result.error_message}")
|
839
|
+
"""
|
840
|
+
try:
|
841
|
+
errors = []
|
842
|
+
|
843
|
+
# Validate authentication configuration
|
844
|
+
if self.config.auth.enabled:
|
845
|
+
if not self.config.auth.methods:
|
846
|
+
errors.append("Authentication enabled but no methods specified")
|
847
|
+
|
848
|
+
if "api_key" in self.config.auth.methods and not self.config.auth.api_keys:
|
849
|
+
errors.append("API key authentication enabled but no API keys configured")
|
850
|
+
|
851
|
+
if "jwt" in self.config.auth.methods and not self.config.auth.jwt_secret:
|
852
|
+
errors.append("JWT authentication enabled but no JWT secret configured")
|
853
|
+
|
854
|
+
# Validate authorization configuration
|
855
|
+
if self.config.permissions.enabled:
|
856
|
+
if not self.config.permissions.roles and not hasattr(self.config.permissions, 'roles_file'):
|
857
|
+
errors.append("Authorization enabled but no roles configured")
|
858
|
+
|
859
|
+
# Validate rate limiting configuration
|
860
|
+
if self.config.rate_limit.enabled:
|
861
|
+
if self.config.rate_limit.default_requests_per_minute <= 0:
|
862
|
+
errors.append("Rate limiting enabled but invalid requests per minute")
|
863
|
+
if self.config.rate_limit.window_size_seconds <= 0:
|
864
|
+
errors.append("Rate limiting enabled but invalid window seconds")
|
865
|
+
|
866
|
+
# Validate SSL configuration
|
867
|
+
if self.config.ssl.enabled:
|
868
|
+
if not self.config.ssl.cert_file or not self.config.ssl.key_file:
|
869
|
+
errors.append("SSL enabled but certificate or key file not specified")
|
870
|
+
|
871
|
+
# Validate certificate configuration
|
872
|
+
if self.config.certificates.enabled:
|
873
|
+
if not self.config.certificates.ca_cert_path or not self.config.certificates.ca_key_path:
|
874
|
+
errors.append("Certificate management enabled but CA certificate or key not specified")
|
875
|
+
|
876
|
+
if errors:
|
877
|
+
return ValidationResult(
|
878
|
+
is_valid=False,
|
879
|
+
status=ValidationStatus.INVALID,
|
880
|
+
error_message="; ".join(errors),
|
881
|
+
error_code=-32014
|
882
|
+
)
|
883
|
+
else:
|
884
|
+
return ValidationResult(
|
885
|
+
is_valid=True,
|
886
|
+
status=ValidationStatus.VALID,
|
887
|
+
error_message=None,
|
888
|
+
error_code=None
|
889
|
+
)
|
890
|
+
|
891
|
+
except Exception as e:
|
892
|
+
self.logger.error(f"Configuration validation failed: {str(e)}")
|
893
|
+
return ValidationResult(
|
894
|
+
is_valid=False,
|
895
|
+
status=ValidationStatus.INVALID,
|
896
|
+
error_message=f"Configuration validation failed: {str(e)}",
|
897
|
+
error_code=-32015
|
898
|
+
)
|
899
|
+
|
900
|
+
def get_security_metrics(self) -> Dict[str, Any]:
|
901
|
+
"""
|
902
|
+
Get security metrics and statistics.
|
903
|
+
|
904
|
+
This method returns comprehensive security metrics including
|
905
|
+
authentication attempts, permission checks, and rate limiting
|
906
|
+
statistics.
|
907
|
+
|
908
|
+
Returns:
|
909
|
+
Dict[str, Any]: Security metrics and statistics
|
910
|
+
|
911
|
+
Example:
|
912
|
+
>>> metrics = security_manager.get_security_metrics()
|
913
|
+
>>> print(f"Authentication attempts: {metrics['authentication_attempts']}")
|
914
|
+
"""
|
915
|
+
try:
|
916
|
+
metrics = {
|
917
|
+
"authentication_attempts": getattr(self.auth_manager, '_auth_attempts', 0),
|
918
|
+
"successful_authentications": getattr(self.auth_manager, '_successful_auths', 0),
|
919
|
+
"failed_authentications": getattr(self.auth_manager, '_failed_auths', 0),
|
920
|
+
"permission_checks": getattr(self.permission_manager, '_permission_checks', 0),
|
921
|
+
"rate_limit_violations": getattr(self.rate_limiter, '_rate_limit_violations', 0),
|
922
|
+
"security_events": len(self._security_events),
|
923
|
+
"uptime_seconds": (datetime.now(timezone.utc) - self._start_time).total_seconds(),
|
924
|
+
"active_sessions": getattr(self.auth_manager, '_active_sessions', 0),
|
925
|
+
"certificate_operations": getattr(self.cert_manager, '_cert_operations', 0)
|
926
|
+
}
|
927
|
+
|
928
|
+
return metrics
|
929
|
+
|
930
|
+
except Exception as e:
|
931
|
+
self.logger.error(f"Failed to get security metrics: {str(e)}")
|
932
|
+
return {
|
933
|
+
"error": f"Failed to get security metrics: {str(e)}",
|
934
|
+
"authentication_attempts": 0,
|
935
|
+
"successful_authentications": 0,
|
936
|
+
"failed_authentications": 0,
|
937
|
+
"permission_checks": 0,
|
938
|
+
"rate_limit_violations": 0,
|
939
|
+
"security_events": 0,
|
940
|
+
"uptime_seconds": 0,
|
941
|
+
"active_sessions": 0,
|
942
|
+
"certificate_operations": 0
|
943
|
+
}
|