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.
Files changed (76) hide show
  1. mcp_security_framework/__init__.py +96 -0
  2. mcp_security_framework/cli/__init__.py +18 -0
  3. mcp_security_framework/cli/cert_cli.py +511 -0
  4. mcp_security_framework/cli/security_cli.py +791 -0
  5. mcp_security_framework/constants.py +209 -0
  6. mcp_security_framework/core/__init__.py +61 -0
  7. mcp_security_framework/core/auth_manager.py +1011 -0
  8. mcp_security_framework/core/cert_manager.py +1663 -0
  9. mcp_security_framework/core/permission_manager.py +735 -0
  10. mcp_security_framework/core/rate_limiter.py +602 -0
  11. mcp_security_framework/core/security_manager.py +943 -0
  12. mcp_security_framework/core/ssl_manager.py +735 -0
  13. mcp_security_framework/examples/__init__.py +75 -0
  14. mcp_security_framework/examples/django_example.py +615 -0
  15. mcp_security_framework/examples/fastapi_example.py +472 -0
  16. mcp_security_framework/examples/flask_example.py +506 -0
  17. mcp_security_framework/examples/gateway_example.py +803 -0
  18. mcp_security_framework/examples/microservice_example.py +690 -0
  19. mcp_security_framework/examples/standalone_example.py +576 -0
  20. mcp_security_framework/middleware/__init__.py +250 -0
  21. mcp_security_framework/middleware/auth_middleware.py +292 -0
  22. mcp_security_framework/middleware/fastapi_auth_middleware.py +447 -0
  23. mcp_security_framework/middleware/fastapi_middleware.py +757 -0
  24. mcp_security_framework/middleware/flask_auth_middleware.py +465 -0
  25. mcp_security_framework/middleware/flask_middleware.py +591 -0
  26. mcp_security_framework/middleware/mtls_middleware.py +439 -0
  27. mcp_security_framework/middleware/rate_limit_middleware.py +403 -0
  28. mcp_security_framework/middleware/security_middleware.py +507 -0
  29. mcp_security_framework/schemas/__init__.py +109 -0
  30. mcp_security_framework/schemas/config.py +694 -0
  31. mcp_security_framework/schemas/models.py +709 -0
  32. mcp_security_framework/schemas/responses.py +686 -0
  33. mcp_security_framework/tests/__init__.py +0 -0
  34. mcp_security_framework/utils/__init__.py +121 -0
  35. mcp_security_framework/utils/cert_utils.py +525 -0
  36. mcp_security_framework/utils/crypto_utils.py +475 -0
  37. mcp_security_framework/utils/validation_utils.py +571 -0
  38. mcp_security_framework-0.1.0.dist-info/METADATA +411 -0
  39. mcp_security_framework-0.1.0.dist-info/RECORD +76 -0
  40. mcp_security_framework-0.1.0.dist-info/WHEEL +5 -0
  41. mcp_security_framework-0.1.0.dist-info/entry_points.txt +3 -0
  42. mcp_security_framework-0.1.0.dist-info/top_level.txt +2 -0
  43. tests/__init__.py +0 -0
  44. tests/test_cli/__init__.py +0 -0
  45. tests/test_cli/test_cert_cli.py +379 -0
  46. tests/test_cli/test_security_cli.py +657 -0
  47. tests/test_core/__init__.py +0 -0
  48. tests/test_core/test_auth_manager.py +582 -0
  49. tests/test_core/test_cert_manager.py +795 -0
  50. tests/test_core/test_permission_manager.py +395 -0
  51. tests/test_core/test_rate_limiter.py +626 -0
  52. tests/test_core/test_security_manager.py +841 -0
  53. tests/test_core/test_ssl_manager.py +532 -0
  54. tests/test_examples/__init__.py +8 -0
  55. tests/test_examples/test_fastapi_example.py +264 -0
  56. tests/test_examples/test_flask_example.py +238 -0
  57. tests/test_examples/test_standalone_example.py +292 -0
  58. tests/test_integration/__init__.py +0 -0
  59. tests/test_integration/test_auth_flow.py +502 -0
  60. tests/test_integration/test_certificate_flow.py +527 -0
  61. tests/test_integration/test_fastapi_integration.py +341 -0
  62. tests/test_integration/test_flask_integration.py +398 -0
  63. tests/test_integration/test_standalone_integration.py +493 -0
  64. tests/test_middleware/__init__.py +0 -0
  65. tests/test_middleware/test_fastapi_middleware.py +523 -0
  66. tests/test_middleware/test_flask_middleware.py +582 -0
  67. tests/test_middleware/test_security_middleware.py +493 -0
  68. tests/test_schemas/__init__.py +0 -0
  69. tests/test_schemas/test_config.py +811 -0
  70. tests/test_schemas/test_models.py +879 -0
  71. tests/test_schemas/test_responses.py +1054 -0
  72. tests/test_schemas/test_serialization.py +493 -0
  73. tests/test_utils/__init__.py +0 -0
  74. tests/test_utils/test_cert_utils.py +510 -0
  75. tests/test_utils/test_crypto_utils.py +603 -0
  76. tests/test_utils/test_validation_utils.py +477 -0
