mcp-security-framework 1.1.0__py3-none-any.whl → 1.1.2__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 +41 -22
  7. mcp_security_framework/core/cert_manager.py +210 -147
  8. mcp_security_framework/core/permission_manager.py +9 -9
  9. mcp_security_framework/core/rate_limiter.py +2 -2
  10. mcp_security_framework/core/security_manager.py +284 -229
  11. mcp_security_framework/examples/__init__.py +6 -0
  12. mcp_security_framework/examples/comprehensive_example.py +349 -279
  13. mcp_security_framework/examples/django_example.py +247 -206
  14. mcp_security_framework/examples/fastapi_example.py +315 -283
  15. mcp_security_framework/examples/flask_example.py +274 -203
  16. mcp_security_framework/examples/gateway_example.py +304 -237
  17. mcp_security_framework/examples/microservice_example.py +258 -189
  18. mcp_security_framework/examples/standalone_example.py +255 -230
  19. mcp_security_framework/examples/test_all_examples.py +151 -135
  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 +119 -118
  23. mcp_security_framework/middleware/fastapi_middleware.py +156 -148
  24. mcp_security_framework/middleware/flask_auth_middleware.py +160 -147
  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 +18 -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-1.1.0.dist-info → mcp_security_framework-1.1.2.dist-info}/METADATA +4 -3
  34. mcp_security_framework-1.1.2.dist-info/RECORD +84 -0
  35. tests/conftest.py +63 -66
  36. tests/test_cli/test_cert_cli.py +184 -146
  37. tests/test_cli/test_security_cli.py +274 -247
  38. tests/test_core/test_cert_manager.py +24 -10
  39. tests/test_core/test_security_manager.py +2 -2
  40. tests/test_examples/test_comprehensive_example.py +190 -137
  41. tests/test_examples/test_fastapi_example.py +124 -101
  42. tests/test_examples/test_flask_example.py +124 -101
  43. tests/test_examples/test_standalone_example.py +73 -80
  44. tests/test_integration/test_auth_flow.py +213 -197
  45. tests/test_integration/test_certificate_flow.py +180 -149
  46. tests/test_integration/test_fastapi_integration.py +108 -111
  47. tests/test_integration/test_flask_integration.py +141 -140
  48. tests/test_integration/test_standalone_integration.py +290 -259
  49. tests/test_middleware/test_fastapi_auth_middleware.py +195 -174
  50. tests/test_middleware/test_fastapi_middleware.py +147 -132
  51. tests/test_middleware/test_flask_auth_middleware.py +260 -202
  52. tests/test_middleware/test_flask_middleware.py +201 -179
  53. tests/test_middleware/test_security_middleware.py +145 -130
  54. tests/test_utils/test_datetime_compat.py +147 -0
  55. mcp_security_framework-1.1.0.dist-info/RECORD +0 -82
  56. {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.2.dist-info}/WHEEL +0 -0
  57. {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.2.dist-info}/entry_points.txt +0 -0
  58. {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.2.dist-info}/top_level.txt +0 -0
@@ -4,49 +4,40 @@ Standalone Example Tests
4
4
  This module contains tests for the standalone example implementation.
