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