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,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
|