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.
- mcp_security_framework/__init__.py +26 -15
- mcp_security_framework/cli/__init__.py +1 -1
- mcp_security_framework/cli/cert_cli.py +233 -197
- mcp_security_framework/cli/security_cli.py +324 -234
- mcp_security_framework/constants.py +21 -27
- mcp_security_framework/core/auth_manager.py +41 -22
- mcp_security_framework/core/cert_manager.py +210 -147
- mcp_security_framework/core/permission_manager.py +9 -9
- mcp_security_framework/core/rate_limiter.py +2 -2
- mcp_security_framework/core/security_manager.py +284 -229
- mcp_security_framework/examples/__init__.py +6 -0
- mcp_security_framework/examples/comprehensive_example.py +349 -279
- mcp_security_framework/examples/django_example.py +247 -206
- mcp_security_framework/examples/fastapi_example.py +315 -283
- mcp_security_framework/examples/flask_example.py +274 -203
- mcp_security_framework/examples/gateway_example.py +304 -237
- mcp_security_framework/examples/microservice_example.py +258 -189
- mcp_security_framework/examples/standalone_example.py +255 -230
- mcp_security_framework/examples/test_all_examples.py +151 -135
- mcp_security_framework/middleware/__init__.py +46 -55
- mcp_security_framework/middleware/auth_middleware.py +62 -63
- mcp_security_framework/middleware/fastapi_auth_middleware.py +119 -118
- mcp_security_framework/middleware/fastapi_middleware.py +156 -148
- mcp_security_framework/middleware/flask_auth_middleware.py +160 -147
- mcp_security_framework/middleware/flask_middleware.py +183 -157
- mcp_security_framework/middleware/mtls_middleware.py +106 -117
- mcp_security_framework/middleware/rate_limit_middleware.py +105 -101
- mcp_security_framework/middleware/security_middleware.py +109 -124
- mcp_security_framework/schemas/config.py +2 -1
- mcp_security_framework/schemas/models.py +18 -6
- mcp_security_framework/utils/cert_utils.py +14 -8
- mcp_security_framework/utils/datetime_compat.py +116 -0
- {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.2.dist-info}/METADATA +4 -3
- mcp_security_framework-1.1.2.dist-info/RECORD +84 -0
- tests/conftest.py +63 -66
- tests/test_cli/test_cert_cli.py +184 -146
- tests/test_cli/test_security_cli.py +274 -247
- tests/test_core/test_cert_manager.py +24 -10
- tests/test_core/test_security_manager.py +2 -2
- tests/test_examples/test_comprehensive_example.py +190 -137
- tests/test_examples/test_fastapi_example.py +124 -101
- tests/test_examples/test_flask_example.py +124 -101
- tests/test_examples/test_standalone_example.py +73 -80
- tests/test_integration/test_auth_flow.py +213 -197
- tests/test_integration/test_certificate_flow.py +180 -149
- tests/test_integration/test_fastapi_integration.py +108 -111
- tests/test_integration/test_flask_integration.py +141 -140
- tests/test_integration/test_standalone_integration.py +290 -259
- tests/test_middleware/test_fastapi_auth_middleware.py +195 -174
- tests/test_middleware/test_fastapi_middleware.py +147 -132
- tests/test_middleware/test_flask_auth_middleware.py +260 -202
- tests/test_middleware/test_flask_middleware.py +201 -179
- tests/test_middleware/test_security_middleware.py +145 -130
- tests/test_utils/test_datetime_compat.py +147 -0
- mcp_security_framework-1.1.0.dist-info/RECORD +0 -82
- {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.2.dist-info}/WHEEL +0 -0
- {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.2.dist-info}/entry_points.txt +0 -0
- {mcp_security_framework-1.1.0.dist-info → mcp_security_framework-1.1.2.dist-info}/top_level.txt +0 -0
@@ -21,82 +21,98 @@ Version: 1.0.0
|
|
21
21
|
License: MIT
|
22
22
|
"""
|
23
23
|
|
24
|
-
import os
|
25
24
|
import json
|
26
25
|
import logging
|
27
|
-
import
|
26
|
+
import os
|
28
27
|
import shutil
|
29
|
-
|
28
|
+
import tempfile
|
30
29
|
from datetime import datetime, timedelta, timezone
|
30
|
+
from typing import Any, Dict, List, Optional
|
31
31
|
|
32
|
+
from mcp_security_framework.constants import (
|
33
|
+
AUTH_METHODS,
|
34
|
+
DEFAULT_SECURITY_HEADERS,
|
35
|
+
ErrorCodes,
|
36
|
+
)
|
32
37
|
from mcp_security_framework.core.security_manager import SecurityManager
|
33
38
|
from mcp_security_framework.schemas.config import (
|
34
|
-
|
35
|
-
CertificateConfig,
|
39
|
+
AuthConfig,
|
40
|
+
CertificateConfig,
|
41
|
+
LoggingConfig,
|
42
|
+
PermissionConfig,
|
43
|
+
RateLimitConfig,
|
44
|
+
SecurityConfig,
|
45
|
+
SSLConfig,
|
36
46
|
)
|
37
47
|
from mcp_security_framework.schemas.models import (
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
48
|
+
AuthMethod,
|
49
|
+
AuthResult,
|
50
|
+
AuthStatus,
|
51
|
+
CertificateInfo,
|
52
|
+
CertificatePair,
|
53
|
+
ValidationResult,
|
54
|
+
ValidationStatus,
|
43
55
|
)
|
44
56
|
|
45
57
|
|
46
58
|
class StandaloneSecurityExample:
|
47
59
|
"""
|
48
60
|
Comprehensive Standalone Security Example
|
49
|
-
|
61
|
+
|
50
62
|
This class demonstrates ALL capabilities of the MCP Security Framework
|
51
63
|
in a standalone environment, serving as a complete integration test.
|
52
64
|
"""
|
53
|
-
|
65
|
+
|
54
66
|
def __init__(self, config_path: Optional[str] = None):
|
55
67
|
"""
|
56
68
|
Initialize the standalone security example.
|
57
|
-
|
69
|
+
|
58
70
|
Args:
|
59
71
|
config_path: Optional path to configuration file
|
60
72
|
"""
|
61
73
|
self.config = self._load_config(config_path)
|
62
74
|
self.security_manager = SecurityManager(self.config)
|
63
75
|
self.logger = logging.getLogger(__name__)
|
64
|
-
|
76
|
+
|
65
77
|
# Test data
|
66
78
|
self.test_api_key = "admin_key_123"
|
67
79
|
self.test_jwt_token = self._create_test_jwt_token()
|
68
80
|
self.test_certificate = self._create_test_certificate()
|
69
|
-
|
81
|
+
|
70
82
|
self.logger.info("Standalone Security Example initialized successfully")
|
71
|
-
|
83
|
+
|
72
84
|
def _load_config(self, config_path: Optional[str] = None) -> SecurityConfig:
|
73
85
|
"""Load security configuration."""
|
74
86
|
if config_path and os.path.exists(config_path):
|
75
|
-
with open(config_path,
|
87
|
+
with open(config_path, "r") as f:
|
76
88
|
config_data = json.load(f)
|
77
89
|
return SecurityConfig(**config_data)
|
78
|
-
|
90
|
+
|
79
91
|
# Create comprehensive configuration
|
80
92
|
return SecurityConfig(
|
81
93
|
auth=AuthConfig(
|
82
94
|
enabled=True,
|
83
|
-
methods=[
|
95
|
+
methods=[
|
96
|
+
AUTH_METHODS["API_KEY"],
|
97
|
+
AUTH_METHODS["JWT"],
|
98
|
+
AUTH_METHODS["CERTIFICATE"],
|
99
|
+
],
|
84
100
|
api_keys={
|
85
101
|
"admin_key_123": {"username": "admin", "roles": ["admin", "user"]},
|
86
102
|
"user_key_456": {"username": "user", "roles": ["user"]},
|
87
|
-
"readonly_key_789": {"username": "readonly", "roles": ["readonly"]}
|
103
|
+
"readonly_key_789": {"username": "readonly", "roles": ["readonly"]},
|
88
104
|
},
|
89
105
|
jwt_secret="your-super-secret-jwt-key-change-in-production-12345",
|
90
106
|
jwt_algorithm="HS256",
|
91
107
|
jwt_expiry_hours=24,
|
92
108
|
public_paths=["/health/", "/metrics/"],
|
93
|
-
security_headers=DEFAULT_SECURITY_HEADERS
|
109
|
+
security_headers=DEFAULT_SECURITY_HEADERS,
|
94
110
|
),
|
95
111
|
permissions=PermissionConfig(
|
96
112
|
enabled=True,
|
97
113
|
roles_file="config/roles.json",
|
98
114
|
default_role="user",
|
99
|
-
hierarchy_enabled=True
|
115
|
+
hierarchy_enabled=True,
|
100
116
|
),
|
101
117
|
ssl=SSLConfig(
|
102
118
|
enabled=False, # Disable for standalone example
|
@@ -104,14 +120,14 @@ class StandaloneSecurityExample:
|
|
104
120
|
key_file=None,
|
105
121
|
ca_cert_file=None,
|
106
122
|
verify_mode="CERT_REQUIRED",
|
107
|
-
min_version="TLSv1.2"
|
123
|
+
min_version="TLSv1.2",
|
108
124
|
),
|
109
125
|
certificates=CertificateConfig(
|
110
126
|
enabled=False, # Disable for standalone example
|
111
127
|
ca_cert_path=None,
|
112
128
|
ca_key_path=None,
|
113
129
|
cert_validity_days=365,
|
114
|
-
key_size=2048
|
130
|
+
key_size=2048,
|
115
131
|
),
|
116
132
|
rate_limit=RateLimitConfig(
|
117
133
|
enabled=True,
|
@@ -120,7 +136,7 @@ class StandaloneSecurityExample:
|
|
120
136
|
burst_limit=2,
|
121
137
|
window_size_seconds=60,
|
122
138
|
storage_backend="memory",
|
123
|
-
cleanup_interval=300
|
139
|
+
cleanup_interval=300,
|
124
140
|
),
|
125
141
|
logging=LoggingConfig(
|
126
142
|
enabled=True,
|
@@ -130,24 +146,29 @@ class StandaloneSecurityExample:
|
|
130
146
|
max_file_size=10,
|
131
147
|
backup_count=5,
|
132
148
|
console_output=True,
|
133
|
-
json_format=False
|
149
|
+
json_format=False,
|
134
150
|
),
|
135
151
|
debug=True,
|
136
152
|
environment="test",
|
137
|
-
version="1.0.0"
|
153
|
+
version="1.0.0",
|
138
154
|
)
|
139
|
-
|
155
|
+
|
140
156
|
def _create_test_jwt_token(self) -> str:
|
141
157
|
"""Create a test JWT token."""
|
142
158
|
import jwt
|
159
|
+
|
143
160
|
payload = {
|
144
161
|
"username": "test_user",
|
145
162
|
"roles": ["user"],
|
146
|
-
"exp": datetime.now(timezone.utc) + timedelta(hours=1)
|
163
|
+
"exp": datetime.now(timezone.utc) + timedelta(hours=1),
|
147
164
|
}
|
148
|
-
jwt_secret =
|
165
|
+
jwt_secret = (
|
166
|
+
self.config.auth.jwt_secret.get_secret_value()
|
167
|
+
if self.config.auth.jwt_secret
|
168
|
+
else "default-jwt-secret-for-testing"
|
169
|
+
)
|
149
170
|
return jwt.encode(payload, jwt_secret, algorithm="HS256")
|
150
|
-
|
171
|
+
|
151
172
|
def _create_test_certificate(self) -> str:
|
152
173
|
"""Create a test certificate."""
|
153
174
|
return """-----BEGIN CERTIFICATE-----
|
@@ -162,104 +183,104 @@ eSBMdGQwHhcNMTkwMzI2MTIzMzQ5WhcNMjAwMzI1MTIzMzQ5WjBFMQswCQYDVQQG
|
|
162
183
|
EwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lk
|
163
184
|
Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
164
185
|
-----END CERTIFICATE-----"""
|
165
|
-
|
186
|
+
|
166
187
|
def demonstrate_authentication(self) -> Dict[str, Any]:
|
167
188
|
"""
|
168
189
|
Demonstrate ALL authentication methods.
|
169
|
-
|
190
|
+
|
170
191
|
Returns:
|
171
192
|
Dict with authentication test results
|
172
193
|
"""
|
173
194
|
self.logger.info("Demonstrating authentication capabilities...")
|
174
|
-
|
195
|
+
|
175
196
|
results = {
|
176
197
|
"api_key_auth": {},
|
177
198
|
"jwt_auth": {},
|
178
199
|
"certificate_auth": {},
|
179
|
-
"failed_auth": {}
|
200
|
+
"failed_auth": {},
|
180
201
|
}
|
181
|
-
|
202
|
+
|
182
203
|
# 1. API Key Authentication
|
183
204
|
try:
|
184
|
-
auth_result = self.security_manager.authenticate_user(
|
185
|
-
"method": "api_key",
|
186
|
-
|
187
|
-
})
|
205
|
+
auth_result = self.security_manager.authenticate_user(
|
206
|
+
{"method": "api_key", "api_key": self.test_api_key}
|
207
|
+
)
|
188
208
|
results["api_key_auth"] = {
|
189
209
|
"success": auth_result.is_valid,
|
190
210
|
"username": auth_result.username,
|
191
211
|
"roles": auth_result.roles,
|
192
|
-
"auth_method": auth_result.auth_method.value
|
212
|
+
"auth_method": auth_result.auth_method.value,
|
193
213
|
}
|
194
|
-
self.logger.info(
|
214
|
+
self.logger.info(
|
215
|
+
f"API Key auth: {auth_result.username} - {auth_result.roles}"
|
216
|
+
)
|
195
217
|
except Exception as e:
|
196
218
|
results["api_key_auth"] = {"error": str(e)}
|
197
|
-
|
219
|
+
|
198
220
|
# 2. JWT Authentication
|
199
221
|
try:
|
200
|
-
auth_result = self.security_manager.authenticate_user(
|
201
|
-
"method": "jwt",
|
202
|
-
|
203
|
-
})
|
222
|
+
auth_result = self.security_manager.authenticate_user(
|
223
|
+
{"method": "jwt", "token": self.test_jwt_token}
|
224
|
+
)
|
204
225
|
results["jwt_auth"] = {
|
205
226
|
"success": auth_result.is_valid,
|
206
227
|
"username": auth_result.username,
|
207
228
|
"roles": auth_result.roles,
|
208
|
-
"auth_method": auth_result.auth_method.value
|
229
|
+
"auth_method": auth_result.auth_method.value,
|
209
230
|
}
|
210
231
|
self.logger.info(f"JWT auth: {auth_result.username} - {auth_result.roles}")
|
211
232
|
except Exception as e:
|
212
233
|
results["jwt_auth"] = {"error": str(e)}
|
213
|
-
|
234
|
+
|
214
235
|
# 3. Certificate Authentication
|
215
236
|
try:
|
216
|
-
auth_result = self.security_manager.authenticate_user(
|
217
|
-
"method": "certificate",
|
218
|
-
|
219
|
-
})
|
237
|
+
auth_result = self.security_manager.authenticate_user(
|
238
|
+
{"method": "certificate", "certificate": self.test_certificate}
|
239
|
+
)
|
220
240
|
results["certificate_auth"] = {
|
221
241
|
"success": auth_result.is_valid,
|
222
242
|
"username": auth_result.username,
|
223
243
|
"roles": auth_result.roles,
|
224
|
-
"auth_method": auth_result.auth_method.value
|
244
|
+
"auth_method": auth_result.auth_method.value,
|
225
245
|
}
|
226
|
-
self.logger.info(
|
246
|
+
self.logger.info(
|
247
|
+
f"Certificate auth: {auth_result.username} - {auth_result.roles}"
|
248
|
+
)
|
227
249
|
except Exception as e:
|
228
250
|
results["certificate_auth"] = {"error": str(e)}
|
229
|
-
|
251
|
+
|
230
252
|
# 4. Failed Authentication
|
231
253
|
try:
|
232
|
-
auth_result = self.security_manager.authenticate_user(
|
233
|
-
"method": "api_key",
|
234
|
-
|
235
|
-
})
|
254
|
+
auth_result = self.security_manager.authenticate_user(
|
255
|
+
{"method": "api_key", "api_key": "invalid_key"}
|
256
|
+
)
|
236
257
|
results["failed_auth"] = {
|
237
258
|
"success": auth_result.is_valid,
|
238
259
|
"error_message": auth_result.error_message,
|
239
|
-
"error_code": auth_result.error_code
|
260
|
+
"error_code": auth_result.error_code,
|
240
261
|
}
|
241
262
|
self.logger.info(f"Failed auth test: {auth_result.error_message}")
|
242
263
|
except Exception as e:
|
243
264
|
results["failed_auth"] = {"error": str(e)}
|
244
|
-
|
265
|
+
|
245
266
|
return results
|
246
|
-
|
267
|
+
|
247
268
|
def demonstrate_authorization(self) -> Dict[str, Any]:
|
248
269
|
"""
|
249
270
|
Demonstrate authorization capabilities.
|
250
|
-
|
271
|
+
|
251
272
|
Returns:
|
252
273
|
Dict with authorization test results
|
253
274
|
"""
|
254
275
|
self.logger.info("Demonstrating authorization capabilities...")
|
255
|
-
|
276
|
+
|
256
277
|
results = {
|
257
278
|
"admin_permissions": {},
|
258
279
|
"user_permissions": {},
|
259
280
|
"readonly_permissions": {},
|
260
|
-
"denied_permissions": {}
|
281
|
+
"denied_permissions": {},
|
261
282
|
}
|
262
|
-
|
283
|
+
|
263
284
|
# 1. Admin permissions
|
264
285
|
try:
|
265
286
|
result = self.security_manager.check_permissions(
|
@@ -267,12 +288,12 @@ Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
267
288
|
)
|
268
289
|
results["admin_permissions"] = {
|
269
290
|
"success": result.is_valid,
|
270
|
-
"status": result.status.value
|
291
|
+
"status": result.status.value,
|
271
292
|
}
|
272
293
|
self.logger.info(f"Admin permissions: {result.is_valid}")
|
273
294
|
except Exception as e:
|
274
295
|
results["admin_permissions"] = {"error": str(e)}
|
275
|
-
|
296
|
+
|
276
297
|
# 2. User permissions
|
277
298
|
try:
|
278
299
|
result = self.security_manager.check_permissions(
|
@@ -280,94 +301,85 @@ Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
280
301
|
)
|
281
302
|
results["user_permissions"] = {
|
282
303
|
"success": result.is_valid,
|
283
|
-
"status": result.status.value
|
304
|
+
"status": result.status.value,
|
284
305
|
}
|
285
306
|
self.logger.info(f"User permissions: {result.is_valid}")
|
286
307
|
except Exception as e:
|
287
308
|
results["user_permissions"] = {"error": str(e)}
|
288
|
-
|
309
|
+
|
289
310
|
# 3. Readonly permissions
|
290
311
|
try:
|
291
|
-
result = self.security_manager.check_permissions(
|
292
|
-
["readonly"], ["read"]
|
293
|
-
)
|
312
|
+
result = self.security_manager.check_permissions(["readonly"], ["read"])
|
294
313
|
results["readonly_permissions"] = {
|
295
314
|
"success": result.is_valid,
|
296
|
-
"status": result.status.value
|
315
|
+
"status": result.status.value,
|
297
316
|
}
|
298
317
|
self.logger.info(f"Readonly permissions: {result.is_valid}")
|
299
318
|
except Exception as e:
|
300
319
|
results["readonly_permissions"] = {"error": str(e)}
|
301
|
-
|
320
|
+
|
302
321
|
# 4. Denied permissions
|
303
322
|
try:
|
304
|
-
result = self.security_manager.check_permissions(
|
305
|
-
["readonly"], ["delete"]
|
306
|
-
)
|
323
|
+
result = self.security_manager.check_permissions(["readonly"], ["delete"])
|
307
324
|
results["denied_permissions"] = {
|
308
325
|
"success": result.is_valid,
|
309
326
|
"status": result.status.value,
|
310
|
-
"error_message": result.error_message
|
327
|
+
"error_message": result.error_message,
|
311
328
|
}
|
312
329
|
self.logger.info(f"Denied permissions: {result.is_valid}")
|
313
330
|
except Exception as e:
|
314
331
|
results["denied_permissions"] = {"error": str(e)}
|
315
|
-
|
332
|
+
|
316
333
|
return results
|
317
|
-
|
334
|
+
|
318
335
|
def demonstrate_rate_limiting(self) -> Dict[str, Any]:
|
319
336
|
"""
|
320
337
|
Demonstrate rate limiting capabilities.
|
321
|
-
|
338
|
+
|
322
339
|
Returns:
|
323
340
|
Dict with rate limiting test results
|
324
341
|
"""
|
325
342
|
self.logger.info("Demonstrating rate limiting capabilities...")
|
326
|
-
|
327
|
-
results = {
|
328
|
-
|
329
|
-
"rate_limit_exceeded": False
|
330
|
-
}
|
331
|
-
|
343
|
+
|
344
|
+
results = {"rate_limit_checks": [], "rate_limit_exceeded": False}
|
345
|
+
|
332
346
|
identifier = "test_user_123"
|
333
|
-
|
347
|
+
|
334
348
|
# Test rate limiting
|
335
349
|
for i in range(5):
|
336
350
|
try:
|
337
351
|
allowed = self.security_manager.check_rate_limit(identifier)
|
338
|
-
results["rate_limit_checks"].append(
|
339
|
-
"request": i + 1,
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
352
|
+
results["rate_limit_checks"].append(
|
353
|
+
{"request": i + 1, "allowed": allowed}
|
354
|
+
)
|
355
|
+
self.logger.info(
|
356
|
+
f"Rate limit check {i+1}: {'Allowed' if allowed else 'Blocked'}"
|
357
|
+
)
|
358
|
+
|
344
359
|
if not allowed:
|
345
360
|
results["rate_limit_exceeded"] = True
|
346
361
|
break
|
347
|
-
|
362
|
+
|
348
363
|
except Exception as e:
|
349
|
-
results["rate_limit_checks"].append({
|
350
|
-
|
351
|
-
"error": str(e)
|
352
|
-
})
|
353
|
-
|
364
|
+
results["rate_limit_checks"].append({"request": i + 1, "error": str(e)})
|
365
|
+
|
354
366
|
return results
|
355
|
-
|
367
|
+
|
356
368
|
def demonstrate_certificate_management(self) -> Dict[str, Any]:
|
357
369
|
"""
|
358
370
|
Demonstrate certificate management capabilities.
|
359
|
-
|
371
|
+
|
360
372
|
Returns:
|
361
373
|
Dict with certificate management test results
|
362
374
|
"""
|
363
375
|
self.logger.info("Demonstrating certificate management capabilities...")
|
364
|
-
|
376
|
+
|
365
377
|
results = {
|
366
378
|
"certificate_creation": {},
|
367
379
|
"certificate_validation": {},
|
368
|
-
"certificate_info": {}
|
380
|
+
"certificate_info": {},
|
369
381
|
}
|
370
|
-
|
382
|
+
|
371
383
|
# 1. Certificate creation (if enabled)
|
372
384
|
if self.config.certificates.enabled:
|
373
385
|
try:
|
@@ -376,19 +388,19 @@ Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
376
388
|
"common_name": "test-client.example.com",
|
377
389
|
"organization": "Test Organization",
|
378
390
|
"country": "US",
|
379
|
-
"validity_days": 365
|
391
|
+
"validity_days": 365,
|
380
392
|
}
|
381
|
-
|
393
|
+
|
382
394
|
# Note: This would require actual CA files
|
383
395
|
# cert_pair = self.security_manager.create_certificate(cert_config)
|
384
396
|
results["certificate_creation"] = {
|
385
397
|
"success": True,
|
386
|
-
"message": "Certificate creation capability demonstrated"
|
398
|
+
"message": "Certificate creation capability demonstrated",
|
387
399
|
}
|
388
400
|
self.logger.info("Certificate creation capability demonstrated")
|
389
401
|
except Exception as e:
|
390
402
|
results["certificate_creation"] = {"error": str(e)}
|
391
|
-
|
403
|
+
|
392
404
|
# 2. Certificate validation
|
393
405
|
try:
|
394
406
|
# Test with dummy certificate
|
@@ -398,81 +410,74 @@ Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
398
410
|
serial_number="123456789",
|
399
411
|
valid_from=datetime.now(timezone.utc),
|
400
412
|
valid_until=datetime.now(timezone.utc) + timedelta(days=365),
|
401
|
-
is_valid=True
|
413
|
+
is_valid=True,
|
402
414
|
)
|
403
415
|
results["certificate_validation"] = {
|
404
416
|
"success": True,
|
405
417
|
"certificate_info": {
|
406
418
|
"subject": cert_info.subject,
|
407
419
|
"issuer": cert_info.issuer,
|
408
|
-
"is_valid": cert_info.is_valid
|
409
|
-
}
|
420
|
+
"is_valid": cert_info.is_valid,
|
421
|
+
},
|
410
422
|
}
|
411
423
|
self.logger.info("Certificate validation capability demonstrated")
|
412
424
|
except Exception as e:
|
413
425
|
results["certificate_validation"] = {"error": str(e)}
|
414
|
-
|
426
|
+
|
415
427
|
return results
|
416
|
-
|
428
|
+
|
417
429
|
def demonstrate_security_validation(self) -> Dict[str, Any]:
|
418
430
|
"""
|
419
431
|
Demonstrate security validation capabilities.
|
420
|
-
|
432
|
+
|
421
433
|
Returns:
|
422
434
|
Dict with validation test results
|
423
435
|
"""
|
424
436
|
self.logger.info("Demonstrating security validation capabilities...")
|
425
|
-
|
426
|
-
results = {
|
427
|
-
|
428
|
-
"configuration_validation": {}
|
429
|
-
}
|
430
|
-
|
437
|
+
|
438
|
+
results = {"request_validation": {}, "configuration_validation": {}}
|
439
|
+
|
431
440
|
# 1. Request validation
|
432
441
|
try:
|
433
442
|
request_data = {
|
434
443
|
"api_key": self.test_api_key,
|
435
444
|
"required_permissions": ["read", "write"],
|
436
|
-
"client_ip": "192.168.1.100"
|
445
|
+
"client_ip": "192.168.1.100",
|
437
446
|
}
|
438
|
-
|
447
|
+
|
439
448
|
result = self.security_manager.validate_request(request_data)
|
440
449
|
results["request_validation"] = {
|
441
450
|
"success": result.is_valid,
|
442
|
-
"status": result.status.value
|
451
|
+
"status": result.status.value,
|
443
452
|
}
|
444
453
|
self.logger.info(f"Request validation: {result.is_valid}")
|
445
454
|
except Exception as e:
|
446
455
|
results["request_validation"] = {"error": str(e)}
|
447
|
-
|
456
|
+
|
448
457
|
# 2. Configuration validation
|
449
458
|
try:
|
450
459
|
result = self.security_manager.validate_configuration()
|
451
460
|
results["configuration_validation"] = {
|
452
461
|
"success": result.is_valid,
|
453
|
-
"status": result.status.value
|
462
|
+
"status": result.status.value,
|
454
463
|
}
|
455
464
|
self.logger.info(f"Configuration validation: {result.is_valid}")
|
456
465
|
except Exception as e:
|
457
466
|
results["configuration_validation"] = {"error": str(e)}
|
458
|
-
|
467
|
+
|
459
468
|
return results
|
460
|
-
|
469
|
+
|
461
470
|
def demonstrate_security_monitoring(self) -> Dict[str, Any]:
|
462
471
|
"""
|
463
472
|
Demonstrate security monitoring capabilities.
|
464
|
-
|
473
|
+
|
465
474
|
Returns:
|
466
475
|
Dict with monitoring test results
|
467
476
|
"""
|
468
477
|
self.logger.info("Demonstrating security monitoring capabilities...")
|
469
|
-
|
470
|
-
results = {
|
471
|
-
|
472
|
-
"security_metrics": {},
|
473
|
-
"security_audit": {}
|
474
|
-
}
|
475
|
-
|
478
|
+
|
479
|
+
results = {"security_status": {}, "security_metrics": {}, "security_audit": {}}
|
480
|
+
|
476
481
|
# 1. Security status
|
477
482
|
try:
|
478
483
|
status = self.security_manager.get_security_status()
|
@@ -480,26 +485,26 @@ Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
480
485
|
"status": status.status.value,
|
481
486
|
"message": status.message,
|
482
487
|
"version": status.version,
|
483
|
-
"metadata": status.metadata
|
488
|
+
"metadata": status.metadata,
|
484
489
|
}
|
485
490
|
print(f"Security status: {results['security_status']}")
|
486
491
|
self.logger.info("Security status retrieved successfully")
|
487
492
|
except Exception as e:
|
488
493
|
results["security_status"] = {"error": str(e)}
|
489
494
|
print(f"Security status error: {str(e)}")
|
490
|
-
|
495
|
+
|
491
496
|
# 2. Security metrics
|
492
497
|
try:
|
493
498
|
metrics = self.security_manager.get_security_metrics()
|
494
499
|
results["security_metrics"] = {
|
495
500
|
"authentication_attempts": metrics.get("authentication_attempts", 0),
|
496
501
|
"security_events": metrics.get("security_events", 0),
|
497
|
-
"uptime_seconds": metrics.get("uptime_seconds", 0)
|
502
|
+
"uptime_seconds": metrics.get("uptime_seconds", 0),
|
498
503
|
}
|
499
504
|
self.logger.info("Security metrics retrieved successfully")
|
500
505
|
except Exception as e:
|
501
506
|
results["security_metrics"] = {"error": str(e)}
|
502
|
-
|
507
|
+
|
503
508
|
# 3. Security audit
|
504
509
|
try:
|
505
510
|
audit = self.security_manager.perform_security_audit()
|
@@ -507,23 +512,23 @@ Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
507
512
|
"authentication": audit.get("authentication", {}),
|
508
513
|
"authorization": audit.get("authorization", {}),
|
509
514
|
"rate_limiting": audit.get("rate_limiting", {}),
|
510
|
-
"ssl": audit.get("ssl", {})
|
515
|
+
"ssl": audit.get("ssl", {}),
|
511
516
|
}
|
512
517
|
self.logger.info("Security audit completed successfully")
|
513
518
|
except Exception as e:
|
514
519
|
results["security_audit"] = {"error": str(e)}
|
515
|
-
|
520
|
+
|
516
521
|
return results
|
517
|
-
|
522
|
+
|
518
523
|
def run_comprehensive_demo(self) -> Dict[str, Any]:
|
519
524
|
"""
|
520
525
|
Run comprehensive demonstration of ALL framework capabilities.
|
521
|
-
|
526
|
+
|
522
527
|
Returns:
|
523
528
|
Dict with all demonstration results
|
524
529
|
"""
|
525
530
|
self.logger.info("Starting comprehensive security framework demonstration...")
|
526
|
-
|
531
|
+
|
527
532
|
demo_results = {
|
528
533
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
529
534
|
"framework": "MCP Security Framework",
|
@@ -533,16 +538,16 @@ Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
533
538
|
"rate_limiting": self.demonstrate_rate_limiting(),
|
534
539
|
"certificate_management": self.demonstrate_certificate_management(),
|
535
540
|
"security_validation": self.demonstrate_security_validation(),
|
536
|
-
"security_monitoring": self.demonstrate_security_monitoring()
|
541
|
+
"security_monitoring": self.demonstrate_security_monitoring(),
|
537
542
|
}
|
538
|
-
|
543
|
+
|
539
544
|
self.logger.info("Comprehensive demonstration completed successfully")
|
540
545
|
return demo_results
|
541
|
-
|
546
|
+
|
542
547
|
def process_request(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
|
543
548
|
"""
|
544
549
|
Process a security request.
|
545
|
-
|
550
|
+
|
546
551
|
Args:
|
547
552
|
request_data: Dictionary containing request information
|
548
553
|
- credentials: Authentication credentials
|
@@ -550,7 +555,7 @@ Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
550
555
|
- resource: Resource being accessed
|
551
556
|
- identifier: Client identifier for rate limiting
|
552
557
|
- data: Optional data for write operations
|
553
|
-
|
558
|
+
|
554
559
|
Returns:
|
555
560
|
Dictionary with processing results
|
556
561
|
"""
|
@@ -561,7 +566,7 @@ Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
561
566
|
resource = request_data.get("resource", "/")
|
562
567
|
identifier = request_data.get("identifier", "unknown")
|
563
568
|
data = request_data.get("data")
|
564
|
-
|
569
|
+
|
565
570
|
# Check rate limiting
|
566
571
|
rate_limit_result = self.security_manager.check_rate_limit(identifier)
|
567
572
|
if not rate_limit_result:
|
@@ -569,52 +574,48 @@ Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
569
574
|
"success": False,
|
570
575
|
"status_code": 429,
|
571
576
|
"error": "Rate limit exceeded",
|
572
|
-
"retry_after": 60
|
577
|
+
"retry_after": 60,
|
573
578
|
}
|
574
|
-
|
579
|
+
|
575
580
|
# Authenticate request
|
576
581
|
auth_result = None
|
577
582
|
if "api_key" in credentials:
|
578
|
-
auth_result = self.security_manager.authenticate_user(
|
579
|
-
"method": "api_key",
|
580
|
-
|
581
|
-
})
|
583
|
+
auth_result = self.security_manager.authenticate_user(
|
584
|
+
{"method": "api_key", "api_key": credentials["api_key"]}
|
585
|
+
)
|
582
586
|
elif "jwt_token" in credentials:
|
583
|
-
auth_result = self.security_manager.authenticate_user(
|
584
|
-
"method": "jwt",
|
585
|
-
|
586
|
-
})
|
587
|
+
auth_result = self.security_manager.authenticate_user(
|
588
|
+
{"method": "jwt", "token": credentials["jwt_token"]}
|
589
|
+
)
|
587
590
|
elif "certificate" in credentials:
|
588
|
-
auth_result = self.security_manager.authenticate_user(
|
589
|
-
"method": "certificate",
|
590
|
-
|
591
|
-
|
592
|
-
|
591
|
+
auth_result = self.security_manager.authenticate_user(
|
592
|
+
{"method": "certificate", "certificate": credentials["certificate"]}
|
593
|
+
)
|
594
|
+
|
593
595
|
# Check authentication
|
594
596
|
if not auth_result or not auth_result.is_valid:
|
595
597
|
return {
|
596
598
|
"success": False,
|
597
599
|
"status_code": 401,
|
598
600
|
"error": "Authentication failed",
|
599
|
-
"auth_result": auth_result.model_dump() if auth_result else None
|
601
|
+
"auth_result": auth_result.model_dump() if auth_result else None,
|
600
602
|
}
|
601
|
-
|
603
|
+
|
602
604
|
# Check authorization
|
603
605
|
required_permissions = self._get_required_permissions(action, resource)
|
604
606
|
authz_result = self.security_manager.check_permissions(
|
605
|
-
auth_result.roles,
|
606
|
-
required_permissions
|
607
|
+
auth_result.roles, required_permissions
|
607
608
|
)
|
608
|
-
|
609
|
+
|
609
610
|
if not authz_result.is_valid:
|
610
611
|
return {
|
611
612
|
"success": False,
|
612
613
|
"status_code": 403,
|
613
614
|
"error": "Authorization failed",
|
614
615
|
"auth_result": auth_result.model_dump(),
|
615
|
-
"authz_result": authz_result.model_dump()
|
616
|
+
"authz_result": authz_result.model_dump(),
|
616
617
|
}
|
617
|
-
|
618
|
+
|
618
619
|
# Process the request
|
619
620
|
result = {
|
620
621
|
"success": True,
|
@@ -623,113 +624,113 @@ Z2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
|
623
624
|
"authz_result": authz_result.model_dump(),
|
624
625
|
"data": data if action == "write" else None,
|
625
626
|
"resource": resource,
|
626
|
-
"action": action
|
627
|
+
"action": action,
|
627
628
|
}
|
628
|
-
|
629
|
+
|
629
630
|
# Log the successful request
|
630
631
|
self.logger.info(f"Request processed successfully: {action} {resource}")
|
631
|
-
|
632
|
+
|
632
633
|
return result
|
633
|
-
|
634
|
+
|
634
635
|
except Exception as e:
|
635
636
|
self.logger.error(f"Error processing request: {str(e)}")
|
636
637
|
return {
|
637
638
|
"success": False,
|
638
639
|
"status_code": 500,
|
639
|
-
"error": f"Internal server error: {str(e)}"
|
640
|
+
"error": f"Internal server error: {str(e)}",
|
640
641
|
}
|
641
|
-
|
642
|
+
|
642
643
|
def _get_required_permissions(self, action: str, resource: str) -> List[str]:
|
643
644
|
"""Get required permissions for action and resource."""
|
644
645
|
if action == "read":
|
645
|
-
return ["read
|
646
|
+
return ["read"]
|
646
647
|
elif action == "write":
|
647
|
-
return ["write
|
648
|
+
return ["write"]
|
648
649
|
elif action == "delete":
|
649
|
-
return ["delete
|
650
|
-
elif "admin"
|
650
|
+
return ["delete"]
|
651
|
+
elif action == "admin":
|
651
652
|
return ["admin"]
|
652
653
|
else:
|
653
|
-
return ["read
|
654
|
+
return ["read"]
|
654
655
|
|
655
656
|
|
656
657
|
class StandaloneExampleTest:
|
657
658
|
"""Test class for standalone example."""
|
658
|
-
|
659
|
+
|
659
660
|
def test_authentication(self):
|
660
661
|
"""Test authentication capabilities."""
|
661
662
|
example = StandaloneSecurityExample()
|
662
663
|
results = example.demonstrate_authentication()
|
663
|
-
|
664
|
+
|
664
665
|
# Verify API key authentication works
|
665
666
|
assert results["api_key_auth"]["success"] == True
|
666
667
|
assert results["api_key_auth"]["username"] == "admin"
|
667
668
|
assert "admin" in results["api_key_auth"]["roles"]
|
668
|
-
|
669
|
+
|
669
670
|
# Verify JWT authentication works
|
670
671
|
assert results["jwt_auth"]["success"] == True
|
671
672
|
assert results["jwt_auth"]["username"] == "test_user"
|
672
|
-
|
673
|
+
|
673
674
|
# Verify failed authentication is handled
|
674
675
|
assert results["failed_auth"]["success"] == False
|
675
|
-
|
676
|
+
|
676
677
|
print("✅ Authentication tests passed")
|
677
|
-
|
678
|
+
|
678
679
|
def test_authorization(self):
|
679
680
|
"""Test authorization capabilities."""
|
680
681
|
example = StandaloneSecurityExample()
|
681
682
|
results = example.demonstrate_authorization()
|
682
|
-
|
683
|
+
|
683
684
|
# Verify admin permissions work
|
684
685
|
assert results["admin_permissions"]["success"] == True
|
685
|
-
|
686
|
+
|
686
687
|
# Verify user permissions work
|
687
688
|
assert results["user_permissions"]["success"] == True
|
688
|
-
|
689
|
+
|
689
690
|
# Verify readonly permissions work
|
690
691
|
assert results["readonly_permissions"]["success"] == True
|
691
|
-
|
692
|
+
|
692
693
|
print("✅ Authorization tests passed")
|
693
|
-
|
694
|
+
|
694
695
|
def test_rate_limiting(self):
|
695
696
|
"""Test rate limiting capabilities."""
|
696
697
|
example = StandaloneSecurityExample()
|
697
698
|
results = example.demonstrate_rate_limiting()
|
698
|
-
|
699
|
+
|
699
700
|
# Verify rate limiting checks work
|
700
701
|
assert len(results["rate_limit_checks"]) > 0
|
701
702
|
assert results["rate_limit_checks"][0]["allowed"] == True
|
702
|
-
|
703
|
+
|
703
704
|
print("✅ Rate limiting tests passed")
|
704
|
-
|
705
|
+
|
705
706
|
def test_security_validation(self):
|
706
707
|
"""Test security validation capabilities."""
|
707
708
|
example = StandaloneSecurityExample()
|
708
709
|
results = example.demonstrate_security_validation()
|
709
|
-
|
710
|
+
|
710
711
|
# Verify request validation works
|
711
712
|
assert results["request_validation"]["success"] == True
|
712
|
-
|
713
|
+
|
713
714
|
# Verify configuration validation works
|
714
715
|
assert results["configuration_validation"]["success"] == True
|
715
|
-
|
716
|
+
|
716
717
|
print("✅ Security validation tests passed")
|
717
|
-
|
718
|
+
|
718
719
|
def test_security_monitoring(self):
|
719
720
|
"""Test security monitoring capabilities."""
|
720
721
|
example = StandaloneSecurityExample()
|
721
722
|
results = example.demonstrate_security_monitoring()
|
722
|
-
|
723
|
+
|
723
724
|
# Verify security status works
|
724
725
|
assert "status" in results["security_status"]
|
725
726
|
assert "message" in results["security_status"]
|
726
|
-
|
727
|
+
|
727
728
|
# Verify security metrics work
|
728
729
|
assert "authentication_attempts" in results["security_metrics"]
|
729
|
-
|
730
|
+
|
730
731
|
# Verify security audit works
|
731
732
|
assert "authentication" in results["security_audit"]
|
732
|
-
|
733
|
+
|
733
734
|
print("✅ Security monitoring tests passed")
|
734
735
|
|
735
736
|
|
@@ -737,43 +738,67 @@ def main():
|
|
737
738
|
"""Main function to run the standalone example."""
|
738
739
|
print("\n🚀 MCP Security Framework - Standalone Example")
|
739
740
|
print("=" * 60)
|
740
|
-
|
741
|
+
|
741
742
|
# Create example instance
|
742
743
|
example = StandaloneSecurityExample()
|
743
|
-
|
744
|
+
|
744
745
|
# Run comprehensive demonstration
|
745
746
|
results = example.run_comprehensive_demo()
|
746
|
-
|
747
|
+
|
747
748
|
# Print results
|
748
749
|
print("\n📊 COMPREHENSIVE DEMONSTRATION RESULTS")
|
749
750
|
print("=" * 60)
|
750
751
|
print(f"Framework: {results['framework']}")
|
751
752
|
print(f"Version: {results['version']}")
|
752
753
|
print(f"Timestamp: {results['timestamp']}")
|
753
|
-
|
754
|
+
|
754
755
|
print("\n🔐 AUTHENTICATION RESULTS:")
|
755
|
-
print(
|
756
|
-
|
757
|
-
|
758
|
-
|
756
|
+
print(
|
757
|
+
f" API Key: {'✅' if results['authentication']['api_key_auth']['success'] else '❌'}"
|
758
|
+
)
|
759
|
+
print(
|
760
|
+
f" JWT: {'✅' if results['authentication']['jwt_auth']['success'] else '❌'}"
|
761
|
+
)
|
762
|
+
print(
|
763
|
+
f" Certificate: {'✅' if results['authentication']['certificate_auth']['success'] else '❌'}"
|
764
|
+
)
|
765
|
+
|
759
766
|
print("\n🔑 AUTHORIZATION RESULTS:")
|
760
|
-
print(
|
761
|
-
|
762
|
-
|
763
|
-
|
767
|
+
print(
|
768
|
+
f" Admin Permissions: {'✅' if results['authorization']['admin_permissions']['success'] else '❌'}"
|
769
|
+
)
|
770
|
+
print(
|
771
|
+
f" User Permissions: {'✅' if results['authorization']['user_permissions']['success'] else '❌'}"
|
772
|
+
)
|
773
|
+
print(
|
774
|
+
f" Readonly Permissions: {'✅' if results['authorization']['readonly_permissions']['success'] else '❌'}"
|
775
|
+
)
|
776
|
+
|
764
777
|
print("\n⚡ RATE LIMITING RESULTS:")
|
765
778
|
print(f" Rate Limit Checks: {len(results['rate_limiting']['rate_limit_checks'])}")
|
766
|
-
print(
|
767
|
-
|
779
|
+
print(
|
780
|
+
f" Rate Limit Exceeded: {'❌' if results['rate_limiting']['rate_limit_exceeded'] else '✅'}"
|
781
|
+
)
|
782
|
+
|
768
783
|
print("\n🔒 SECURITY VALIDATION RESULTS:")
|
769
|
-
print(
|
770
|
-
|
771
|
-
|
784
|
+
print(
|
785
|
+
f" Request Validation: {'✅' if results['security_validation']['request_validation']['success'] else '❌'}"
|
786
|
+
)
|
787
|
+
print(
|
788
|
+
f" Configuration Validation: {'✅' if results['security_validation']['configuration_validation']['success'] else '❌'}"
|
789
|
+
)
|
790
|
+
|
772
791
|
print("\n📊 SECURITY MONITORING RESULTS:")
|
773
|
-
print(
|
774
|
-
|
775
|
-
|
776
|
-
|
792
|
+
print(
|
793
|
+
f" Security Status: {'✅' if 'ssl_enabled' in results['security_monitoring']['security_status'] else '❌'}"
|
794
|
+
)
|
795
|
+
print(
|
796
|
+
f" Security Metrics: {'✅' if 'authentication_attempts' in results['security_monitoring']['security_metrics'] else '❌'}"
|
797
|
+
)
|
798
|
+
print(
|
799
|
+
f" Security Audit: {'✅' if 'authentication' in results['security_monitoring']['security_audit'] else '❌'}"
|
800
|
+
)
|
801
|
+
|
777
802
|
print("\n🎉 ALL FRAMEWORK CAPABILITIES DEMONSTRATED SUCCESSFULLY!")
|
778
803
|
print("=" * 60)
|
779
804
|
|
@@ -787,6 +812,6 @@ if __name__ == "__main__":
|
|
787
812
|
test.test_rate_limiting()
|
788
813
|
test.test_security_validation()
|
789
814
|
test.test_security_monitoring()
|
790
|
-
|
815
|
+
|
791
816
|
print("\nExample Usage:")
|
792
817
|
main()
|