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,576 @@
|
|
1
|
+
"""
|
2
|
+
Standalone Example Implementation
|
3
|
+
|
4
|
+
This module provides a complete example of how to implement the MCP Security Framework
|
5
|
+
in a standalone application, including all abstract method implementations.
|
6
|
+
|
7
|
+
The example demonstrates:
|
8
|
+
- Standalone application with security framework
|
9
|
+
- Real-world authentication and authorization
|
10
|
+
- Rate limiting implementation
|
11
|
+
- Certificate-based authentication
|
12
|
+
- Production-ready security features
|
13
|
+
- Comprehensive error handling
|
14
|
+
|
15
|
+
Author: MCP Security Team
|
16
|
+
Version: 1.0.0
|
17
|
+
License: MIT
|
18
|
+
"""
|
19
|
+
|
20
|
+
import os
|
21
|
+
import json
|
22
|
+
import logging
|
23
|
+
import asyncio
|
24
|
+
from typing import Dict, List, Any, Optional
|
25
|
+
from datetime import datetime, timedelta
|
26
|
+
|
27
|
+
from mcp_security_framework.core.security_manager import SecurityManager
|
28
|
+
from mcp_security_framework.core.auth_manager import AuthManager
|
29
|
+
from mcp_security_framework.core.ssl_manager import SSLManager
|
30
|
+
from mcp_security_framework.core.permission_manager import PermissionManager
|
31
|
+
from mcp_security_framework.core.rate_limiter import RateLimiter
|
32
|
+
from mcp_security_framework.schemas.config import SecurityConfig, AuthConfig, SSLConfig
|
33
|
+
from mcp_security_framework.schemas.models import AuthResult, AuthStatus, AuthMethod
|
34
|
+
from mcp_security_framework.constants import (
|
35
|
+
DEFAULT_CLIENT_IP, DEFAULT_SECURITY_HEADERS, AUTH_METHODS,
|
36
|
+
ErrorCodes, HTTP_UNAUTHORIZED, HTTP_FORBIDDEN, HTTP_TOO_MANY_REQUESTS
|
37
|
+
)
|
38
|
+
|
39
|
+
|
40
|
+
class StandaloneExample:
|
41
|
+
"""
|
42
|
+
Complete Standalone Example with Security Framework Implementation
|
43
|
+
|
44
|
+
This class demonstrates a production-ready standalone application
|
45
|
+
with comprehensive security features including:
|
46
|
+
- Multi-method authentication (API Key, JWT, Certificate)
|
47
|
+
- Role-based access control
|
48
|
+
- Rate limiting with Redis backend
|
49
|
+
- SSL/TLS configuration
|
50
|
+
- Comprehensive logging and monitoring
|
51
|
+
- Command-line interface
|
52
|
+
"""
|
53
|
+
|
54
|
+
def __init__(self, config_path: Optional[str] = None):
|
55
|
+
"""
|
56
|
+
Initialize standalone example with security configuration.
|
57
|
+
|
58
|
+
Args:
|
59
|
+
config_path: Path to security configuration file
|
60
|
+
"""
|
61
|
+
self.config = self._load_config(config_path)
|
62
|
+
self.security_manager = SecurityManager(self.config)
|
63
|
+
self.logger = logging.getLogger(__name__)
|
64
|
+
self._setup_logging()
|
65
|
+
|
66
|
+
def _load_config(self, config_path: Optional[str]) -> SecurityConfig:
|
67
|
+
"""
|
68
|
+
Load security configuration from file or create default.
|
69
|
+
|
70
|
+
Args:
|
71
|
+
config_path: Path to configuration file
|
72
|
+
|
73
|
+
Returns:
|
74
|
+
SecurityConfig: Loaded configuration
|
75
|
+
"""
|
76
|
+
if config_path and os.path.exists(config_path):
|
77
|
+
with open(config_path, 'r') as f:
|
78
|
+
config_data = json.load(f)
|
79
|
+
return SecurityConfig(**config_data)
|
80
|
+
|
81
|
+
# Create production-ready default configuration
|
82
|
+
return SecurityConfig(
|
83
|
+
auth=AuthConfig(
|
84
|
+
enabled=True,
|
85
|
+
methods=[AUTH_METHODS["API_KEY"], AUTH_METHODS["JWT"], AUTH_METHODS["CERTIFICATE"]],
|
86
|
+
api_keys={
|
87
|
+
"admin_key_123": {"username": "admin", "roles": ["admin", "user"]},
|
88
|
+
"user_key_456": {"username": "user", "roles": ["user"]},
|
89
|
+
"readonly_key_789": {"username": "readonly", "roles": ["readonly"]}
|
90
|
+
},
|
91
|
+
jwt_secret="your-super-secret-jwt-key-change-in-production",
|
92
|
+
jwt_algorithm="HS256",
|
93
|
+
jwt_expiry_hours=24,
|
94
|
+
public_paths=["/health", "/metrics"],
|
95
|
+
security_headers=DEFAULT_SECURITY_HEADERS
|
96
|
+
),
|
97
|
+
ssl=SSLConfig(
|
98
|
+
enabled=True,
|
99
|
+
cert_file="certs/server.crt",
|
100
|
+
key_file="certs/server.key",
|
101
|
+
ca_cert_file="certs/ca.crt",
|
102
|
+
verify_mode="CERT_REQUIRED",
|
103
|
+
min_version="TLSv1.2"
|
104
|
+
),
|
105
|
+
rate_limit={
|
106
|
+
"enabled": True,
|
107
|
+
"default_requests_per_minute": 60,
|
108
|
+
"default_requests_per_hour": 1000,
|
109
|
+
"burst_limit": 2,
|
110
|
+
"window_size_seconds": 60,
|
111
|
+
"storage_backend": "redis",
|
112
|
+
"redis_config": {
|
113
|
+
"host": "localhost",
|
114
|
+
"port": 6379,
|
115
|
+
"db": 0,
|
116
|
+
"password": None
|
117
|
+
},
|
118
|
+
"exempt_paths": ["/health", "/metrics"],
|
119
|
+
"exempt_roles": ["admin"]
|
120
|
+
},
|
121
|
+
permissions={
|
122
|
+
"enabled": True,
|
123
|
+
"roles_file": "config/roles.json",
|
124
|
+
"default_role": "user",
|
125
|
+
"hierarchy_enabled": True
|
126
|
+
},
|
127
|
+
logging={
|
128
|
+
"enabled": True,
|
129
|
+
"level": "INFO",
|
130
|
+
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
131
|
+
"file_path": "logs/security.log",
|
132
|
+
"max_file_size": 10,
|
133
|
+
"backup_count": 5,
|
134
|
+
"console_output": True,
|
135
|
+
"json_format": False
|
136
|
+
}
|
137
|
+
)
|
138
|
+
|
139
|
+
def _setup_logging(self):
|
140
|
+
"""Setup logging configuration."""
|
141
|
+
if self.config.logging.enabled:
|
142
|
+
logging.basicConfig(
|
143
|
+
level=getattr(logging, self.config.logging.level),
|
144
|
+
format=self.config.logging.format,
|
145
|
+
handlers=[
|
146
|
+
logging.FileHandler(self.config.logging.file_path) if self.config.logging.file_path else logging.NullHandler(),
|
147
|
+
logging.StreamHandler() if self.config.logging.console_output else logging.NullHandler()
|
148
|
+
]
|
149
|
+
)
|
150
|
+
|
151
|
+
def authenticate_user(self, credentials: Dict[str, Any]) -> AuthResult:
|
152
|
+
"""
|
153
|
+
Authenticate user with provided credentials.
|
154
|
+
|
155
|
+
Args:
|
156
|
+
credentials: User credentials (api_key, jwt_token, or certificate)
|
157
|
+
|
158
|
+
Returns:
|
159
|
+
AuthResult: Authentication result
|
160
|
+
"""
|
161
|
+
try:
|
162
|
+
if "api_key" in credentials:
|
163
|
+
return self.security_manager.auth_manager.authenticate_api_key(credentials["api_key"])
|
164
|
+
elif "jwt_token" in credentials:
|
165
|
+
return self.security_manager.auth_manager.authenticate_jwt_token(credentials["jwt_token"])
|
166
|
+
elif "certificate" in credentials:
|
167
|
+
return self.security_manager.auth_manager.authenticate_certificate(credentials["certificate"])
|
168
|
+
else:
|
169
|
+
return AuthResult(
|
170
|
+
is_valid=False,
|
171
|
+
status=AuthStatus.FAILED,
|
172
|
+
username=None,
|
173
|
+
roles=[],
|
174
|
+
auth_method=None,
|
175
|
+
error_code=ErrorCodes.AUTHENTICATION_ERROR,
|
176
|
+
error_message="No valid credentials provided"
|
177
|
+
)
|
178
|
+
except Exception as e:
|
179
|
+
self.logger.error(f"Authentication failed: {str(e)}")
|
180
|
+
return AuthResult(
|
181
|
+
is_valid=False,
|
182
|
+
status=AuthStatus.FAILED,
|
183
|
+
username=None,
|
184
|
+
roles=[],
|
185
|
+
auth_method=None,
|
186
|
+
error_code=ErrorCodes.AUTHENTICATION_ERROR,
|
187
|
+
error_message=str(e)
|
188
|
+
)
|
189
|
+
|
190
|
+
def check_permissions(self, user_roles: List[str], required_permissions: List[str]) -> bool:
|
191
|
+
"""
|
192
|
+
Check if user has required permissions.
|
193
|
+
|
194
|
+
Args:
|
195
|
+
user_roles: User roles
|
196
|
+
required_permissions: Required permissions
|
197
|
+
|
198
|
+
Returns:
|
199
|
+
bool: True if user has required permissions
|
200
|
+
"""
|
201
|
+
try:
|
202
|
+
return self.security_manager.permission_manager.validate_access(
|
203
|
+
user_roles, required_permissions
|
204
|
+
)
|
205
|
+
except Exception as e:
|
206
|
+
self.logger.error(f"Permission check failed: {str(e)}")
|
207
|
+
return False
|
208
|
+
|
209
|
+
def check_rate_limit(self, identifier: str) -> bool:
|
210
|
+
"""
|
211
|
+
Check if request is within rate limits.
|
212
|
+
|
213
|
+
Args:
|
214
|
+
identifier: Request identifier (IP, user ID, etc.)
|
215
|
+
|
216
|
+
Returns:
|
217
|
+
bool: True if request is within rate limits
|
218
|
+
"""
|
219
|
+
try:
|
220
|
+
return self.security_manager.rate_limiter.check_rate_limit(identifier)
|
221
|
+
except Exception as e:
|
222
|
+
self.logger.error(f"Rate limit check failed: {str(e)}")
|
223
|
+
return True # Allow request if rate limiting fails
|
224
|
+
|
225
|
+
def process_request(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
|
226
|
+
"""
|
227
|
+
Process a secure request with full security validation.
|
228
|
+
|
229
|
+
Args:
|
230
|
+
request_data: Request data including credentials and action
|
231
|
+
|
232
|
+
Returns:
|
233
|
+
Dict[str, Any]: Response data
|
234
|
+
"""
|
235
|
+
try:
|
236
|
+
# Extract request components
|
237
|
+
credentials = request_data.get("credentials", {})
|
238
|
+
action = request_data.get("action", "")
|
239
|
+
resource = request_data.get("resource", "")
|
240
|
+
identifier = request_data.get("identifier", DEFAULT_CLIENT_IP)
|
241
|
+
|
242
|
+
# Step 1: Rate limiting check
|
243
|
+
if not self.check_rate_limit(identifier):
|
244
|
+
return {
|
245
|
+
"success": False,
|
246
|
+
"error": "Rate limit exceeded",
|
247
|
+
"error_code": ErrorCodes.RATE_LIMIT_EXCEEDED_ERROR,
|
248
|
+
"timestamp": datetime.utcnow().isoformat()
|
249
|
+
}
|
250
|
+
|
251
|
+
# Step 2: Authentication
|
252
|
+
auth_result = self.authenticate_user(credentials)
|
253
|
+
if not auth_result.is_valid:
|
254
|
+
return {
|
255
|
+
"success": False,
|
256
|
+
"error": "Authentication failed",
|
257
|
+
"error_code": auth_result.error_code,
|
258
|
+
"error_message": auth_result.error_message,
|
259
|
+
"timestamp": datetime.utcnow().isoformat()
|
260
|
+
}
|
261
|
+
|
262
|
+
# Step 3: Authorization
|
263
|
+
required_permissions = self._get_required_permissions(action, resource)
|
264
|
+
if not self.check_permissions(auth_result.roles, required_permissions):
|
265
|
+
return {
|
266
|
+
"success": False,
|
267
|
+
"error": "Insufficient permissions",
|
268
|
+
"error_code": ErrorCodes.PERMISSION_DENIED_ERROR,
|
269
|
+
"timestamp": datetime.utcnow().isoformat()
|
270
|
+
}
|
271
|
+
|
272
|
+
# Step 4: Process the action
|
273
|
+
result = self._execute_action(action, resource, request_data.get("data", {}))
|
274
|
+
|
275
|
+
# Step 5: Log security event
|
276
|
+
self._log_security_event("request_processed", {
|
277
|
+
"username": auth_result.username,
|
278
|
+
"action": action,
|
279
|
+
"resource": resource,
|
280
|
+
"success": True,
|
281
|
+
"timestamp": datetime.utcnow().isoformat()
|
282
|
+
})
|
283
|
+
|
284
|
+
return {
|
285
|
+
"success": True,
|
286
|
+
"data": result,
|
287
|
+
"user": {
|
288
|
+
"username": auth_result.username,
|
289
|
+
"roles": auth_result.roles,
|
290
|
+
"auth_method": auth_result.auth_method
|
291
|
+
},
|
292
|
+
"timestamp": datetime.utcnow().isoformat()
|
293
|
+
}
|
294
|
+
|
295
|
+
except Exception as e:
|
296
|
+
self.logger.error(f"Request processing failed: {str(e)}")
|
297
|
+
return {
|
298
|
+
"success": False,
|
299
|
+
"error": "Internal server error",
|
300
|
+
"error_code": ErrorCodes.GENERAL_ERROR,
|
301
|
+
"timestamp": datetime.utcnow().isoformat()
|
302
|
+
}
|
303
|
+
|
304
|
+
def _get_required_permissions(self, action: str, resource: str) -> List[str]:
|
305
|
+
"""
|
306
|
+
Get required permissions for action and resource.
|
307
|
+
|
308
|
+
Args:
|
309
|
+
action: Action to perform
|
310
|
+
resource: Resource to access
|
311
|
+
|
312
|
+
Returns:
|
313
|
+
List[str]: Required permissions
|
314
|
+
"""
|
315
|
+
# Define permission mappings
|
316
|
+
permission_mappings = {
|
317
|
+
"read": ["read"],
|
318
|
+
"write": ["read", "write"],
|
319
|
+
"delete": ["read", "write", "delete"],
|
320
|
+
"admin": ["admin"],
|
321
|
+
"create": ["read", "write"],
|
322
|
+
"update": ["read", "write"]
|
323
|
+
}
|
324
|
+
|
325
|
+
return permission_mappings.get(action, ["read"])
|
326
|
+
|
327
|
+
def _execute_action(self, action: str, resource: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
328
|
+
"""
|
329
|
+
Execute the requested action.
|
330
|
+
|
331
|
+
Args:
|
332
|
+
action: Action to perform
|
333
|
+
resource: Resource to access
|
334
|
+
data: Action data
|
335
|
+
|
336
|
+
Returns:
|
337
|
+
Dict[str, Any]: Action result
|
338
|
+
"""
|
339
|
+
# Simulate different actions
|
340
|
+
if action == "read":
|
341
|
+
return {"resource": resource, "data": {"example": "data"}}
|
342
|
+
elif action == "write":
|
343
|
+
return {"resource": resource, "data": data, "status": "written"}
|
344
|
+
elif action == "delete":
|
345
|
+
return {"resource": resource, "status": "deleted"}
|
346
|
+
elif action == "create":
|
347
|
+
return {"resource": resource, "data": data, "status": "created"}
|
348
|
+
elif action == "update":
|
349
|
+
return {"resource": resource, "data": data, "status": "updated"}
|
350
|
+
else:
|
351
|
+
return {"error": f"Unknown action: {action}"}
|
352
|
+
|
353
|
+
def _log_security_event(self, event_type: str, details: Dict[str, Any]):
|
354
|
+
"""
|
355
|
+
Log security event.
|
356
|
+
|
357
|
+
Args:
|
358
|
+
event_type: Type of security event
|
359
|
+
details: Event details
|
360
|
+
"""
|
361
|
+
try:
|
362
|
+
self.logger.info(
|
363
|
+
f"Security event: {event_type}",
|
364
|
+
extra={
|
365
|
+
"event_type": event_type,
|
366
|
+
"timestamp": details.get("timestamp"),
|
367
|
+
"username": details.get("username"),
|
368
|
+
"action": details.get("action"),
|
369
|
+
"resource": details.get("resource"),
|
370
|
+
"success": details.get("success"),
|
371
|
+
**details
|
372
|
+
}
|
373
|
+
)
|
374
|
+
except Exception as e:
|
375
|
+
self.logger.error(f"Failed to log security event: {str(e)}")
|
376
|
+
|
377
|
+
def generate_api_key(self, username: str, roles: List[str]) -> str:
|
378
|
+
"""
|
379
|
+
Generate API key for user.
|
380
|
+
|
381
|
+
Args:
|
382
|
+
username: Username
|
383
|
+
roles: User roles
|
384
|
+
|
385
|
+
Returns:
|
386
|
+
str: Generated API key
|
387
|
+
"""
|
388
|
+
try:
|
389
|
+
api_key = self.security_manager.auth_manager.generate_api_key()
|
390
|
+
# Store the API key (in production, this would be in a database)
|
391
|
+
self.config.auth.api_keys[api_key] = {
|
392
|
+
"username": username,
|
393
|
+
"roles": roles
|
394
|
+
}
|
395
|
+
return api_key
|
396
|
+
except Exception as e:
|
397
|
+
self.logger.error(f"Failed to generate API key: {str(e)}")
|
398
|
+
raise
|
399
|
+
|
400
|
+
def create_jwt_token(self, username: str, roles: List[str], expiry_hours: int = 24) -> str:
|
401
|
+
"""
|
402
|
+
Create JWT token for user.
|
403
|
+
|
404
|
+
Args:
|
405
|
+
username: Username
|
406
|
+
roles: User roles
|
407
|
+
expiry_hours: Token expiry in hours
|
408
|
+
|
409
|
+
Returns:
|
410
|
+
str: Generated JWT token
|
411
|
+
"""
|
412
|
+
try:
|
413
|
+
user_data = {
|
414
|
+
"username": username,
|
415
|
+
"roles": roles,
|
416
|
+
"exp": datetime.utcnow() + timedelta(hours=expiry_hours)
|
417
|
+
}
|
418
|
+
return self.security_manager.auth_manager.create_jwt_token(user_data)
|
419
|
+
except Exception as e:
|
420
|
+
self.logger.error(f"Failed to create JWT token: {str(e)}")
|
421
|
+
raise
|
422
|
+
|
423
|
+
def validate_certificate(self, certificate_path: str) -> bool:
|
424
|
+
"""
|
425
|
+
Validate certificate.
|
426
|
+
|
427
|
+
Args:
|
428
|
+
certificate_path: Path to certificate file
|
429
|
+
|
430
|
+
Returns:
|
431
|
+
bool: True if certificate is valid
|
432
|
+
"""
|
433
|
+
try:
|
434
|
+
return self.security_manager.ssl_manager.validate_certificate(certificate_path)
|
435
|
+
except Exception as e:
|
436
|
+
self.logger.error(f"Certificate validation failed: {str(e)}")
|
437
|
+
return False
|
438
|
+
|
439
|
+
def get_security_status(self) -> Dict[str, Any]:
|
440
|
+
"""
|
441
|
+
Get security framework status.
|
442
|
+
|
443
|
+
Returns:
|
444
|
+
Dict[str, Any]: Security status information
|
445
|
+
"""
|
446
|
+
return {
|
447
|
+
"ssl_enabled": self.config.ssl.enabled,
|
448
|
+
"auth_enabled": self.config.auth.enabled,
|
449
|
+
"rate_limiting_enabled": self.config.rate_limit.enabled,
|
450
|
+
"permissions_enabled": self.config.permissions.enabled,
|
451
|
+
"logging_enabled": self.config.logging.enabled,
|
452
|
+
"auth_methods": self.config.auth.methods,
|
453
|
+
"timestamp": datetime.utcnow().isoformat()
|
454
|
+
}
|
455
|
+
|
456
|
+
|
457
|
+
# Example usage and testing
|
458
|
+
class StandaloneExampleTest:
|
459
|
+
"""Test class for standalone example functionality."""
|
460
|
+
|
461
|
+
@staticmethod
|
462
|
+
def test_authentication():
|
463
|
+
"""Test authentication functionality."""
|
464
|
+
example = StandaloneExample()
|
465
|
+
|
466
|
+
# Test API key authentication
|
467
|
+
credentials = {"api_key": "admin_key_123"}
|
468
|
+
auth_result = example.authenticate_user(credentials)
|
469
|
+
assert auth_result.is_valid
|
470
|
+
assert auth_result.username == "admin"
|
471
|
+
assert "admin" in auth_result.roles
|
472
|
+
|
473
|
+
print("✅ API Key authentication test passed")
|
474
|
+
|
475
|
+
@staticmethod
|
476
|
+
def test_permissions():
|
477
|
+
"""Test permission checking."""
|
478
|
+
example = StandaloneExample()
|
479
|
+
|
480
|
+
# Test admin permissions
|
481
|
+
admin_roles = ["admin"]
|
482
|
+
user_roles = ["user"]
|
483
|
+
readonly_roles = ["readonly"]
|
484
|
+
|
485
|
+
# Admin should have all permissions
|
486
|
+
assert example.check_permissions(admin_roles, ["read", "write", "delete"])
|
487
|
+
|
488
|
+
# User should have read and write permissions
|
489
|
+
assert example.check_permissions(user_roles, ["read", "write"])
|
490
|
+
|
491
|
+
# Readonly should only have read permission
|
492
|
+
assert example.check_permissions(readonly_roles, ["read"])
|
493
|
+
assert not example.check_permissions(readonly_roles, ["write"])
|
494
|
+
|
495
|
+
print("✅ Permission checking test passed")
|
496
|
+
|
497
|
+
@staticmethod
|
498
|
+
def test_rate_limiting():
|
499
|
+
"""Test rate limiting functionality."""
|
500
|
+
example = StandaloneExample()
|
501
|
+
|
502
|
+
# Test rate limiting
|
503
|
+
identifier = "test_user"
|
504
|
+
for i in range(5):
|
505
|
+
is_allowed = example.check_rate_limit(identifier)
|
506
|
+
print(f"Request {i+1}: {'Allowed' if is_allowed else 'Blocked'}")
|
507
|
+
|
508
|
+
print("✅ Rate limiting test completed")
|
509
|
+
|
510
|
+
@staticmethod
|
511
|
+
def test_request_processing():
|
512
|
+
"""Test complete request processing."""
|
513
|
+
example = StandaloneExample()
|
514
|
+
|
515
|
+
# Test successful request
|
516
|
+
request_data = {
|
517
|
+
"credentials": {"api_key": "admin_key_123"},
|
518
|
+
"action": "read",
|
519
|
+
"resource": "data",
|
520
|
+
"identifier": "test_user"
|
521
|
+
}
|
522
|
+
|
523
|
+
result = example.process_request(request_data)
|
524
|
+
assert result["success"]
|
525
|
+
assert "data" in result
|
526
|
+
|
527
|
+
print("✅ Request processing test passed")
|
528
|
+
|
529
|
+
@staticmethod
|
530
|
+
def test_api_key_generation():
|
531
|
+
"""Test API key generation."""
|
532
|
+
example = StandaloneExample()
|
533
|
+
|
534
|
+
api_key = example.generate_api_key("test_user", ["user"])
|
535
|
+
assert len(api_key) > 0
|
536
|
+
|
537
|
+
# Test the generated key
|
538
|
+
credentials = {"api_key": api_key}
|
539
|
+
auth_result = example.authenticate_user(credentials)
|
540
|
+
assert auth_result.is_valid
|
541
|
+
assert auth_result.username == "test_user"
|
542
|
+
|
543
|
+
print("✅ API key generation test passed")
|
544
|
+
|
545
|
+
|
546
|
+
if __name__ == "__main__":
|
547
|
+
# Run tests
|
548
|
+
print("Running Standalone Example Tests...")
|
549
|
+
StandaloneExampleTest.test_authentication()
|
550
|
+
StandaloneExampleTest.test_permissions()
|
551
|
+
StandaloneExampleTest.test_rate_limiting()
|
552
|
+
StandaloneExampleTest.test_request_processing()
|
553
|
+
StandaloneExampleTest.test_api_key_generation()
|
554
|
+
|
555
|
+
# Example usage
|
556
|
+
print("\nExample Usage:")
|
557
|
+
example = StandaloneExample()
|
558
|
+
|
559
|
+
# Generate API key for new user
|
560
|
+
api_key = example.generate_api_key("new_user", ["user"])
|
561
|
+
print(f"Generated API key: {api_key}")
|
562
|
+
|
563
|
+
# Process a request
|
564
|
+
request_data = {
|
565
|
+
"credentials": {"api_key": api_key},
|
566
|
+
"action": "read",
|
567
|
+
"resource": "user_data",
|
568
|
+
"identifier": "192.168.1.100"
|
569
|
+
}
|
570
|
+
|
571
|
+
result = example.process_request(request_data)
|
572
|
+
print(f"Request result: {result}")
|
573
|
+
|
574
|
+
# Get security status
|
575
|
+
status = example.get_security_status()
|
576
|
+
print(f"Security status: {status}")
|