mcp-security-framework 0.1.0__py3-none-any.whl → 1.1.1__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 +26 -15
- mcp_security_framework/cli/__init__.py +1 -1
- mcp_security_framework/cli/cert_cli.py +233 -197
- mcp_security_framework/cli/security_cli.py +324 -234
- mcp_security_framework/constants.py +21 -27
- mcp_security_framework/core/auth_manager.py +49 -20
- mcp_security_framework/core/cert_manager.py +398 -104
- mcp_security_framework/core/permission_manager.py +13 -9
- mcp_security_framework/core/rate_limiter.py +10 -0
- mcp_security_framework/core/security_manager.py +286 -229
- mcp_security_framework/examples/__init__.py +6 -0
- mcp_security_framework/examples/comprehensive_example.py +954 -0
- mcp_security_framework/examples/django_example.py +276 -202
- mcp_security_framework/examples/fastapi_example.py +897 -393
- mcp_security_framework/examples/flask_example.py +311 -200
- mcp_security_framework/examples/gateway_example.py +373 -214
- mcp_security_framework/examples/microservice_example.py +337 -172
- mcp_security_framework/examples/standalone_example.py +719 -478
- mcp_security_framework/examples/test_all_examples.py +572 -0
- mcp_security_framework/middleware/__init__.py +46 -55
- mcp_security_framework/middleware/auth_middleware.py +62 -63
- mcp_security_framework/middleware/fastapi_auth_middleware.py +179 -110
- mcp_security_framework/middleware/fastapi_middleware.py +156 -148
- mcp_security_framework/middleware/flask_auth_middleware.py +267 -107
- mcp_security_framework/middleware/flask_middleware.py +183 -157
- mcp_security_framework/middleware/mtls_middleware.py +106 -117
- mcp_security_framework/middleware/rate_limit_middleware.py +105 -101
- mcp_security_framework/middleware/security_middleware.py +109 -124
- mcp_security_framework/schemas/config.py +2 -1
- mcp_security_framework/schemas/models.py +19 -6
- mcp_security_framework/utils/cert_utils.py +14 -8
- mcp_security_framework/utils/datetime_compat.py +116 -0
- {mcp_security_framework-0.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/METADATA +2 -1
- mcp_security_framework-1.1.1.dist-info/RECORD +84 -0
- tests/conftest.py +303 -0
- tests/test_cli/test_cert_cli.py +194 -174
- tests/test_cli/test_security_cli.py +274 -247
- tests/test_core/test_cert_manager.py +33 -19
- tests/test_core/test_security_manager.py +2 -2
- tests/test_examples/test_comprehensive_example.py +613 -0
- tests/test_examples/test_fastapi_example.py +290 -169
- tests/test_examples/test_flask_example.py +304 -162
- tests/test_examples/test_standalone_example.py +106 -168
- tests/test_integration/test_auth_flow.py +214 -198
- tests/test_integration/test_certificate_flow.py +181 -150
- tests/test_integration/test_fastapi_integration.py +140 -149
- tests/test_integration/test_flask_integration.py +144 -141
- tests/test_integration/test_standalone_integration.py +331 -300
- tests/test_middleware/test_fastapi_auth_middleware.py +745 -0
- tests/test_middleware/test_fastapi_middleware.py +147 -132
- tests/test_middleware/test_flask_auth_middleware.py +696 -0
- tests/test_middleware/test_flask_middleware.py +201 -179
- tests/test_middleware/test_security_middleware.py +151 -130
- tests/test_utils/test_datetime_compat.py +147 -0
- mcp_security_framework-0.1.0.dist-info/RECORD +0 -76
- {mcp_security_framework-0.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/WHEEL +0 -0
- {mcp_security_framework-0.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/entry_points.txt +0 -0
- {mcp_security_framework-0.1.0.dist-info → mcp_security_framework-1.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,613 @@
|
|
1
|
+
"""
|
2
|
+
Tests for Comprehensive Security Example
|
3
|
+
|
4
|
+
This module tests the comprehensive security example that demonstrates
|
5
|
+
all capabilities of the MCP Security Framework.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import os
|
9
|
+
import shutil
|
10
|
+
import tempfile
|
11
|
+
from datetime import datetime, timezone
|
12
|
+
from unittest.mock import MagicMock, Mock, mock_open, patch
|
13
|
+
|
14
|
+
import pytest
|
15
|
+
|
16
|
+
from mcp_security_framework.examples.comprehensive_example import (
|
17
|
+
ComprehensiveSecurityExample,
|
18
|
+
)
|
19
|
+
from mcp_security_framework.schemas.config import SecurityConfig
|
20
|
+
from mcp_security_framework.schemas.models import (
|
21
|
+
AuthMethod,
|
22
|
+
AuthResult,
|
23
|
+
AuthStatus,
|
24
|
+
ValidationResult,
|
25
|
+
ValidationStatus,
|
26
|
+
)
|
27
|
+
|
28
|
+
|
29
|
+
class TestComprehensiveSecurityExample:
|
30
|
+
"""Test suite for ComprehensiveSecurityExample class."""
|
31
|
+
|
32
|
+
def setup_method(self):
|
33
|
+
"""Set up test fixtures before each test method."""
|
34
|
+
self.temp_dir = tempfile.mkdtemp(prefix="test_comprehensive_")
|
35
|
+
self.example = ComprehensiveSecurityExample(work_dir=self.temp_dir)
|
36
|
+
|
37
|
+
def teardown_method(self):
|
38
|
+
"""Clean up after each test method."""
|
39
|
+
if hasattr(self, "temp_dir") and os.path.exists(self.temp_dir):
|
40
|
+
shutil.rmtree(self.temp_dir)
|
41
|
+
|
42
|
+
def test_comprehensive_security_example_initialization(self):
|
43
|
+
"""Test ComprehensiveSecurityExample initialization."""
|
44
|
+
assert self.example.work_dir == self.temp_dir
|
45
|
+
assert os.path.exists(self.example.certs_dir)
|
46
|
+
assert os.path.exists(self.example.keys_dir)
|
47
|
+
assert os.path.exists(self.example.config_dir)
|
48
|
+
assert isinstance(self.example.config, SecurityConfig)
|
49
|
+
assert self.example.logger is not None
|
50
|
+
assert self.example.test_api_key == "admin_key_123"
|
51
|
+
assert self.example.test_jwt_token is not None
|
52
|
+
|
53
|
+
def test_create_comprehensive_config(self):
|
54
|
+
"""Test comprehensive configuration creation."""
|
55
|
+
config = self.example._create_comprehensive_config()
|
56
|
+
assert isinstance(config, SecurityConfig)
|
57
|
+
assert config.auth.enabled is True
|
58
|
+
assert config.permissions.enabled is True
|
59
|
+
assert config.ssl.enabled is False # Initially disabled
|
60
|
+
assert config.certificates.enabled is False # Initially disabled
|
61
|
+
assert config.rate_limit.enabled is True
|
62
|
+
assert config.logging.enabled is True
|
63
|
+
|
64
|
+
def test_create_test_jwt_token(self):
|
65
|
+
"""Test JWT token creation."""
|
66
|
+
token = self.example._create_test_jwt_token()
|
67
|
+
assert isinstance(token, str)
|
68
|
+
assert len(token) > 0
|
69
|
+
|
70
|
+
def test_create_roles_config(self):
|
71
|
+
"""Test roles configuration creation."""
|
72
|
+
roles_file = os.path.join(self.example.config_dir, "roles.json")
|
73
|
+
assert os.path.exists(roles_file)
|
74
|
+
|
75
|
+
# Verify roles file content
|
76
|
+
import json
|
77
|
+
|
78
|
+
with open(roles_file, "r") as f:
|
79
|
+
roles_config = json.load(f)
|
80
|
+
|
81
|
+
assert "roles" in roles_config
|
82
|
+
assert "admin" in roles_config["roles"]
|
83
|
+
assert "user" in roles_config["roles"]
|
84
|
+
assert "readonly" in roles_config["roles"]
|
85
|
+
|
86
|
+
@patch("mcp_security_framework.examples.comprehensive_example.CertificateManager")
|
87
|
+
def test_demonstrate_certificate_management_success(self, mock_cert_manager):
|
88
|
+
"""Test successful certificate management demonstration."""
|
89
|
+
# Mock certificate manager methods
|
90
|
+
mock_manager = Mock()
|
91
|
+
mock_cert_manager.return_value = mock_manager
|
92
|
+
|
93
|
+
# Mock certificate creation results
|
94
|
+
mock_ca_pair = Mock()
|
95
|
+
mock_ca_pair.certificate_path = "/path/to/ca.crt"
|
96
|
+
mock_ca_pair.private_key_path = "/path/to/ca.key"
|
97
|
+
mock_ca_pair.serial_number = "123456789"
|
98
|
+
|
99
|
+
mock_intermediate_pair = Mock()
|
100
|
+
mock_intermediate_pair.certificate_path = "/path/to/intermediate.crt"
|
101
|
+
mock_intermediate_pair.private_key_path = "/path/to/intermediate.key"
|
102
|
+
mock_intermediate_pair.serial_number = "987654321"
|
103
|
+
|
104
|
+
mock_server_pair = Mock()
|
105
|
+
mock_server_pair.certificate_path = "/path/to/server.crt"
|
106
|
+
mock_server_pair.private_key_path = "/path/to/server.key"
|
107
|
+
mock_server_pair.serial_number = "111222333"
|
108
|
+
|
109
|
+
mock_client_pair = Mock()
|
110
|
+
mock_client_pair.certificate_path = "/path/to/client.crt"
|
111
|
+
mock_client_pair.private_key_path = "/path/to/client.key"
|
112
|
+
mock_client_pair.serial_number = "444555666"
|
113
|
+
|
114
|
+
mock_manager.create_root_ca.return_value = mock_ca_pair
|
115
|
+
mock_manager.create_intermediate_ca.return_value = mock_intermediate_pair
|
116
|
+
mock_manager.create_server_certificate.return_value = mock_server_pair
|
117
|
+
mock_manager.create_client_certificate.return_value = mock_client_pair
|
118
|
+
mock_manager.create_certificate_signing_request.return_value = (
|
119
|
+
"/path/to/csr.pem",
|
120
|
+
"/path/to/csr.key",
|
121
|
+
)
|
122
|
+
mock_manager.create_crl.return_value = "/path/to/crl.pem"
|
123
|
+
|
124
|
+
mock_cert_info = Mock()
|
125
|
+
mock_cert_info.subject = "CN=test.example.com"
|
126
|
+
mock_cert_info.issuer = "CN=Test CA"
|
127
|
+
mock_cert_info.serial_number = "123456789"
|
128
|
+
mock_cert_info.not_before = datetime.now(timezone.utc)
|
129
|
+
mock_cert_info.not_after = datetime.now(timezone.utc)
|
130
|
+
mock_cert_info.is_expired = False
|
131
|
+
mock_manager.get_certificate_info.return_value = mock_cert_info
|
132
|
+
|
133
|
+
# Run demonstration
|
134
|
+
results = self.example.demonstrate_certificate_management()
|
135
|
+
|
136
|
+
# Verify results
|
137
|
+
assert "root_ca_creation" in results
|
138
|
+
assert results["root_ca_creation"]["success"] is True
|
139
|
+
assert "intermediate_ca_creation" in results
|
140
|
+
assert results["intermediate_ca_creation"]["success"] is True
|
141
|
+
assert "server_cert_creation" in results
|
142
|
+
assert results["server_cert_creation"]["success"] is True
|
143
|
+
assert "client_cert_creation" in results
|
144
|
+
assert results["client_cert_creation"]["success"] is True
|
145
|
+
assert "csr_creation" in results
|
146
|
+
assert results["csr_creation"]["success"] is True
|
147
|
+
assert "crl_creation" in results
|
148
|
+
assert results["crl_creation"]["success"] is True
|
149
|
+
assert "certificate_validation" in results
|
150
|
+
assert results["certificate_validation"]["success"] is True
|
151
|
+
|
152
|
+
def test_demonstrate_certificate_management_exception(self):
|
153
|
+
"""Test certificate management demonstration with exception."""
|
154
|
+
# Mock certificate manager to raise exception
|
155
|
+
with patch.object(self.example, "cert_manager") as mock_cert_manager:
|
156
|
+
mock_cert_manager.create_root_ca.side_effect = Exception(
|
157
|
+
"Certificate creation failed"
|
158
|
+
)
|
159
|
+
|
160
|
+
results = self.example.demonstrate_certificate_management()
|
161
|
+
|
162
|
+
assert "error" in results
|
163
|
+
assert "Certificate creation failed" in results["error"]
|
164
|
+
|
165
|
+
def test_demonstrate_ssl_tls_management_success(self):
|
166
|
+
"""Test successful SSL/TLS management demonstration."""
|
167
|
+
# Set certificate paths
|
168
|
+
self.example.server_cert_path = "/path/to/server.crt"
|
169
|
+
self.example.server_key_path = "/path/to/server.key"
|
170
|
+
self.example.ca_cert_path = "/path/to/ca.crt"
|
171
|
+
self.example.client_cert_path = "/path/to/client.crt"
|
172
|
+
self.example.client_key_path = "/path/to/client.key"
|
173
|
+
|
174
|
+
# Mock SSL manager methods
|
175
|
+
with patch.object(self.example, "ssl_manager") as mock_ssl_manager:
|
176
|
+
# Mock SSL contexts
|
177
|
+
mock_server_context = Mock()
|
178
|
+
mock_server_context.verify_mode = "CERT_REQUIRED"
|
179
|
+
mock_server_context.minimum_version = "TLSv1.2"
|
180
|
+
mock_server_context.maximum_version = "TLSv1.3"
|
181
|
+
|
182
|
+
mock_client_context = Mock()
|
183
|
+
mock_client_context.verify_mode = "CERT_REQUIRED"
|
184
|
+
mock_client_context.minimum_version = "TLSv1.2"
|
185
|
+
mock_client_context.maximum_version = "TLSv1.3"
|
186
|
+
|
187
|
+
mock_ssl_manager.create_server_context.return_value = mock_server_context
|
188
|
+
mock_ssl_manager.create_client_context.return_value = mock_client_context
|
189
|
+
|
190
|
+
# Mock file existence
|
191
|
+
with patch("os.path.exists", return_value=True):
|
192
|
+
results = self.example.demonstrate_ssl_tls_management()
|
193
|
+
|
194
|
+
# Verify results
|
195
|
+
assert "server_context_creation" in results
|
196
|
+
assert results["server_context_creation"]["success"] is True
|
197
|
+
assert "client_context_creation" in results
|
198
|
+
assert results["client_context_creation"]["success"] is True
|
199
|
+
assert "mtls_context_creation" in results
|
200
|
+
assert results["mtls_context_creation"]["success"] is True
|
201
|
+
assert "ssl_validation" in results
|
202
|
+
assert results["ssl_validation"]["success"] is True
|
203
|
+
|
204
|
+
def test_demonstrate_ssl_tls_management_exception(self):
|
205
|
+
"""Test SSL/TLS management demonstration with exception."""
|
206
|
+
# Mock SSL manager to raise exception
|
207
|
+
with patch.object(self.example, "ssl_manager") as mock_ssl_manager:
|
208
|
+
mock_ssl_manager.create_server_context.side_effect = Exception(
|
209
|
+
"SSL context creation failed"
|
210
|
+
)
|
211
|
+
|
212
|
+
results = self.example.demonstrate_ssl_tls_management()
|
213
|
+
|
214
|
+
assert "error" in results
|
215
|
+
assert "SSL context creation failed" in results["error"]
|
216
|
+
|
217
|
+
def test_demonstrate_authentication_success(self):
|
218
|
+
"""Test successful authentication demonstration."""
|
219
|
+
# Set client certificate path
|
220
|
+
self.example.client_cert_path = "/path/to/client.crt"
|
221
|
+
|
222
|
+
# Mock security manager methods
|
223
|
+
with patch.object(self.example, "security_manager") as mock_security_manager:
|
224
|
+
# Mock authentication results
|
225
|
+
success_auth_result = AuthResult(
|
226
|
+
is_valid=True,
|
227
|
+
username="test_user",
|
228
|
+
roles=["user"],
|
229
|
+
auth_method=AuthMethod.API_KEY,
|
230
|
+
status=AuthStatus.SUCCESS,
|
231
|
+
)
|
232
|
+
|
233
|
+
failed_auth_result = AuthResult(
|
234
|
+
is_valid=False,
|
235
|
+
username=None,
|
236
|
+
roles=[],
|
237
|
+
auth_method=AuthMethod.API_KEY,
|
238
|
+
status=AuthStatus.INVALID,
|
239
|
+
error_code=-32001,
|
240
|
+
error_message="Invalid API key",
|
241
|
+
)
|
242
|
+
|
243
|
+
mock_security_manager.authenticate_user.side_effect = [
|
244
|
+
success_auth_result, # API key auth
|
245
|
+
success_auth_result, # JWT auth
|
246
|
+
success_auth_result, # Certificate auth
|
247
|
+
failed_auth_result, # Failed auth
|
248
|
+
]
|
249
|
+
|
250
|
+
# Mock file reading
|
251
|
+
with patch("builtins.open", mock_open(read_data="test certificate")):
|
252
|
+
results = self.example.demonstrate_authentication()
|
253
|
+
|
254
|
+
# Verify results
|
255
|
+
assert "api_key_auth" in results
|
256
|
+
assert results["api_key_auth"]["success"] is True
|
257
|
+
assert "jwt_auth" in results
|
258
|
+
assert results["jwt_auth"]["success"] is True
|
259
|
+
assert "certificate_auth" in results
|
260
|
+
assert results["certificate_auth"]["success"] is True
|
261
|
+
assert "failed_auth" in results
|
262
|
+
assert results["failed_auth"]["success"] is False
|
263
|
+
|
264
|
+
def test_demonstrate_authentication_exception(self):
|
265
|
+
"""Test authentication demonstration with exception."""
|
266
|
+
# Mock security manager to raise exception
|
267
|
+
with patch.object(self.example, "security_manager") as mock_security_manager:
|
268
|
+
mock_security_manager.authenticate_user.side_effect = Exception(
|
269
|
+
"Authentication failed"
|
270
|
+
)
|
271
|
+
|
272
|
+
results = self.example.demonstrate_authentication()
|
273
|
+
|
274
|
+
assert "error" in results
|
275
|
+
assert "Authentication failed" in results["error"]
|
276
|
+
|
277
|
+
def test_demonstrate_authorization_success(self):
|
278
|
+
"""Test successful authorization demonstration."""
|
279
|
+
# Mock security manager methods
|
280
|
+
with patch.object(self.example, "security_manager") as mock_security_manager:
|
281
|
+
# Mock authorization results
|
282
|
+
success_result = ValidationResult(
|
283
|
+
is_valid=True, status=ValidationStatus.VALID
|
284
|
+
)
|
285
|
+
|
286
|
+
failed_result = ValidationResult(
|
287
|
+
is_valid=False, status=ValidationStatus.INVALID
|
288
|
+
)
|
289
|
+
|
290
|
+
mock_security_manager.check_permissions.side_effect = [
|
291
|
+
success_result, # Admin permissions
|
292
|
+
success_result, # User permissions
|
293
|
+
success_result, # Readonly permissions
|
294
|
+
failed_result, # Denied permissions
|
295
|
+
]
|
296
|
+
|
297
|
+
results = self.example.demonstrate_authorization()
|
298
|
+
|
299
|
+
# Verify results
|
300
|
+
assert "admin_permissions" in results
|
301
|
+
assert results["admin_permissions"]["success"] is True
|
302
|
+
assert "user_permissions" in results
|
303
|
+
assert results["user_permissions"]["success"] is True
|
304
|
+
assert "readonly_permissions" in results
|
305
|
+
assert results["readonly_permissions"]["success"] is True
|
306
|
+
assert "denied_permissions" in results
|
307
|
+
assert results["denied_permissions"]["success"] is False
|
308
|
+
|
309
|
+
def test_demonstrate_authorization_exception(self):
|
310
|
+
"""Test authorization demonstration with exception."""
|
311
|
+
# Mock security manager to raise exception
|
312
|
+
with patch.object(self.example, "security_manager") as mock_security_manager:
|
313
|
+
mock_security_manager.check_permissions.side_effect = Exception(
|
314
|
+
"Authorization failed"
|
315
|
+
)
|
316
|
+
|
317
|
+
results = self.example.demonstrate_authorization()
|
318
|
+
|
319
|
+
assert "error" in results
|
320
|
+
assert "Authorization failed" in results["error"]
|
321
|
+
|
322
|
+
def test_demonstrate_rate_limiting_success(self):
|
323
|
+
"""Test successful rate limiting demonstration."""
|
324
|
+
# Mock security manager methods
|
325
|
+
with patch.object(self.example, "security_manager") as mock_security_manager:
|
326
|
+
# Mock rate limiting results (first 4 allowed, 5th denied)
|
327
|
+
mock_security_manager.check_rate_limit.side_effect = [
|
328
|
+
True,
|
329
|
+
True,
|
330
|
+
True,
|
331
|
+
True,
|
332
|
+
False,
|
333
|
+
]
|
334
|
+
|
335
|
+
results = self.example.demonstrate_rate_limiting()
|
336
|
+
|
337
|
+
# Verify results
|
338
|
+
assert "rate_limit_checks" in results
|
339
|
+
assert len(results["rate_limit_checks"]) == 5
|
340
|
+
assert results["rate_limit_exceeded"] is True
|
341
|
+
|
342
|
+
def test_demonstrate_rate_limiting_exception(self):
|
343
|
+
"""Test rate limiting demonstration with exception."""
|
344
|
+
# Mock security manager to raise exception
|
345
|
+
with patch.object(self.example, "security_manager") as mock_security_manager:
|
346
|
+
mock_security_manager.check_rate_limit.side_effect = Exception(
|
347
|
+
"Rate limiting failed"
|
348
|
+
)
|
349
|
+
|
350
|
+
results = self.example.demonstrate_rate_limiting()
|
351
|
+
|
352
|
+
assert "error" in results
|
353
|
+
assert "Rate limiting failed" in results["error"]
|
354
|
+
|
355
|
+
def test_demonstrate_security_validation_success(self):
|
356
|
+
"""Test successful security validation demonstration."""
|
357
|
+
# Mock security manager methods
|
358
|
+
with patch.object(self.example, "security_manager") as mock_security_manager:
|
359
|
+
# Mock validation results
|
360
|
+
success_result = ValidationResult(
|
361
|
+
is_valid=True, status=ValidationStatus.VALID
|
362
|
+
)
|
363
|
+
|
364
|
+
mock_security_manager.validate_request.return_value = success_result
|
365
|
+
mock_security_manager.validate_configuration.return_value = success_result
|
366
|
+
|
367
|
+
results = self.example.demonstrate_security_validation()
|
368
|
+
|
369
|
+
# Verify results
|
370
|
+
assert "request_validation" in results
|
371
|
+
assert results["request_validation"]["success"] is True
|
372
|
+
assert "configuration_validation" in results
|
373
|
+
assert results["configuration_validation"]["success"] is True
|
374
|
+
|
375
|
+
def test_demonstrate_security_validation_exception(self):
|
376
|
+
"""Test security validation demonstration with exception."""
|
377
|
+
# Mock security manager to raise exception
|
378
|
+
with patch.object(self.example, "security_manager") as mock_security_manager:
|
379
|
+
mock_security_manager.validate_request.side_effect = Exception(
|
380
|
+
"Validation failed"
|
381
|
+
)
|
382
|
+
|
383
|
+
results = self.example.demonstrate_security_validation()
|
384
|
+
|
385
|
+
assert "error" in results
|
386
|
+
assert "Validation failed" in results["error"]
|
387
|
+
|
388
|
+
def test_demonstrate_security_monitoring_success(self):
|
389
|
+
"""Test successful security monitoring demonstration."""
|
390
|
+
# Mock security manager methods
|
391
|
+
with patch.object(self.example, "security_manager") as mock_security_manager:
|
392
|
+
# Mock monitoring results
|
393
|
+
mock_security_manager.get_security_status.return_value = {
|
394
|
+
"status": "healthy"
|
395
|
+
}
|
396
|
+
mock_security_manager.get_security_metrics.return_value = {"requests": 100}
|
397
|
+
|
398
|
+
results = self.example.demonstrate_security_monitoring()
|
399
|
+
|
400
|
+
# Verify results
|
401
|
+
assert "security_status" in results
|
402
|
+
assert results["security_status"]["status"] == "healthy"
|
403
|
+
assert "security_metrics" in results
|
404
|
+
assert results["security_metrics"]["requests"] == 100
|
405
|
+
assert "security_audit" in results
|
406
|
+
|
407
|
+
def test_demonstrate_security_monitoring_exception(self):
|
408
|
+
"""Test security monitoring demonstration with exception."""
|
409
|
+
# Mock security manager to raise exception
|
410
|
+
with patch.object(self.example, "security_manager") as mock_security_manager:
|
411
|
+
mock_security_manager.get_security_status.side_effect = Exception(
|
412
|
+
"Monitoring failed"
|
413
|
+
)
|
414
|
+
|
415
|
+
results = self.example.demonstrate_security_monitoring()
|
416
|
+
|
417
|
+
assert "error" in results
|
418
|
+
assert "Monitoring failed" in results["error"]
|
419
|
+
|
420
|
+
def test_update_config_after_certificates(self):
|
421
|
+
"""Test configuration update after certificate creation."""
|
422
|
+
# Set certificate paths
|
423
|
+
self.example.ca_cert_path = "/path/to/ca.crt"
|
424
|
+
self.example.ca_key_path = "/path/to/ca.key"
|
425
|
+
self.example.server_cert_path = "/path/to/server.crt"
|
426
|
+
self.example.server_key_path = "/path/to/server.key"
|
427
|
+
|
428
|
+
# Mock file existence and SSL manager creation
|
429
|
+
with patch("os.path.exists", return_value=True), patch(
|
430
|
+
"mcp_security_framework.examples.comprehensive_example.SSLManager"
|
431
|
+
) as mock_ssl_manager_class, patch(
|
432
|
+
"mcp_security_framework.examples.comprehensive_example.CertificateManager"
|
433
|
+
) as mock_cert_manager_class:
|
434
|
+
|
435
|
+
mock_ssl_manager = Mock()
|
436
|
+
mock_cert_manager = Mock()
|
437
|
+
mock_ssl_manager_class.return_value = mock_ssl_manager
|
438
|
+
mock_cert_manager_class.return_value = mock_cert_manager
|
439
|
+
|
440
|
+
self.example._update_config_after_certificates()
|
441
|
+
|
442
|
+
# Verify configuration was updated
|
443
|
+
assert self.example.config.certificates.enabled is True
|
444
|
+
assert self.example.config.certificates.ca_cert_path == "/path/to/ca.crt"
|
445
|
+
assert self.example.config.certificates.ca_key_path == "/path/to/ca.key"
|
446
|
+
assert self.example.config.ssl.enabled is True
|
447
|
+
assert self.example.config.ssl.cert_file == "/path/to/server.crt"
|
448
|
+
assert self.example.config.ssl.key_file == "/path/to/server.key"
|
449
|
+
assert self.example.config.ssl.ca_cert_file == "/path/to/ca.crt"
|
450
|
+
|
451
|
+
@patch(
|
452
|
+
"mcp_security_framework.examples.comprehensive_example.ComprehensiveSecurityExample.demonstrate_certificate_management"
|
453
|
+
)
|
454
|
+
@patch(
|
455
|
+
"mcp_security_framework.examples.comprehensive_example.ComprehensiveSecurityExample.demonstrate_ssl_tls_management"
|
456
|
+
)
|
457
|
+
@patch(
|
458
|
+
"mcp_security_framework.examples.comprehensive_example.ComprehensiveSecurityExample.demonstrate_authentication"
|
459
|
+
)
|
460
|
+
@patch(
|
461
|
+
"mcp_security_framework.examples.comprehensive_example.ComprehensiveSecurityExample.demonstrate_authorization"
|
462
|
+
)
|
463
|
+
@patch(
|
464
|
+
"mcp_security_framework.examples.comprehensive_example.ComprehensiveSecurityExample.demonstrate_rate_limiting"
|
465
|
+
)
|
466
|
+
@patch(
|
467
|
+
"mcp_security_framework.examples.comprehensive_example.ComprehensiveSecurityExample.demonstrate_security_validation"
|
468
|
+
)
|
469
|
+
@patch(
|
470
|
+
"mcp_security_framework.examples.comprehensive_example.ComprehensiveSecurityExample.demonstrate_security_monitoring"
|
471
|
+
)
|
472
|
+
def test_run_comprehensive_demo_success(
|
473
|
+
self,
|
474
|
+
mock_monitoring,
|
475
|
+
mock_validation,
|
476
|
+
mock_rate_limit,
|
477
|
+
mock_authz,
|
478
|
+
mock_auth,
|
479
|
+
mock_ssl,
|
480
|
+
mock_cert,
|
481
|
+
):
|
482
|
+
"""Test successful comprehensive demonstration."""
|
483
|
+
# Mock all demonstration methods
|
484
|
+
mock_cert.return_value = {"root_ca_creation": {"success": True}}
|
485
|
+
mock_ssl.return_value = {"server_context_creation": {"success": True}}
|
486
|
+
mock_auth.return_value = {"api_key_auth": {"success": True}}
|
487
|
+
mock_authz.return_value = {"admin_permissions": {"success": True}}
|
488
|
+
mock_rate_limit.return_value = {"rate_limit_checks": []}
|
489
|
+
mock_validation.return_value = {"request_validation": {"success": True}}
|
490
|
+
mock_monitoring.return_value = {"security_status": {"status": "healthy"}}
|
491
|
+
|
492
|
+
results = self.example.run_comprehensive_demo()
|
493
|
+
|
494
|
+
# Verify results structure
|
495
|
+
assert "framework" in results
|
496
|
+
assert "version" in results
|
497
|
+
assert "timestamp" in results
|
498
|
+
assert "certificate_management" in results
|
499
|
+
assert "ssl_tls_management" in results
|
500
|
+
assert "authentication" in results
|
501
|
+
assert "authorization" in results
|
502
|
+
assert "rate_limiting" in results
|
503
|
+
assert "security_validation" in results
|
504
|
+
assert "security_monitoring" in results
|
505
|
+
|
506
|
+
def test_comprehensive_example_cleanup(self):
|
507
|
+
"""Test that working directory is properly cleaned up."""
|
508
|
+
# Create a temporary example
|
509
|
+
temp_example = ComprehensiveSecurityExample()
|
510
|
+
work_dir = temp_example.work_dir
|
511
|
+
|
512
|
+
# Verify directory exists
|
513
|
+
assert os.path.exists(work_dir)
|
514
|
+
|
515
|
+
# Clean up
|
516
|
+
if os.path.exists(work_dir):
|
517
|
+
shutil.rmtree(work_dir)
|
518
|
+
|
519
|
+
# Verify directory is removed
|
520
|
+
assert not os.path.exists(work_dir)
|
521
|
+
|
522
|
+
|
523
|
+
def test_main_function():
|
524
|
+
"""Test the main function."""
|
525
|
+
with patch(
|
526
|
+
"mcp_security_framework.examples.comprehensive_example.ComprehensiveSecurityExample"
|
527
|
+
) as mock_example_class:
|
528
|
+
mock_example = Mock()
|
529
|
+
mock_example_class.return_value = mock_example
|
530
|
+
|
531
|
+
# Mock the run_comprehensive_demo method
|
532
|
+
mock_example.run_comprehensive_demo.return_value = {
|
533
|
+
"framework": "MCP Security Framework",
|
534
|
+
"version": "1.0.0",
|
535
|
+
"timestamp": "2024-01-01T00:00:00Z",
|
536
|
+
"certificate_management": {
|
537
|
+
"root_ca_creation": {"success": True},
|
538
|
+
"intermediate_ca_creation": {"success": True},
|
539
|
+
"server_cert_creation": {"success": True},
|
540
|
+
"client_cert_creation": {"success": True},
|
541
|
+
"csr_creation": {"success": True},
|
542
|
+
"crl_creation": {"success": True},
|
543
|
+
"certificate_validation": {"success": True},
|
544
|
+
},
|
545
|
+
"ssl_tls_management": {
|
546
|
+
"server_context_creation": {"success": True},
|
547
|
+
"client_context_creation": {"success": True},
|
548
|
+
"mtls_context_creation": {"success": True},
|
549
|
+
"ssl_validation": {"success": True},
|
550
|
+
},
|
551
|
+
"authentication": {
|
552
|
+
"api_key_auth": {"success": True},
|
553
|
+
"jwt_auth": {"success": True},
|
554
|
+
"certificate_auth": {"success": True},
|
555
|
+
"failed_auth": {"success": False},
|
556
|
+
},
|
557
|
+
"authorization": {
|
558
|
+
"admin_permissions": {"success": True},
|
559
|
+
"user_permissions": {"success": True},
|
560
|
+
"readonly_permissions": {"success": True},
|
561
|
+
"denied_permissions": {"success": False},
|
562
|
+
},
|
563
|
+
"rate_limiting": {
|
564
|
+
"rate_limit_checks": [{"request": 1, "allowed": True}],
|
565
|
+
"rate_limit_exceeded": False,
|
566
|
+
},
|
567
|
+
"security_validation": {
|
568
|
+
"request_validation": {"success": True},
|
569
|
+
"configuration_validation": {"success": True},
|
570
|
+
},
|
571
|
+
"security_monitoring": {
|
572
|
+
"security_status": {"status": "healthy"},
|
573
|
+
"security_metrics": {"requests": 100},
|
574
|
+
"security_audit": {"authentication": []},
|
575
|
+
},
|
576
|
+
}
|
577
|
+
|
578
|
+
# Mock cleanup
|
579
|
+
mock_example.work_dir = "/tmp/test"
|
580
|
+
|
581
|
+
# Import and run main function
|
582
|
+
from mcp_security_framework.examples.comprehensive_example import main
|
583
|
+
|
584
|
+
# Mock print to avoid output during tests
|
585
|
+
with patch("builtins.print"):
|
586
|
+
main()
|
587
|
+
|
588
|
+
# Verify example was created and demo was run
|
589
|
+
mock_example_class.assert_called_once()
|
590
|
+
mock_example.run_comprehensive_demo.assert_called_once()
|
591
|
+
|
592
|
+
|
593
|
+
def test_main_function_exception():
|
594
|
+
"""Test main function with exception."""
|
595
|
+
with patch(
|
596
|
+
"mcp_security_framework.examples.comprehensive_example.ComprehensiveSecurityExample"
|
597
|
+
) as mock_example_class:
|
598
|
+
mock_example = Mock()
|
599
|
+
mock_example_class.return_value = mock_example
|
600
|
+
|
601
|
+
# Mock the run_comprehensive_demo method to raise exception
|
602
|
+
mock_example.run_comprehensive_demo.side_effect = Exception("Test exception")
|
603
|
+
|
604
|
+
# Import and run main function
|
605
|
+
from mcp_security_framework.examples.comprehensive_example import main
|
606
|
+
|
607
|
+
# Mock print to avoid output during tests
|
608
|
+
with patch("builtins.print"):
|
609
|
+
main()
|
610
|
+
|
611
|
+
# Verify example was created and demo was attempted
|
612
|
+
mock_example_class.assert_called_once()
|
613
|
+
mock_example.run_comprehensive_demo.assert_called_once()
|