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