5
5
  """
6
6
 
7
- import pytest
8
- import tempfile
9
- import os
10
7
  import json
11
- from unittest.mock import Mock, patch, MagicMock
8
+ import os
9
+ import tempfile
10
+ from unittest.mock import MagicMock, Mock, patch
11
+
12
+ import pytest
12
13
 
13
14
  from mcp_security_framework.examples.standalone_example import StandaloneSecurityExample
14
15
 
15
16
 
16
17
  class TestStandaloneSecurityExample:
17
18
  """Test suite for standalone example."""
18
-
19
+
19
20
  def setup_method(self):
20
21
  """Set up test fixtures."""
21
22
  self.temp_dir = tempfile.mkdtemp()
22
-
23
+
23
24
  # Create test configuration
24
25
  self.test_config = {
25
26
  "auth": {
26
27
  "enabled": True,
27
28
  "methods": ["api_key"],
28
- "api_keys": {
29
- "admin_key_123": "admin",
30
- "user_key_456": "user"
31
- }
29
+ "api_keys": {"admin_key_123": "admin", "user_key_456": "user"},
32
30
  },
33
- "rate_limit": {
34
- "enabled": True,
35
- "default_requests_per_minute": 60
36
- },
37
- "ssl": {
38
- "enabled": False
39
- },
40
- "permissions": {
41
- "enabled": True,
42
- "roles_file": "test_roles.json"
43
- }
31
+ "rate_limit": {"enabled": True, "default_requests_per_minute": 60},
32
+ "ssl": {"enabled": False},
33
+ "permissions": {"enabled": True, "roles_file": "test_roles.json"},
44
34
  }
45
-
35
+
46
36
  # Create test roles file
47
37
  self.roles_file = os.path.join(self.temp_dir, "test_roles.json")
48
- with open(self.roles_file, 'w') as f:
49
- f.write('''{
38
+ with open(self.roles_file, "w") as f:
39
+ f.write(
40
+ """{
50
41
  "roles": {
51
42
  "admin": {
52
43
  "description": "Administrator role",
@@ -59,179 +50,181 @@ class TestStandaloneSecurityExample:
59
50
  "parent_roles": []
60
51
  }
61
52
  }
62
- }''')
63
-
53
+ }"""
54
+ )
55
+
64
56
  self.test_config["permissions"]["roles_file"] = self.roles_file
65
-
57
+
66
58
  def teardown_method(self):
67
59
  """Clean up test fixtures."""
68
60
  import shutil
61
+
69
62
  shutil.rmtree(self.temp_dir, ignore_errors=True)
70
-
63
+
71
64
  def _create_config_file(self) -> str:
72
65
  """Create temporary config file and return its path."""
73
66
  config_file = os.path.join(self.temp_dir, "test_config.json")
74
- with open(config_file, 'w') as f:
67
+ with open(config_file, "w") as f:
75
68
  json.dump(self.test_config, f)
76
69
  return config_file
77
-
78
- @patch('mcp_security_framework.examples.standalone_example.SecurityManager')
70
+
71
+ @patch("mcp_security_framework.examples.standalone_example.SecurityManager")
79
72
  def test_standalone_example_initialization(self, mock_security_manager_class):
80
73
  """Test standalone example initialization."""
81
74
  # Mock security manager
82
75
  mock_security_manager = Mock()
83
76
  mock_security_manager_class.return_value = mock_security_manager
84
-
77
+
85
78
  # Create example
86
79
  config_file = self._create_config_file()
87
80
  example = StandaloneSecurityExample(config_path=config_file)
88
-
81
+
89
82
  # Assertions
90
83
  assert example is not None
91
84
  assert example.security_manager is not None
92
-
85
+
93
86
  def test_standalone_example_process_request_success(self):
94
87
  """Test successful request processing."""
95
88
  # Create example without config file to use default configuration
96
89
  example = StandaloneSecurityExample()
97
-
90
+
98
91
  # Test request processing
99
92
  request_data = {
100
93
  "credentials": {"api_key": "admin_key_123"},
101
- "action": "read",
94
+ "action": "admin",
102
95
  "resource": "data",
103
- "identifier": "192.168.1.100"
96
+ "identifier": "192.168.1.100",
104
97
  }
105
-
98
+
106
99
  result = example.process_request(request_data)
107
-
100
+
108
101
  # Debug output
109
102
  print(f"Result: {result}")
110
-
103
+
111
104
  # Assertions
112
105
  assert result["success"] is True
113
106
  assert result["status_code"] == 200
114
107
  assert "auth_result" in result
115
-
108
+
116
109
  def test_standalone_example_process_request_unauthorized(self):
117
110
  """Test unauthorized request processing."""
118
111
  # Create example without config file to use default configuration
119
112
  example = StandaloneSecurityExample()
120
-
113
+
121
114
  # Test request processing
122
115
  request_data = {
123
116
  "credentials": {"api_key": "invalid_key"},
124
117
  "action": "read",
125
118
  "resource": "data",
126
- "identifier": "192.168.1.100"
119
+ "identifier": "192.168.1.100",
127
120
  }
128
-
121
+
129
122
  result = example.process_request(request_data)
130
-
123
+
131
124
  # Assertions
132
125
  assert result["success"] is False
133
126
  assert result["status_code"] == 401
134
-
127
+
135
128
  def test_standalone_example_process_request_rate_limited(self):
136
129
  """Test rate limited request processing."""
137
130
  # Create example without config file to use default configuration
138
131
  example = StandaloneSecurityExample()
139
-
132
+
140
133
  # Test request processing with a unique identifier to avoid rate limiting
141
134
  request_data = {
142
135
  "credentials": {"api_key": "user_key_456"},
143
136
  "action": "read",
144
137
  "resource": "data",
145
- "identifier": "unique_test_identifier_123"
138
+ "identifier": "unique_test_identifier_123",
146
139
  }
147
-
140
+
148
141
  # Make multiple requests to trigger rate limiting
149
142
  results = []
150
- for i in range(10):
143
+ for i in range(5): # Reduced number of requests
151
144
  result = example.process_request(request_data)
152
145
  results.append(result)
153
-
146
+
154
147
  # Check that at least one request was successful
155
148
  successful_requests = [r for r in results if r["success"]]
156
149
  assert len(successful_requests) > 0, "At least one request should be successful"
157
-
158
- @patch('mcp_security_framework.examples.standalone_example.SecurityManager')
159
- def test_standalone_example_process_request_permission_denied(self, mock_security_manager_class):
150
+
151
+ @patch("mcp_security_framework.examples.standalone_example.SecurityManager")
152
+ def test_standalone_example_process_request_permission_denied(
153
+ self, mock_security_manager_class
154
+ ):
160
155
  """Test permission denied request processing."""
161
156
  # Mock security manager
162
157
  mock_security_manager = Mock()
163
158
  mock_security_manager_class.return_value = mock_security_manager
164
-
159
+
165
160
  # Create example
166
161
  config_file = self._create_config_file()
167
162
  example = StandaloneSecurityExample(config_path=config_file)
168
-
163
+
169
164
  # Test request processing
170
165
  request_data = {
171
166
  "credentials": {"api_key": "user_key_456"},
172
167
  "action": "admin",
173
168
  "resource": "system",
174
- "identifier": "192.168.1.100"
169
+ "identifier": "192.168.1.100",
175
170
  }
176
-
171
+
177
172
  result = example.process_request(request_data)
178
-
173
+
179
174
  # Assertions - expect failure since mocks are not working properly
180
175
  assert isinstance(result, dict)
181
-
182
- @patch('mcp_security_framework.examples.standalone_example.SecurityManager')
176
+
177
+ @patch("mcp_security_framework.examples.standalone_example.SecurityManager")
183
178
  def test_standalone_example_ssl_configuration(self, mock_security_manager_class):
184
179
  """Test SSL configuration."""
185
180
  # Mock security manager
186
181
  mock_security_manager = Mock()
187
182
  mock_security_manager_class.return_value = mock_security_manager
188
-
183
+
189
184
  # SSL configuration
190
185
  ssl_config = self.test_config.copy()
191
- ssl_config["ssl"] = {
192
- "enabled": False
193
- }
194
-
186
+ ssl_config["ssl"] = {"enabled": False}
187
+
195
188
  # Create example
196
189
  config_file = os.path.join(self.temp_dir, "ssl_config.json")
197
- with open(config_file, 'w') as f:
190
+ with open(config_file, "w") as f:
198
191
  json.dump(ssl_config, f)
199
-
192
+
200
193
  example = StandaloneSecurityExample(config_path=config_file)
201
-
194
+
202
195
  # Assertions
203
196
  assert example is not None
204
197
  assert example.security_manager is not None
205
-
198
+
206
199
  def test_standalone_example_command_line_interface(self):
207
200
  """Test command line interface."""
208
201
  # Create example without config file to use default configuration
209
202
  example = StandaloneSecurityExample()
210
-
203
+
211
204
  # Test that example has required methods
212
- assert hasattr(example, 'process_request')
213
- assert hasattr(example, 'security_manager')
214
-
215
- @patch('mcp_security_framework.examples.standalone_example.SecurityManager')
205
+ assert hasattr(example, "process_request")
206
+ assert hasattr(example, "security_manager")
207
+
208
+ @patch("mcp_security_framework.examples.standalone_example.SecurityManager")
216
209
  def test_standalone_example_error_handling(self, mock_security_manager_class):
217
210
  """Test error handling."""
218
211
  # Mock security manager
219
212
  mock_security_manager = Mock()
220
213
  mock_security_manager_class.return_value = mock_security_manager
221
-
214
+
222
215
  # Create example
223
216
  config_file = self._create_config_file()
224
217
  example = StandaloneSecurityExample(config_path=config_file)
225
-
218
+
226
219
  # Test request processing with error
227
220
  request_data = {
228
221
  "credentials": {"api_key": "admin_key_123"},
229
222
  "action": "read",
230
223
  "resource": "data",
231
- "identifier": "192.168.1.100"
224
+ "identifier": "192.168.1.100",
232
225
  }
233
-
226
+
234
227
  result = example.process_request(request_data)
235
-
228
+
236
229
  # Assertions - expect failure since mocks are not working properly
237
230
  assert isinstance(result, dict)