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,502 @@
|
|
1
|
+
"""
|
2
|
+
Authentication Flow Integration Tests
|
3
|
+
|
4
|
+
This module contains integration tests for complete authentication and
|
5
|
+
authorization flows using the MCP Security Framework. Tests cover API key
|
6
|
+
authentication, JWT authentication, role-based access control, and
|
7
|
+
permission management.
|
8
|
+
|
9
|
+
Author: MCP Security Team
|
10
|
+
Version: 1.0.0
|
11
|
+
License: MIT
|
12
|
+
"""
|
13
|
+
|
14
|
+
import json
|
15
|
+
import tempfile
|
16
|
+
import os
|
17
|
+
from unittest.mock import patch, MagicMock
|
18
|
+
from typing import Dict, Any
|
19
|
+
from datetime import datetime, timedelta
|
20
|
+
|
21
|
+
import pytest
|
22
|
+
import jwt
|
23
|
+
|
24
|
+
from mcp_security_framework.core.auth_manager import AuthManager
|
25
|
+
from mcp_security_framework.core.permission_manager import PermissionManager
|
26
|
+
from mcp_security_framework.core.security_manager import SecurityManager, SecurityValidationError
|
27
|
+
from mcp_security_framework.schemas.config import (
|
28
|
+
SecurityConfig, AuthConfig, PermissionConfig, RateLimitConfig, SSLConfig, CertificateConfig
|
29
|
+
)
|
30
|
+
from mcp_security_framework.schemas.responses import AuthResult, ValidationResult
|
31
|
+
|
32
|
+
|
33
|
+
class TestAuthFlowIntegration:
|
34
|
+
"""Integration tests for complete authentication and authorization flows."""
|
35
|
+
|
36
|
+
def setup_method(self):
|
37
|
+
"""Set up test fixtures before each test method."""
|
38
|
+
# Create temporary roles file
|
39
|
+
self.roles_fd, self.roles_path = tempfile.mkstemp(suffix='.json')
|
40
|
+
self.roles_config = {
|
41
|
+
"roles": {
|
42
|
+
"admin": {
|
43
|
+
"permissions": ["read", "write", "delete", "admin"],
|
44
|
+
"description": "Administrator role",
|
45
|
+
"inherits": ["user", "moderator"]
|
46
|
+
},
|
47
|
+
"user": {
|
48
|
+
"permissions": ["read", "write"],
|
49
|
+
"description": "Regular user role"
|
50
|
+
},
|
51
|
+
"readonly": {
|
52
|
+
"permissions": ["read"],
|
53
|
+
"description": "Read-only user role"
|
54
|
+
},
|
55
|
+
"moderator": {
|
56
|
+
"permissions": ["read", "write", "moderate"],
|
57
|
+
"description": "Moderator role",
|
58
|
+
"inherits": ["user"]
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
with os.fdopen(self.roles_fd, 'w') as f:
|
64
|
+
json.dump(self.roles_config, f)
|
65
|
+
|
66
|
+
# Create authentication configuration
|
67
|
+
self.auth_config = AuthConfig(
|
68
|
+
enabled=True,
|
69
|
+
methods=["api_key", "jwt"],
|
70
|
+
api_keys={
|
71
|
+
"admin_key_123456789012345": "admin",
|
72
|
+
"user_key_456789012345678": "user",
|
73
|
+
"readonly_key_789012345678": "readonly",
|
74
|
+
"moderator_key_101234567890": "moderator"
|
75
|
+
},
|
76
|
+
user_roles={
|
77
|
+
"admin": ["admin"],
|
78
|
+
"user": ["user"],
|
79
|
+
"readonly": ["readonly"],
|
80
|
+
"moderator": ["moderator"]
|
81
|
+
},
|
82
|
+
jwt_secret="test_jwt_secret_key_for_integration_tests",
|
83
|
+
jwt_algorithm="HS256",
|
84
|
+
jwt_expiry_hours=24
|
85
|
+
)
|
86
|
+
|
87
|
+
# Create permission configuration
|
88
|
+
self.permission_config = PermissionConfig(
|
89
|
+
enabled=True,
|
90
|
+
roles_file=self.roles_path
|
91
|
+
)
|
92
|
+
|
93
|
+
# Create security configuration
|
94
|
+
self.security_config = SecurityConfig(
|
95
|
+
auth=self.auth_config,
|
96
|
+
permissions=self.permission_config,
|
97
|
+
rate_limit=RateLimitConfig(enabled=True, default_requests_per_minute=100),
|
98
|
+
ssl=SSLConfig(enabled=False),
|
99
|
+
certificates=CertificateConfig(enabled=False)
|
100
|
+
)
|
101
|
+
|
102
|
+
# Create security manager
|
103
|
+
self.security_manager = SecurityManager(self.security_config)
|
104
|
+
|
105
|
+
def teardown_method(self):
|
106
|
+
"""Clean up after each test method."""
|
107
|
+
if hasattr(self, 'roles_path') and os.path.exists(self.roles_path):
|
108
|
+
os.unlink(self.roles_path)
|
109
|
+
|
110
|
+
def test_complete_api_key_authentication_flow(self):
|
111
|
+
"""Test complete API key authentication flow."""
|
112
|
+
# Test valid API key authentication
|
113
|
+
auth_result = self.security_manager.auth_manager.authenticate_api_key("admin_key_123456789012345")
|
114
|
+
|
115
|
+
assert auth_result.is_valid is True
|
116
|
+
assert auth_result.username == "admin"
|
117
|
+
assert "admin" in auth_result.roles
|
118
|
+
assert auth_result.auth_method == "api_key"
|
119
|
+
|
120
|
+
# Test invalid API key
|
121
|
+
auth_result = self.security_manager.auth_manager.authenticate_api_key("short")
|
122
|
+
|
123
|
+
assert auth_result.is_valid is False
|
124
|
+
assert auth_result.error_code == -32002
|
125
|
+
|
126
|
+
# Test missing API key
|
127
|
+
auth_result = self.security_manager.auth_manager.authenticate_api_key("")
|
128
|
+
|
129
|
+
assert auth_result.is_valid is False
|
130
|
+
assert auth_result.error_code == -32001
|
131
|
+
|
132
|
+
def test_complete_jwt_authentication_flow(self):
|
133
|
+
"""Test complete JWT authentication flow."""
|
134
|
+
# Create JWT token
|
135
|
+
payload = {
|
136
|
+
"username": "admin",
|
137
|
+
"roles": ["admin"],
|
138
|
+
"exp": datetime.utcnow() + timedelta(hours=24)
|
139
|
+
}
|
140
|
+
|
141
|
+
token = jwt.encode(
|
142
|
+
payload,
|
143
|
+
self.auth_config.jwt_secret.get_secret_value(),
|
144
|
+
algorithm=self.auth_config.jwt_algorithm
|
145
|
+
)
|
146
|
+
|
147
|
+
# Test valid JWT authentication
|
148
|
+
auth_result = self.security_manager.authenticate_user({
|
149
|
+
"method": "jwt",
|
150
|
+
"token": token
|
151
|
+
})
|
152
|
+
|
153
|
+
assert auth_result.is_valid is True
|
154
|
+
assert auth_result.username == "admin"
|
155
|
+
assert "admin" in auth_result.roles
|
156
|
+
assert auth_result.auth_method == "jwt"
|
157
|
+
|
158
|
+
# Test expired JWT token
|
159
|
+
expired_payload = {
|
160
|
+
"username": "admin",
|
161
|
+
"roles": ["admin"],
|
162
|
+
"exp": datetime.utcnow() - timedelta(hours=1)
|
163
|
+
}
|
164
|
+
|
165
|
+
expired_token = jwt.encode(
|
166
|
+
expired_payload,
|
167
|
+
self.auth_config.jwt_secret.get_secret_value(),
|
168
|
+
algorithm=self.auth_config.jwt_algorithm
|
169
|
+
)
|
170
|
+
|
171
|
+
auth_result = self.security_manager.authenticate_user({
|
172
|
+
"method": "jwt",
|
173
|
+
"token": expired_token
|
174
|
+
})
|
175
|
+
|
176
|
+
assert auth_result.is_valid is False
|
177
|
+
assert auth_result.error_code == -32002 # JWT token expired error
|
178
|
+
|
179
|
+
# Test invalid JWT token
|
180
|
+
auth_result = self.security_manager.authenticate_user({
|
181
|
+
"method": "jwt",
|
182
|
+
"token": "invalid_token"
|
183
|
+
})
|
184
|
+
|
185
|
+
assert auth_result.is_valid is False
|
186
|
+
assert auth_result.error_code == -32003 # Invalid JWT token error
|
187
|
+
|
188
|
+
def test_complete_authorization_flow(self):
|
189
|
+
"""Test complete authorization flow."""
|
190
|
+
# Test admin permissions
|
191
|
+
auth_result = self.security_manager.authenticate_user({
|
192
|
+
"method": "api_key",
|
193
|
+
"api_key": "admin_key_123456789012345"
|
194
|
+
})
|
195
|
+
|
196
|
+
assert auth_result.is_valid is True
|
197
|
+
|
198
|
+
# Check admin permissions
|
199
|
+
perm_result = self.security_manager.check_permissions(
|
200
|
+
auth_result.roles,
|
201
|
+
["read", "write", "delete", "admin"]
|
202
|
+
)
|
203
|
+
|
204
|
+
assert perm_result.is_valid is True
|
205
|
+
assert set(perm_result.granted_permissions) == {"read", "write", "delete", "admin", "moderate"}
|
206
|
+
|
207
|
+
# Test user permissions
|
208
|
+
auth_result = self.security_manager.auth_manager.authenticate_api_key("user_key_456789012345678")
|
209
|
+
|
210
|
+
assert auth_result.is_valid is True
|
211
|
+
|
212
|
+
# Check user permissions
|
213
|
+
perm_result = self.security_manager.check_permissions(
|
214
|
+
auth_result.roles,
|
215
|
+
["read", "write"]
|
216
|
+
)
|
217
|
+
|
218
|
+
assert perm_result.is_valid is True
|
219
|
+
assert set(perm_result.granted_permissions) == {"read", "write"}
|
220
|
+
|
221
|
+
# Test user denied admin permissions
|
222
|
+
perm_result = self.security_manager.check_permissions(
|
223
|
+
auth_result.roles,
|
224
|
+
["admin"]
|
225
|
+
)
|
226
|
+
|
227
|
+
assert perm_result.is_valid is False
|
228
|
+
assert perm_result.denied_permissions == ["admin"]
|
229
|
+
|
230
|
+
# Test readonly permissions
|
231
|
+
auth_result = self.security_manager.auth_manager.authenticate_api_key("readonly_key_789012345678")
|
232
|
+
|
233
|
+
assert auth_result.is_valid is True
|
234
|
+
|
235
|
+
# Check readonly permissions
|
236
|
+
perm_result = self.security_manager.check_permissions(
|
237
|
+
auth_result.roles,
|
238
|
+
["read"]
|
239
|
+
)
|
240
|
+
|
241
|
+
assert perm_result.is_valid is True
|
242
|
+
assert perm_result.granted_permissions == ["read"]
|
243
|
+
|
244
|
+
# Test readonly denied write permissions
|
245
|
+
perm_result = self.security_manager.check_permissions(
|
246
|
+
auth_result.roles,
|
247
|
+
["write"]
|
248
|
+
)
|
249
|
+
|
250
|
+
assert perm_result.is_valid is False
|
251
|
+
assert perm_result.denied_permissions == ["write"]
|
252
|
+
|
253
|
+
def test_role_hierarchy_flow(self):
|
254
|
+
"""Test role hierarchy inheritance flow."""
|
255
|
+
# Test admin role (inherits from user and guest)
|
256
|
+
auth_result = self.security_manager.auth_manager.authenticate_api_key("admin_key_123456789012345")
|
257
|
+
|
258
|
+
assert auth_result.is_valid is True
|
259
|
+
assert "admin" in auth_result.roles
|
260
|
+
# Admin inherits from user and guest through hierarchy
|
261
|
+
|
262
|
+
# Check inherited permissions (admin has all permissions including moderate from moderator)
|
263
|
+
perm_result = self.security_manager.check_permissions(
|
264
|
+
auth_result.roles,
|
265
|
+
["read", "write", "moderate", "admin"]
|
266
|
+
)
|
267
|
+
|
268
|
+
assert perm_result.is_valid is True
|
269
|
+
assert set(perm_result.granted_permissions) == {"read", "write", "moderate", "admin", "delete"}
|
270
|
+
assert "read" in perm_result.granted_permissions
|
271
|
+
assert "write" in perm_result.granted_permissions
|
272
|
+
assert "moderate" in perm_result.granted_permissions
|
273
|
+
|
274
|
+
def test_rate_limiting_integration_flow(self):
|
275
|
+
"""Test rate limiting integration with authentication."""
|
276
|
+
# Test rate limiting for authenticated user
|
277
|
+
user_identifier = "user_key_456789012345678"
|
278
|
+
|
279
|
+
# Make multiple requests to trigger rate limiting
|
280
|
+
for i in range(105): # Exceed default limit
|
281
|
+
rate_limit_result = self.security_manager.check_rate_limit(user_identifier)
|
282
|
+
|
283
|
+
# Rate limiting should work
|
284
|
+
assert isinstance(rate_limit_result, bool)
|
285
|
+
|
286
|
+
# Test rate limiting reset
|
287
|
+
# Note: In real implementation, this would depend on time window
|
288
|
+
# For testing, we'll just verify the mechanism works
|
289
|
+
|
290
|
+
def test_multi_method_authentication_flow(self):
|
291
|
+
"""Test authentication with multiple methods."""
|
292
|
+
# Test API key first, then JWT
|
293
|
+
auth_result = self.security_manager.auth_manager.authenticate_api_key("admin_key_123456789012345")
|
294
|
+
|
295
|
+
# Should use API key (first method)
|
296
|
+
assert auth_result.is_valid is True
|
297
|
+
assert auth_result.auth_method == "api_key"
|
298
|
+
|
299
|
+
# Test JWT when API key is invalid
|
300
|
+
auth_result = self.security_manager.authenticate_user({
|
301
|
+
"method": "api_key",
|
302
|
+
"api_key": "invalid_key"
|
303
|
+
})
|
304
|
+
|
305
|
+
# Should fail (both methods invalid)
|
306
|
+
assert auth_result.is_valid is False
|
307
|
+
|
308
|
+
def test_session_management_flow(self):
|
309
|
+
"""Test session management flow."""
|
310
|
+
# Create session for user
|
311
|
+
auth_result = self.security_manager.authenticate_user({
|
312
|
+
"method": "api_key",
|
313
|
+
"api_key": "user_key_456789012345678"
|
314
|
+
})
|
315
|
+
|
316
|
+
assert auth_result.is_valid is True
|
317
|
+
|
318
|
+
# Simulate session persistence
|
319
|
+
session_data = {
|
320
|
+
"user_id": auth_result.username,
|
321
|
+
"roles": auth_result.roles,
|
322
|
+
"permissions": auth_result.permissions,
|
323
|
+
"created_at": datetime.utcnow().isoformat()
|
324
|
+
}
|
325
|
+
|
326
|
+
# Verify session data
|
327
|
+
assert session_data["user_id"] == "user"
|
328
|
+
assert "user" in session_data["roles"]
|
329
|
+
assert "read" in session_data["permissions"]
|
330
|
+
assert "write" in session_data["permissions"]
|
331
|
+
|
332
|
+
def test_error_handling_flow(self):
|
333
|
+
"""Test error handling in authentication flow."""
|
334
|
+
# Test with malformed headers
|
335
|
+
auth_result = self.security_manager.authenticate_user({
|
336
|
+
"method": "api_key",
|
337
|
+
"api_key": "" # Empty API key
|
338
|
+
})
|
339
|
+
|
340
|
+
assert auth_result.is_valid is False
|
341
|
+
assert auth_result.error_code == -32001
|
342
|
+
|
343
|
+
# Test with invalid JWT format
|
344
|
+
auth_result = self.security_manager.authenticate_user({
|
345
|
+
"method": "jwt",
|
346
|
+
"token": "InvalidFormat token"
|
347
|
+
})
|
348
|
+
|
349
|
+
assert auth_result.is_valid is False
|
350
|
+
assert auth_result.error_code == -32003
|
351
|
+
|
352
|
+
# Test with unsupported authentication method
|
353
|
+
with pytest.raises(SecurityValidationError) as exc_info:
|
354
|
+
self.security_manager.authenticate_user({
|
355
|
+
"method": "custom",
|
356
|
+
"custom_token": "custom_token"
|
357
|
+
})
|
358
|
+
|
359
|
+
assert "Unsupported authentication method: custom" in str(exc_info.value)
|
360
|
+
|
361
|
+
def test_performance_benchmark_flow(self):
|
362
|
+
"""Test performance of authentication flow."""
|
363
|
+
import time
|
364
|
+
|
365
|
+
# Benchmark API key authentication
|
366
|
+
start_time = time.time()
|
367
|
+
for i in range(1000):
|
368
|
+
auth_result = self.security_manager.authenticate_user({
|
369
|
+
"method": "api_key",
|
370
|
+
"api_key": "admin_key_123456789012345"
|
371
|
+
})
|
372
|
+
assert auth_result.is_valid is True
|
373
|
+
end_time = time.time()
|
374
|
+
|
375
|
+
avg_time = (end_time - start_time) / 1000
|
376
|
+
assert avg_time < 0.001, f"API key auth too slow: {avg_time:.6f}s per request"
|
377
|
+
|
378
|
+
# Benchmark permission checking
|
379
|
+
auth_result = self.security_manager.authenticate_user({
|
380
|
+
"method": "api_key",
|
381
|
+
"api_key": "admin_key_123456789012345"
|
382
|
+
})
|
383
|
+
|
384
|
+
start_time = time.time()
|
385
|
+
for i in range(1000):
|
386
|
+
perm_result = self.security_manager.check_permissions(
|
387
|
+
auth_result.roles,
|
388
|
+
["read", "write", "delete"]
|
389
|
+
)
|
390
|
+
assert perm_result.is_valid is True
|
391
|
+
end_time = time.time()
|
392
|
+
|
393
|
+
avg_time = (end_time - start_time) / 1000
|
394
|
+
assert avg_time < 0.001, f"Permission check too slow: {avg_time:.6f}s per request"
|
395
|
+
|
396
|
+
def test_security_audit_flow(self):
|
397
|
+
"""Test security audit flow."""
|
398
|
+
# Perform security audit
|
399
|
+
audit_result = self.security_manager.perform_security_audit()
|
400
|
+
|
401
|
+
# Verify audit results
|
402
|
+
assert audit_result is not None
|
403
|
+
assert "authentication" in audit_result
|
404
|
+
assert "authorization" in audit_result
|
405
|
+
assert "rate_limiting" in audit_result
|
406
|
+
|
407
|
+
# Check authentication audit
|
408
|
+
auth_audit = audit_result["authentication"]
|
409
|
+
assert auth_audit["enabled"] is True
|
410
|
+
assert "api_key" in auth_audit["methods"]
|
411
|
+
assert "jwt" in auth_audit["methods"]
|
412
|
+
|
413
|
+
# Check authorization audit
|
414
|
+
authz_audit = audit_result["authorization"]
|
415
|
+
assert authz_audit["enabled"] is True
|
416
|
+
assert authz_audit["roles_count"] >= 4 # admin, user, readonly, moderator
|
417
|
+
|
418
|
+
# Check rate limiting audit
|
419
|
+
rate_audit = audit_result["rate_limiting"]
|
420
|
+
assert rate_audit["enabled"] is True
|
421
|
+
|
422
|
+
def test_configuration_validation_flow(self):
|
423
|
+
"""Test configuration validation flow."""
|
424
|
+
# Test valid configuration
|
425
|
+
validation_result = self.security_manager.validate_configuration()
|
426
|
+
assert validation_result.is_valid is True
|
427
|
+
|
428
|
+
# Test with invalid configuration (missing API keys)
|
429
|
+
invalid_auth_config = AuthConfig(
|
430
|
+
enabled=True,
|
431
|
+
methods=["api_key"],
|
432
|
+
api_keys={}, # Empty API keys
|
433
|
+
jwt_secret="test_secret_long_enough_for_validation"
|
434
|
+
)
|
435
|
+
|
436
|
+
invalid_config = SecurityConfig(
|
437
|
+
auth=invalid_auth_config,
|
438
|
+
permissions=self.permission_config,
|
439
|
+
rate_limit=RateLimitConfig(enabled=True, default_requests_per_minute=100),
|
440
|
+
ssl=SSLConfig(enabled=False),
|
441
|
+
certificates=CertificateConfig(enabled=False)
|
442
|
+
)
|
443
|
+
|
444
|
+
invalid_manager = SecurityManager(invalid_config)
|
445
|
+
validation_result = invalid_manager.validate_configuration()
|
446
|
+
assert validation_result.is_valid is False
|
447
|
+
|
448
|
+
def test_logging_and_monitoring_flow(self):
|
449
|
+
"""Test logging and monitoring flow."""
|
450
|
+
# Perform authentication with logging
|
451
|
+
auth_result = self.security_manager.authenticate_user({
|
452
|
+
"method": "api_key",
|
453
|
+
"api_key": "admin_key_123456789012345"
|
454
|
+
})
|
455
|
+
|
456
|
+
assert auth_result.is_valid is True
|
457
|
+
|
458
|
+
# Check that logging is configured
|
459
|
+
assert hasattr(self.security_manager.auth_manager, 'logger')
|
460
|
+
assert self.security_manager.auth_manager.logger is not None
|
461
|
+
|
462
|
+
assert hasattr(self.security_manager.permission_manager, 'logger')
|
463
|
+
assert self.security_manager.permission_manager.logger is not None
|
464
|
+
|
465
|
+
# Get security metrics
|
466
|
+
metrics = self.security_manager.get_security_metrics()
|
467
|
+
|
468
|
+
assert metrics is not None
|
469
|
+
assert "authentication_attempts" in metrics
|
470
|
+
assert "successful_authentications" in metrics
|
471
|
+
assert "failed_authentications" in metrics
|
472
|
+
assert "permission_checks" in metrics
|
473
|
+
assert "rate_limit_violations" in metrics
|
474
|
+
|
475
|
+
def test_integration_with_external_systems_flow(self):
|
476
|
+
"""Test integration with external systems flow."""
|
477
|
+
# Test with external user store (mocked)
|
478
|
+
with patch('mcp_security_framework.core.auth_manager.AuthManager._validate_external_user') as mock_validate:
|
479
|
+
mock_validate.return_value = True
|
480
|
+
|
481
|
+
auth_result = self.security_manager.authenticate_user({
|
482
|
+
"method": "api_key",
|
483
|
+
"api_key": "external_user_key"
|
484
|
+
})
|
485
|
+
|
486
|
+
# Should handle external authentication gracefully
|
487
|
+
assert auth_result.is_valid is False # Key not in config
|
488
|
+
assert auth_result.error_code == -32003
|
489
|
+
|
490
|
+
# Test with external permission store (mocked)
|
491
|
+
with patch('mcp_security_framework.core.permission_manager.PermissionManager._load_external_permissions') as mock_load:
|
492
|
+
mock_load.return_value = {"external_role": {"permissions": ["external_perm"]}}
|
493
|
+
|
494
|
+
# Should integrate with external permission systems
|
495
|
+
perm_result = self.security_manager.check_permissions(
|
496
|
+
["external_role"],
|
497
|
+
["external_perm"]
|
498
|
+
)
|
499
|
+
|
500
|
+
# In this case, external permissions would be loaded
|
501
|
+
# but the test role doesn't exist in our config
|
502
|
+
assert perm_result.is_valid is False
|