@@ -0,0 +1,657 @@
1
+ """
2
+ Security CLI Tests
3
+
4
+ This module contains tests for the security management CLI commands.
5
+ """
6
+
7
+ import pytest
8
+ import tempfile
9
+ import os
10
+ from unittest.mock import Mock, patch, MagicMock
11
+ from click.testing import CliRunner
12
+
13
+ from mcp_security_framework.cli.security_cli import security_cli
14
+ from mcp_security_framework.schemas.config import SecurityConfig, AuthConfig, RateLimitConfig, SSLConfig, PermissionConfig
15
+ from mcp_security_framework.schemas.models import AuthResult, AuthStatus, AuthMethod, ValidationResult
16
+
17
+
18
+ class TestSecurityCLI:
19
+ """Test suite for security CLI commands."""
20
+
21
+ def setup_method(self):
22
+ """Set up test fixtures."""
23
+ self.runner = CliRunner()
24
+ self.temp_dir = tempfile.mkdtemp()
25
+
26
+ def teardown_method(self):
27
+ """Clean up test fixtures."""
28
+ import shutil
29
+ shutil.rmtree(self.temp_dir, ignore_errors=True)
30
+
31
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
32
+ def test_add_api_key_success(self, mock_security_manager_class):
33
+ """Test successful API key addition."""
34
+ # Mock security manager
35
+ mock_security_manager = Mock()
36
+ mock_security_manager_class.return_value = mock_security_manager
37
+ mock_security_manager.auth_manager.add_api_key.return_value = True
38
+
39
+ # Run command
40
+ result = self.runner.invoke(security_cli, [
41
+ 'auth', 'add-api-key',
42
+ '--username', 'testuser',
43
+ '--api-key', 'test_key_123'
44
+ ])
45
+
46
+ # Assertions
47
+ assert result.exit_code == 0
48
+ assert "✅ API key added successfully" in result.output
49
+ assert "testuser" in result.output
50
+
51
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
52
+ def test_add_api_key_failure(self, mock_security_manager_class):
53
+ """Test API key addition failure."""
54
+ # Mock security manager
55
+ mock_security_manager = Mock()
56
+ mock_security_manager_class.return_value = mock_security_manager
57
+ mock_security_manager.auth_manager.add_api_key.return_value = False
58
+
59
+ # Run command
60
+ result = self.runner.invoke(security_cli, [
61
+ 'auth', 'add-api-key',
62
+ '--username', 'testuser',
63
+ '--api-key', 'test_key_123'
64
+ ])
65
+
66
+ # Assertions
67
+ assert result.exit_code != 0
68
+ assert "❌ Failed to add API key" in result.output
69
+
70
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
71
+ def test_remove_api_key_success(self, mock_security_manager_class):
72
+ """Test successful API key removal."""
73
+ # Mock security manager
74
+ mock_security_manager = Mock()
75
+ mock_security_manager_class.return_value = mock_security_manager
76
+ mock_security_manager.auth_manager.remove_api_key.return_value = True
77
+
78
+ # Run command
79
+ result = self.runner.invoke(security_cli, [
80
+ 'auth', 'remove-api-key',
81
+ '--username', 'testuser'
82
+ ])
83
+
84
+ # Assertions
85
+ assert result.exit_code == 0
86
+ assert "✅ API key removed successfully" in result.output
87
+ assert "testuser" in result.output
88
+
89
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
90
+ def test_test_api_key_success(self, mock_security_manager_class):
91
+ """Test successful API key authentication."""
92
+ # Mock security manager
93
+ mock_security_manager = Mock()
94
+ mock_security_manager_class.return_value = mock_security_manager
95
+
96
+ # Mock auth result
97
+ mock_auth_result = Mock(spec=AuthResult)
98
+ mock_auth_result.is_valid = True
99
+ mock_auth_result.username = "testuser"
100
+ mock_auth_result.roles = ["user", "admin"]
101
+ mock_auth_result.auth_method = AuthMethod.API_KEY
102
+ mock_security_manager.auth_manager.authenticate_api_key.return_value = mock_auth_result
103
+
104
+ # Run command
105
+ result = self.runner.invoke(security_cli, [
106
+ 'auth', 'test-api-key',
107
+ '--api-key', 'test_key_123'
108
+ ])
109
+
110
+ # Assertions
111
+ assert result.exit_code == 0
112
+ assert "✅ API key authentication successful!" in result.output
113
+ assert "testuser" in result.output
114
+ assert "user, admin" in result.output
115
+
116
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
117
+ def test_test_api_key_failure(self, mock_security_manager_class):
118
+ """Test API key authentication failure."""
119
+ # Mock security manager
120
+ mock_security_manager = Mock()
121
+ mock_security_manager_class.return_value = mock_security_manager
122
+
123
+ # Mock auth result
124
+ mock_auth_result = Mock(spec=AuthResult)
125
+ mock_auth_result.is_valid = False
126
+ mock_auth_result.error_message = "Invalid API key"
127
+ mock_security_manager.auth_manager.authenticate_api_key.return_value = mock_auth_result
128
+
129
+ # Run command
130
+ result = self.runner.invoke(security_cli, [
131
+ 'auth', 'test-api-key',
132
+ '--api-key', 'invalid_key'
133
+ ])
134
+
135
+ # Assertions
136
+ assert result.exit_code != 0
137
+ assert "❌ API key authentication failed!" in result.output
138
+ assert "Invalid API key" in result.output
139
+
140
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
141
+ def test_test_jwt_success(self, mock_security_manager_class):
142
+ """Test successful JWT authentication."""
143
+ # Mock security manager
144
+ mock_security_manager = Mock()
145
+ mock_security_manager_class.return_value = mock_security_manager
146
+
147
+ # Mock auth result
148
+ mock_auth_result = Mock(spec=AuthResult)
149
+ mock_auth_result.is_valid = True
150
+ mock_auth_result.username = "testuser"
151
+ mock_auth_result.roles = ["user"]
152
+ mock_auth_result.auth_method = AuthMethod.JWT
153
+ mock_security_manager.auth_manager.authenticate_jwt_token.return_value = mock_auth_result
154
+
155
+ # Run command
156
+ result = self.runner.invoke(security_cli, [
157
+ 'auth', 'test-jwt',
158
+ '--token', 'test_jwt_token'
159
+ ])
160
+
161
+ # Assertions
162
+ assert result.exit_code == 0
163
+ assert "✅ JWT token authentication successful!" in result.output
164
+ assert "testuser" in result.output
165
+
166
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
167
+ def test_check_permissions_success(self, mock_security_manager_class):
168
+ """Test successful permission check."""
169
+ # Mock security manager
170
+ mock_security_manager = Mock()
171
+ mock_security_manager_class.return_value = mock_security_manager
172
+
173
+ # Mock user roles
174
+ mock_security_manager.auth_manager._get_user_roles.return_value = ["user", "admin"]
175
+
176
+ # Mock validation result
177
+ mock_validation_result = Mock(spec=ValidationResult)
178
+ mock_validation_result.is_valid = True
179
+ mock_validation_result.missing_permissions = []
180
+ mock_security_manager.permission_manager.validate_access.return_value = mock_validation_result
181
+
182
+ # Run command
183
+ result = self.runner.invoke(security_cli, [
184
+ 'permissions', 'check',
185
+ '--username', 'testuser',
186
+ '--permissions', 'read',
187
+ '--permissions', 'write'
188
+ ])
189
+
190
+ # Assertions
191
+ assert result.exit_code == 0
192
+ assert "✅ User has all required permissions!" in result.output
193
+ assert "testuser" in result.output
194
+ assert "user, admin" in result.output
195
+
196
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
197
+ def test_check_permissions_failure(self, mock_security_manager_class):
198
+ """Test permission check failure."""
199
+ # Mock security manager
200
+ mock_security_manager = Mock()
201
+ mock_security_manager_class.return_value = mock_security_manager
202
+
203
+ # Mock user roles
204
+ mock_security_manager.auth_manager._get_user_roles.return_value = ["user"]
205
+
206
+ # Mock validation result
207
+ mock_validation_result = Mock(spec=ValidationResult)
208
+ mock_validation_result.is_valid = False
209
+ mock_validation_result.missing_permissions = ["admin"]
210
+ mock_security_manager.permission_manager.validate_access.return_value = mock_validation_result
211
+
212
+ # Run command
213
+ result = self.runner.invoke(security_cli, [
214
+ 'permissions', 'check',
215
+ '--username', 'testuser',
216
+ '--permissions', 'admin'
217
+ ])
218
+
219
+ # Assertions
220
+ assert result.exit_code != 0
221
+ assert "❌ User does not have required permissions!" in result.output
222
+ assert "admin" in result.output
223
+
224
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
225
+ def test_list_role_permissions_success(self, mock_security_manager_class):
226
+ """Test successful role permissions listing."""
227
+ # Mock security manager
228
+ mock_security_manager = Mock()
229
+ mock_security_manager_class.return_value = mock_security_manager
230
+ mock_security_manager.permission_manager.get_role_permissions.return_value = ["read", "write", "delete"]
231
+
232
+ # Run command
233
+ result = self.runner.invoke(security_cli, [
234
+ 'permissions', 'list-role-permissions',
235
+ '--role', 'admin'
236
+ ])
237
+
238
+ # Assertions
239
+ assert result.exit_code == 0
240
+ assert "Permissions for role 'admin':" in result.output
241
+ assert "read" in result.output
242
+ assert "write" in result.output
243
+ assert "delete" in result.output
244
+
245
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
246
+ def test_rate_limit_check_success(self, mock_security_manager_class):
247
+ """Test successful rate limit check."""
248
+ # Mock security manager
249
+ mock_security_manager = Mock()
250
+ mock_security_manager_class.return_value = mock_security_manager
251
+ mock_security_manager.rate_limiter.check_rate_limit.return_value = True
252
+
253
+ # Run command
254
+ result = self.runner.invoke(security_cli, [
255
+ 'rate-limit', 'check',
256
+ '--identifier', '192.168.1.1'
257
+ ])
258
+
259
+ # Assertions
260
+ assert result.exit_code == 0
261
+ assert "✅ Rate limit check passed" in result.output
262
+ assert "192.168.1.1" in result.output
263
+
264
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
265
+ def test_rate_limit_check_failure(self, mock_security_manager_class):
266
+ """Test rate limit check failure."""
267
+ # Mock security manager
268
+ mock_security_manager = Mock()
269
+ mock_security_manager_class.return_value = mock_security_manager
270
+ mock_security_manager.rate_limiter.check_rate_limit.return_value = False
271
+
272
+ # Run command
273
+ result = self.runner.invoke(security_cli, [
274
+ 'rate-limit', 'check',
275
+ '--identifier', '192.168.1.1'
276
+ ])
277
+
278
+ # Assertions
279
+ assert result.exit_code != 0
280
+ assert "❌ Rate limit exceeded" in result.output
281
+
282
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
283
+ def test_rate_limit_reset_success(self, mock_security_manager_class):
284
+ """Test successful rate limit reset."""
285
+ # Mock security manager
286
+ mock_security_manager = Mock()
287
+ mock_security_manager_class.return_value = mock_security_manager
288
+
289
+ # Run command
290
+ result = self.runner.invoke(security_cli, [
291
+ 'rate-limit', 'reset',
292
+ '--identifier', '192.168.1.1'
293
+ ])
294
+
295
+ # Assertions
296
+ assert result.exit_code == 0
297
+ assert "✅ Rate limit reset successfully" in result.output
298
+ assert "192.168.1.1" in result.output
299
+
300
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
301
+ def test_rate_limit_status_success(self, mock_security_manager_class):
302
+ """Test successful rate limit status."""
303
+ # Mock security manager
304
+ mock_security_manager = Mock()
305
+ mock_security_manager_class.return_value = mock_security_manager
306
+
307
+ # Mock rate limit status
308
+ mock_status = Mock()
309
+ mock_status.current_count = 5
310
+ mock_status.limit = 100
311
+ mock_status.window_start = "2024-01-01 10:00:00"
312
+ mock_status.window_end = "2024-01-01 10:01:00"
313
+ mock_status.is_allowed = True
314
+ mock_security_manager.rate_limiter.get_rate_limit_status.return_value = mock_status
315
+
316
+ # Run command
317
+ result = self.runner.invoke(security_cli, [
318
+ 'rate-limit', 'status',
319
+ '--identifier', '192.168.1.1'
320
+ ])
321
+
322
+ # Assertions
323
+ assert result.exit_code == 0
324
+ assert "Rate Limit Status for '192.168.1.1':" in result.output
325
+ assert "Current Count: 5" in result.output
326
+ assert "Limit: 100" in result.output
327
+
328
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
329
+ def test_config_validate_success(self, mock_security_manager_class):
330
+ """Test successful configuration validation."""
331
+ # Mock security manager
332
+ mock_security_manager = Mock()
333
+ mock_security_manager_class.return_value = mock_security_manager
334
+
335
+ # Run command
336
+ result = self.runner.invoke(security_cli, [
337
+ 'config', 'validate'
338
+ ])
339
+
340
+ # Assertions
341
+ assert result.exit_code == 0
342
+ assert "✅ Configuration validation passed!" in result.output
343
+
344
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
345
+ def test_config_export_success(self, mock_security_manager_class):
346
+ """Test successful configuration export."""
347
+ # Mock security manager
348
+ mock_security_manager = Mock()
349
+ mock_security_manager_class.return_value = mock_security_manager
350
+
351
+ # Create temporary output file
352
+ output_file = os.path.join(self.temp_dir, "config.json")
353
+
354
+ # Run command
355
+ result = self.runner.invoke(security_cli, [
356
+ 'config', 'export',
357
+ '--output', output_file
358
+ ])
359
+
360
+ # Assertions
361
+ assert result.exit_code == 0
362
+ assert "✅ Configuration exported to:" in result.output
363
+ assert os.path.exists(output_file)
364
+
365
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
366
+ def test_status_success(self, mock_security_manager_class):
367
+ """Test successful security status display."""
368
+ # Mock security manager
369
+ mock_security_manager = Mock()
370
+ mock_security_manager_class.return_value = mock_security_manager
371
+ mock_security_manager.auth_manager = Mock()
372
+ mock_security_manager.permission_manager = Mock()
373
+ mock_security_manager.rate_limiter = Mock()
374
+ mock_security_manager.ssl_manager = Mock()
375
+ mock_security_manager.cert_manager = Mock()
376
+
377
+ # Run command
378
+ result = self.runner.invoke(security_cli, [
379
+ 'status'
380
+ ])
381
+
382
+ # Assertions
383
+ assert result.exit_code == 0
384
+ assert "Security Status:" in result.output
385
+ assert "Component Status:" in result.output
386
+
387
+ def test_help(self):
388
+ """Test CLI help output."""
389
+ result = self.runner.invoke(security_cli, ['--help'])
390
+ assert result.exit_code == 0
391
+ assert "Security Management CLI" in result.output
392
+
393
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
394
+ def test_auth_help(self, mock_security_manager_class):
395
+ """Test auth help output."""
396
+ # Mock security manager
397
+ mock_security_manager = Mock()
398
+ mock_security_manager_class.return_value = mock_security_manager
399
+
400
+ result = self.runner.invoke(security_cli, ['auth', '--help'])
401
+ assert result.exit_code == 0
402
+ assert "Authentication operations" in result.output
403
+
404
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
405
+ def test_permissions_help(self, mock_security_manager_class):
406
+ """Test permissions help output."""
407
+ # Mock security manager
408
+ mock_security_manager = Mock()
409
+ mock_security_manager_class.return_value = mock_security_manager
410
+
411
+ result = self.runner.invoke(security_cli, ['permissions', '--help'])
412
+ assert result.exit_code == 0
413
+ assert "Permission management operations" in result.output
414
+
415
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
416
+ def test_rate_limit_help(self, mock_security_manager_class):
417
+ """Test rate-limit help output."""
418
+ # Mock security manager
419
+ mock_security_manager = Mock()
420
+ mock_security_manager_class.return_value = mock_security_manager
421
+
422
+ result = self.runner.invoke(security_cli, ['rate-limit', '--help'])
423
+ assert result.exit_code == 0
424
+ assert "Rate limiting operations" in result.output
425
+
426
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
427
+ def test_config_help(self, mock_security_manager_class):
428
+ """Test config help output."""
429
+ # Mock security manager
430
+ mock_security_manager = Mock()
431
+ mock_security_manager_class.return_value = mock_security_manager
432
+
433
+ result = self.runner.invoke(security_cli, ['config', '--help'])
434
+ assert result.exit_code == 0
435
+ assert "Configuration management operations" in result.output
436
+
437
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
438
+ def test_missing_required_options(self, mock_security_manager_class):
439
+ """Test missing required options."""
440
+ # Mock security manager
441
+ mock_security_manager = Mock()
442
+ mock_security_manager_class.return_value = mock_security_manager
443
+
444
+ result = self.runner.invoke(security_cli, ['auth', 'add-api-key'])
445
+ assert result.exit_code != 0
446
+ assert "Missing option" in result.output
447
+
448
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
449
+ def test_generate_roles_template(self, mock_security_manager_class):
450
+ """Test generating template roles configuration."""
451
+ # Mock security manager
452
+ mock_security_manager = Mock()
453
+ mock_security_manager_class.return_value = mock_security_manager
454
+
455
+ # Run command
456
+ result = self.runner.invoke(security_cli, [
457
+ 'generate-roles',
458
+ '--template'
459
+ ])
460
+
461
+ # Assertions
462
+ assert result.exit_code == 0
463
+ assert "admin" in result.output
464
+ assert "user" in result.output
465
+ assert "guest" in result.output
466
+ assert "permissions" in result.output
467
+
468
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
469
+ def test_generate_roles_current(self, mock_security_manager_class):
470
+ """Test generating current roles configuration."""
471
+ # Mock security manager
472
+ mock_security_manager = Mock()
473
+ mock_security_manager_class.return_value = mock_security_manager
474
+
475
+ # Mock permission manager
476
+ mock_permission_manager = Mock()
477
+ mock_security_manager.permission_manager = mock_permission_manager
478
+
479
+ # Mock export method
480
+ mock_roles_config = {
481
+ "roles": {
482
+ "admin": {
483
+ "description": "Administrator role",
484
+ "permissions": ["*"],
485
+ "parent_roles": []
486
+ }
487
+ },
488
+ "permissions": {
489
+ "*": "All permissions"
490
+ }
491
+ }
492
+ mock_permission_manager.export_roles_config.return_value = mock_roles_config
493
+
494
+ # Run command
495
+ result = self.runner.invoke(security_cli, [
496
+ 'generate-roles'
497
+ ])
498
+
499
+ # Assertions
500
+ assert result.exit_code == 0
501
+ assert "admin" in result.output
502
+ assert "Administrator role" in result.output
503
+
504
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
505
+ def test_generate_roles_with_output(self, mock_security_manager_class):
506
+ """Test generating roles configuration with output file."""
507
+ # Mock security manager
508
+ mock_security_manager = Mock()
509
+ mock_security_manager_class.return_value = mock_security_manager
510
+
511
+ # Mock permission manager
512
+ mock_permission_manager = Mock()
513
+ mock_security_manager.permission_manager = mock_permission_manager
514
+
515
+ # Mock export method
516
+ mock_roles_config = {
517
+ "roles": {
518
+ "user": {
519
+ "description": "User role",
520
+ "permissions": ["read:own"],
521
+ "parent_roles": []
522
+ }
523
+ },
524
+ "permissions": {
525
+ "read:own": "Read own resources"
526
+ }
527
+ }
528
+ mock_permission_manager.export_roles_config.return_value = mock_roles_config
529
+
530
+ # Create temporary output file
531
+ output_file = os.path.join(self.temp_dir, "roles.json")
532
+
533
+ # Run command
534
+ result = self.runner.invoke(security_cli, [
535
+ 'generate-roles',
536
+ '--output', output_file
537
+ ])
538
+
539
+ # Assertions
540
+ assert result.exit_code == 0
541
+ assert "✅ Current roles configuration exported" in result.output
542
+ assert os.path.exists(output_file)
543
+
544
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
545
+ def test_security_audit_text_format(self, mock_security_manager_class):
546
+ """Test security audit in text format."""
547
+ # Mock security manager
548
+ mock_security_manager = Mock()
549
+ mock_security_manager_class.return_value = mock_security_manager
550
+
551
+ # Mock components
552
+ mock_auth_manager = Mock()
553
+ mock_auth_manager.api_keys = {"key1": "user1", "key2": "user2"}
554
+ mock_security_manager.auth_manager = mock_auth_manager
555
+
556
+ mock_permission_manager = Mock()
557
+ mock_permission_manager.roles = {"admin": {}, "user": {}}
558
+ mock_security_manager.permission_manager = mock_permission_manager
559
+
560
+ mock_security_manager.rate_limiter = Mock()
561
+ mock_security_manager.ssl_manager = Mock()
562
+ mock_security_manager.cert_manager = Mock()
563
+
564
+ # Run command
565
+ result = self.runner.invoke(security_cli, [
566
+ 'security-audit'
567
+ ])
568
+
569
+ # Assertions
570
+ assert result.exit_code == 0
571
+ assert "Security Audit Report" in result.output
572
+ assert "Configuration:" in result.output
573
+ assert "Components:" in result.output
574
+
575
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
576
+ def test_security_audit_json_format(self, mock_security_manager_class):
577
+ """Test security audit in JSON format."""
578
+ # Mock security manager
579
+ mock_security_manager = Mock()
580
+ mock_security_manager_class.return_value = mock_security_manager
581
+
582
+ # Mock components
583
+ mock_auth_manager = Mock()
584
+ mock_auth_manager.api_keys = {"key1": "user1"}
585
+ mock_security_manager.auth_manager = mock_auth_manager
586
+
587
+ mock_permission_manager = Mock()
588
+ mock_permission_manager.roles = {"admin": {}}
589
+ mock_security_manager.permission_manager = mock_permission_manager
590
+
591
+ mock_security_manager.rate_limiter = Mock()
592
+ mock_security_manager.ssl_manager = Mock()
593
+ mock_security_manager.cert_manager = Mock()
594
+
595
+ # Run command
596
+ result = self.runner.invoke(security_cli, [
597
+ 'security-audit',
598
+ '--format', 'json'
599
+ ])
600
+
601
+ # Assertions
602
+ assert result.exit_code == 0
603
+ assert "timestamp" in result.output
604
+ assert "configuration" in result.output
605
+ assert "components" in result.output
606
+
607
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
608
+ def test_security_audit_with_output(self, mock_security_manager_class):
609
+ """Test security audit with output file."""
610
+ # Mock security manager
611
+ mock_security_manager = Mock()
612
+ mock_security_manager_class.return_value = mock_security_manager
613
+
614
+ # Mock components
615
+ mock_auth_manager = Mock()
616
+ mock_auth_manager.api_keys = {"key1": "user1"}
617
+ mock_security_manager.auth_manager = mock_auth_manager
618
+
619
+ mock_permission_manager = Mock()
620
+ mock_permission_manager.roles = {"admin": {}}
621
+ mock_security_manager.permission_manager = mock_permission_manager
622
+
623
+ mock_security_manager.rate_limiter = Mock()
624
+ mock_security_manager.ssl_manager = Mock()
625
+ mock_security_manager.cert_manager = Mock()
626
+
627
+ # Create temporary output file
628
+ output_file = os.path.join(self.temp_dir, "audit.json")
629
+
630
+ # Run command
631
+ result = self.runner.invoke(security_cli, [
632
+ 'security-audit',
633
+ '--output', output_file,
634
+ '--format', 'json'
635
+ ])
636
+
637
+ # Assertions
638
+ assert result.exit_code == 0
639
+ assert "✅ Security audit report saved" in result.output
640
+ assert os.path.exists(output_file)
641
+
642
+ @patch('mcp_security_framework.cli.security_cli.SecurityManager')
643
+ def test_security_audit_failure(self, mock_security_manager_class):
644
+ """Test security audit failure."""
645
+ # Mock security manager
646
+ mock_security_manager = Mock()
647
+ mock_security_manager_class.return_value = mock_security_manager
648
+ mock_security_manager.auth_manager = None # This will cause an error
649
+
650
+ # Run command
651
+ result = self.runner.invoke(security_cli, [
652
+ 'security-audit'
653
+ ])
654
+
655
+ # Assertions
656
+ assert result.exit_code != 0
657
+ assert "❌ Failed to perform security audit" in result.output
File without changes