mcp-security-framework 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. mcp_security_framework/__init__.py +96 -0
  2. mcp_security_framework/cli/__init__.py +18 -0
  3. mcp_security_framework/cli/cert_cli.py +511 -0
  4. mcp_security_framework/cli/security_cli.py +791 -0
  5. mcp_security_framework/constants.py +209 -0
  6. mcp_security_framework/core/__init__.py +61 -0
  7. mcp_security_framework/core/auth_manager.py +1011 -0
  8. mcp_security_framework/core/cert_manager.py +1663 -0
  9. mcp_security_framework/core/permission_manager.py +735 -0
  10. mcp_security_framework/core/rate_limiter.py +602 -0
  11. mcp_security_framework/core/security_manager.py +943 -0
  12. mcp_security_framework/core/ssl_manager.py +735 -0
  13. mcp_security_framework/examples/__init__.py +75 -0
  14. mcp_security_framework/examples/django_example.py +615 -0
  15. mcp_security_framework/examples/fastapi_example.py +472 -0
  16. mcp_security_framework/examples/flask_example.py +506 -0
  17. mcp_security_framework/examples/gateway_example.py +803 -0
  18. mcp_security_framework/examples/microservice_example.py +690 -0
  19. mcp_security_framework/examples/standalone_example.py +576 -0
  20. mcp_security_framework/middleware/__init__.py +250 -0
  21. mcp_security_framework/middleware/auth_middleware.py +292 -0
  22. mcp_security_framework/middleware/fastapi_auth_middleware.py +447 -0
  23. mcp_security_framework/middleware/fastapi_middleware.py +757 -0
  24. mcp_security_framework/middleware/flask_auth_middleware.py +465 -0
  25. mcp_security_framework/middleware/flask_middleware.py +591 -0
  26. mcp_security_framework/middleware/mtls_middleware.py +439 -0
  27. mcp_security_framework/middleware/rate_limit_middleware.py +403 -0
  28. mcp_security_framework/middleware/security_middleware.py +507 -0
  29. mcp_security_framework/schemas/__init__.py +109 -0
  30. mcp_security_framework/schemas/config.py +694 -0
  31. mcp_security_framework/schemas/models.py +709 -0
  32. mcp_security_framework/schemas/responses.py +686 -0
  33. mcp_security_framework/tests/__init__.py +0 -0
  34. mcp_security_framework/utils/__init__.py +121 -0
  35. mcp_security_framework/utils/cert_utils.py +525 -0
  36. mcp_security_framework/utils/crypto_utils.py +475 -0
  37. mcp_security_framework/utils/validation_utils.py +571 -0
  38. mcp_security_framework-0.1.0.dist-info/METADATA +411 -0
  39. mcp_security_framework-0.1.0.dist-info/RECORD +76 -0
  40. mcp_security_framework-0.1.0.dist-info/WHEEL +5 -0
  41. mcp_security_framework-0.1.0.dist-info/entry_points.txt +3 -0
  42. mcp_security_framework-0.1.0.dist-info/top_level.txt +2 -0
  43. tests/__init__.py +0 -0
  44. tests/test_cli/__init__.py +0 -0
  45. tests/test_cli/test_cert_cli.py +379 -0
  46. tests/test_cli/test_security_cli.py +657 -0
  47. tests/test_core/__init__.py +0 -0
  48. tests/test_core/test_auth_manager.py +582 -0
  49. tests/test_core/test_cert_manager.py +795 -0
  50. tests/test_core/test_permission_manager.py +395 -0
  51. tests/test_core/test_rate_limiter.py +626 -0
  52. tests/test_core/test_security_manager.py +841 -0
  53. tests/test_core/test_ssl_manager.py +532 -0
  54. tests/test_examples/__init__.py +8 -0
  55. tests/test_examples/test_fastapi_example.py +264 -0
  56. tests/test_examples/test_flask_example.py +238 -0
  57. tests/test_examples/test_standalone_example.py +292 -0
  58. tests/test_integration/__init__.py +0 -0
  59. tests/test_integration/test_auth_flow.py +502 -0
  60. tests/test_integration/test_certificate_flow.py +527 -0
  61. tests/test_integration/test_fastapi_integration.py +341 -0
  62. tests/test_integration/test_flask_integration.py +398 -0
  63. tests/test_integration/test_standalone_integration.py +493 -0
  64. tests/test_middleware/__init__.py +0 -0
  65. tests/test_middleware/test_fastapi_middleware.py +523 -0
  66. tests/test_middleware/test_flask_middleware.py +582 -0
  67. tests/test_middleware/test_security_middleware.py +493 -0
  68. tests/test_schemas/__init__.py +0 -0
  69. tests/test_schemas/test_config.py +811 -0
  70. tests/test_schemas/test_models.py +879 -0
  71. tests/test_schemas/test_responses.py +1054 -0
  72. tests/test_schemas/test_serialization.py +493 -0
  73. tests/test_utils/__init__.py +0 -0
  74. tests/test_utils/test_cert_utils.py +510 -0
  75. tests/test_utils/test_crypto_utils.py +603 -0
  76. tests/test_utils/test_validation_utils.py +477 -0
@@ -0,0 +1,690 @@
1
+ """
2
+ Microservice Example Implementation
3
+
4
+ This module provides a complete example of how to implement the MCP Security Framework
5
+ in a microservice architecture, including all abstract method implementations.
6
+
7
+ The example demonstrates:
8
+ - Microservice with security framework
9
+ - Service-to-service authentication
10
+ - Rate limiting for microservices
11
+ - Certificate-based service 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
+ import aiohttp
25
+ from typing import Dict, List, Any, Optional
26
+ from datetime import datetime, timedelta
27
+
28
+ from mcp_security_framework.core.security_manager import SecurityManager
29
+ from mcp_security_framework.core.auth_manager import AuthManager
30
+ from mcp_security_framework.core.ssl_manager import SSLManager
31
+ from mcp_security_framework.core.permission_manager import PermissionManager
32
+ from mcp_security_framework.core.rate_limiter import RateLimiter
33
+ from mcp_security_framework.schemas.config import SecurityConfig, AuthConfig, SSLConfig
34
+ from mcp_security_framework.schemas.models import AuthResult, AuthStatus, AuthMethod
35
+ from mcp_security_framework.constants import (
36
+ DEFAULT_CLIENT_IP, DEFAULT_SECURITY_HEADERS, AUTH_METHODS,
37
+ ErrorCodes, HTTP_UNAUTHORIZED, HTTP_FORBIDDEN, HTTP_TOO_MANY_REQUESTS
38
+ )
39
+
40
+
41
+ class MicroserviceExample:
42
+ """
43
+ Complete Microservice Example with Security Framework Implementation
44
+
45
+ This class demonstrates a production-ready microservice
46
+ with comprehensive security features including:
47
+ - Service-to-service authentication
48
+ - API gateway integration
49
+ - Rate limiting for microservices
50
+ - Certificate-based service authentication
51
+ - Comprehensive logging and monitoring
52
+ - Health checks and metrics
53
+ """
54
+
55
+ def __init__(self, service_name: str, config_path: Optional[str] = None):
56
+ """
57
+ Initialize microservice example with security configuration.
58
+
59
+ Args:
60
+ service_name: Name of the microservice
61
+ config_path: Path to security configuration file
62
+ """
63
+ self.service_name = service_name
64
+ self.config = self._load_config(config_path)
65
+ self.security_manager = SecurityManager(self.config)
66
+ self.logger = logging.getLogger(__name__)
67
+ self._setup_logging()
68
+ self._setup_service_registry()
69
+
70
+ def _load_config(self, config_path: Optional[str]) -> SecurityConfig:
71
+ """
72
+ Load security configuration from file or create default.
73
+
74
+ Args:
75
+ config_path: Path to configuration file
76
+
77
+ Returns:
78
+ SecurityConfig: Loaded configuration
79
+ """
80
+ if config_path and os.path.exists(config_path):
81
+ with open(config_path, 'r') as f:
82
+ config_data = json.load(f)
83
+ return SecurityConfig(**config_data)
84
+
85
+ # Create production-ready microservice configuration
86
+ return SecurityConfig(
87
+ auth=AuthConfig(
88
+ enabled=True,
89
+ methods=[AUTH_METHODS["API_KEY"], AUTH_METHODS["JWT"], AUTH_METHODS["CERTIFICATE"]],
90
+ api_keys={
91
+ "service_key_123": {"username": "user-service", "roles": ["service", "user"]},
92
+ "service_key_456": {"username": "order-service", "roles": ["service", "order"]},
93
+ "service_key_789": {"username": "payment-service", "roles": ["service", "payment"]}
94
+ },
95
+ jwt_secret="your-super-secret-jwt-key-change-in-production",
96
+ jwt_algorithm="HS256",
97
+ jwt_expiry_hours=24,
98
+ public_paths=["/health", "/metrics", "/ready"],
99
+ security_headers=DEFAULT_SECURITY_HEADERS
100
+ ),
101
+ ssl=SSLConfig(
102
+ enabled=True,
103
+ cert_file=f"certs/{self.service_name}.crt",
104
+ key_file=f"certs/{self.service_name}.key",
105
+ ca_cert_file="certs/ca.crt",
106
+ verify_mode="CERT_REQUIRED",
107
+ min_version="TLSv1.2"
108
+ ),
109
+ rate_limit={
110
+ "enabled": True,
111
+ "default_requests_per_minute": 1000, # Higher for microservices
112
+ "default_requests_per_hour": 10000,
113
+ "burst_limit": 5,
114
+ "window_size_seconds": 60,
115
+ "storage_backend": "redis",
116
+ "redis_config": {
117
+ "host": "redis-cluster",
118
+ "port": 6379,
119
+ "db": 0,
120
+ "password": None
121
+ },
122
+ "exempt_paths": ["/health", "/metrics", "/ready"],
123
+ "exempt_roles": ["service"]
124
+ },
125
+ permissions={
126
+ "enabled": True,
127
+ "roles_file": "config/roles.json",
128
+ "default_role": "service",
129
+ "hierarchy_enabled": True
130
+ },
131
+ logging={
132
+ "enabled": True,
133
+ "level": "INFO",
134
+ "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
135
+ "file_path": f"logs/{self.service_name}.log",
136
+ "max_file_size": 10,
137
+ "backup_count": 5,
138
+ "console_output": True,
139
+ "json_format": True # JSON format for microservices
140
+ }
141
+ )
142
+
143
+ def _setup_logging(self):
144
+ """Setup logging configuration."""
145
+ if self.config.logging.enabled:
146
+ logging.basicConfig(
147
+ level=getattr(logging, self.config.logging.level),
148
+ format=self.config.logging.format,
149
+ handlers=[
150
+ logging.FileHandler(self.config.logging.file_path) if self.config.logging.file_path else logging.NullHandler(),
151
+ logging.StreamHandler() if self.config.logging.console_output else logging.NullHandler()
152
+ ]
153
+ )
154
+
155
+ def _setup_service_registry(self):
156
+ """Setup service registry for microservice discovery."""
157
+ self.service_registry = {
158
+ "user-service": {
159
+ "url": "https://user-service:8080",
160
+ "health_check": "/health",
161
+ "api_key": "service_key_123"
162
+ },
163
+ "order-service": {
164
+ "url": "https://order-service:8081",
165
+ "health_check": "/health",
166
+ "api_key": "service_key_456"
167
+ },
168
+ "payment-service": {
169
+ "url": "https://payment-service:8082",
170
+ "health_check": "/health",
171
+ "api_key": "service_key_789"
172
+ }
173
+ }
174
+
175
+ async def call_service(self, service_name: str, endpoint: str, method: str = "GET", data: Optional[Dict] = None) -> Dict[str, Any]:
176
+ """
177
+ Call another microservice with security.
178
+
179
+ Args:
180
+ service_name: Name of the service to call
181
+ endpoint: Service endpoint
182
+ method: HTTP method
183
+ data: Request data
184
+
185
+ Returns:
186
+ Dict[str, Any]: Service response
187
+ """
188
+ try:
189
+ if service_name not in self.service_registry:
190
+ raise ValueError(f"Service {service_name} not found in registry")
191
+
192
+ service_info = self.service_registry[service_name]
193
+ url = f"{service_info['url']}{endpoint}"
194
+
195
+ # Get service API key
196
+ api_key = service_info['api_key']
197
+
198
+ # Prepare headers with authentication
199
+ headers = {
200
+ "X-API-Key": api_key,
201
+ "X-Service-Name": self.service_name,
202
+ "X-Request-ID": self._generate_request_id(),
203
+ "Content-Type": "application/json"
204
+ }
205
+
206
+ # Make request with SSL context
207
+ ssl_context = None
208
+ if self.config.ssl.enabled:
209
+ ssl_context = self.security_manager.ssl_manager.create_client_context()
210
+
211
+ async with aiohttp.ClientSession() as session:
212
+ if method.upper() == "GET":
213
+ async with session.get(url, headers=headers, ssl=ssl_context) as response:
214
+ return await response.json()
215
+ elif method.upper() == "POST":
216
+ async with session.post(url, headers=headers, json=data, ssl=ssl_context) as response:
217
+ return await response.json()
218
+ elif method.upper() == "PUT":
219
+ async with session.put(url, headers=headers, json=data, ssl=ssl_context) as response:
220
+ return await response.json()
221
+ elif method.upper() == "DELETE":
222
+ async with session.delete(url, headers=headers, ssl=ssl_context) as response:
223
+ return await response.json()
224
+ else:
225
+ raise ValueError(f"Unsupported HTTP method: {method}")
226
+
227
+ except Exception as e:
228
+ self.logger.error(f"Service call failed: {str(e)}")
229
+ return {
230
+ "error": "Service call failed",
231
+ "message": str(e),
232
+ "service": service_name,
233
+ "endpoint": endpoint
234
+ }
235
+
236
+ def _generate_request_id(self) -> str:
237
+ """Generate unique request ID for tracing."""
238
+ import uuid
239
+ return str(uuid.uuid4())
240
+
241
+ async def process_request(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
242
+ """
243
+ Process a microservice request with full security validation.
244
+
245
+ Args:
246
+ request_data: Request data including credentials and action
247
+
248
+ Returns:
249
+ Dict[str, Any]: Response data
250
+ """
251
+ try:
252
+ # Extract request components
253
+ credentials = request_data.get("credentials", {})
254
+ action = request_data.get("action", "")
255
+ resource = request_data.get("resource", "")
256
+ identifier = request_data.get("identifier", DEFAULT_CLIENT_IP)
257
+ request_id = request_data.get("request_id", self._generate_request_id())
258
+
259
+ # Step 1: Rate limiting check
260
+ if not self.check_rate_limit(identifier):
261
+ return {
262
+ "success": False,
263
+ "error": "Rate limit exceeded",
264
+ "error_code": ErrorCodes.RATE_LIMIT_EXCEEDED_ERROR,
265
+ "request_id": request_id,
266
+ "timestamp": datetime.utcnow().isoformat()
267
+ }
268
+
269
+ # Step 2: Authentication
270
+ auth_result = self.authenticate_user(credentials)
271
+ if not auth_result.is_valid:
272
+ return {
273
+ "success": False,
274
+ "error": "Authentication failed",
275
+ "error_code": auth_result.error_code,
276
+ "error_message": auth_result.error_message,
277
+ "request_id": request_id,
278
+ "timestamp": datetime.utcnow().isoformat()
279
+ }
280
+
281
+ # Step 3: Authorization
282
+ required_permissions = self._get_required_permissions(action, resource)
283
+ if not self.check_permissions(auth_result.roles, required_permissions):
284
+ return {
285
+ "success": False,
286
+ "error": "Insufficient permissions",
287
+ "error_code": ErrorCodes.PERMISSION_DENIED_ERROR,
288
+ "request_id": request_id,
289
+ "timestamp": datetime.utcnow().isoformat()
290
+ }
291
+
292
+ # Step 4: Process the action
293
+ result = await self._execute_action(action, resource, request_data.get("data", {}))
294
+
295
+ # Step 5: Log security event
296
+ self._log_security_event("request_processed", {
297
+ "username": auth_result.username,
298
+ "action": action,
299
+ "resource": resource,
300
+ "success": True,
301
+ "request_id": request_id,
302
+ "timestamp": datetime.utcnow().isoformat()
303
+ })
304
+
305
+ return {
306
+ "success": True,
307
+ "data": result,
308
+ "user": {
309
+ "username": auth_result.username,
310
+ "roles": auth_result.roles,
311
+ "auth_method": auth_result.auth_method
312
+ },
313
+ "request_id": request_id,
314
+ "timestamp": datetime.utcnow().isoformat()
315
+ }
316
+
317
+ except Exception as e:
318
+ self.logger.error(f"Request processing failed: {str(e)}")
319
+ return {
320
+ "success": False,
321
+ "error": "Internal server error",
322
+ "error_code": ErrorCodes.GENERAL_ERROR,
323
+ "request_id": request_id if 'request_id' in locals() else self._generate_request_id(),
324
+ "timestamp": datetime.utcnow().isoformat()
325
+ }
326
+
327
+ def authenticate_user(self, credentials: Dict[str, Any]) -> AuthResult:
328
+ """
329
+ Authenticate user with provided credentials.
330
+
331
+ Args:
332
+ credentials: User credentials (api_key, jwt_token, or certificate)
333
+
334
+ Returns:
335
+ AuthResult: Authentication result
336
+ """
337
+ try:
338
+ if "api_key" in credentials:
339
+ return self.security_manager.auth_manager.authenticate_api_key(credentials["api_key"])
340
+ elif "jwt_token" in credentials:
341
+ return self.security_manager.auth_manager.authenticate_jwt_token(credentials["jwt_token"])
342
+ elif "certificate" in credentials:
343
+ return self.security_manager.auth_manager.authenticate_certificate(credentials["certificate"])
344
+ else:
345
+ return AuthResult(
346
+ is_valid=False,
347
+ status=AuthStatus.FAILED,
348
+ username=None,
349
+ roles=[],
350
+ auth_method=None,
351
+ error_code=ErrorCodes.AUTHENTICATION_ERROR,
352
+ error_message="No valid credentials provided"
353
+ )
354
+ except Exception as e:
355
+ self.logger.error(f"Authentication failed: {str(e)}")
356
+ return AuthResult(
357
+ is_valid=False,
358
+ status=AuthStatus.FAILED,
359
+ username=None,
360
+ roles=[],
361
+ auth_method=None,
362
+ error_code=ErrorCodes.AUTHENTICATION_ERROR,
363
+ error_message=str(e)
364
+ )
365
+
366
+ def check_permissions(self, user_roles: List[str], required_permissions: List[str]) -> bool:
367
+ """
368
+ Check if user has required permissions.
369
+
370
+ Args:
371
+ user_roles: User roles
372
+ required_permissions: Required permissions
373
+
374
+ Returns:
375
+ bool: True if user has required permissions
376
+ """
377
+ try:
378
+ return self.security_manager.permission_manager.validate_access(
379
+ user_roles, required_permissions
380
+ )
381
+ except Exception as e:
382
+ self.logger.error(f"Permission check failed: {str(e)}")
383
+ return False
384
+
385
+ def check_rate_limit(self, identifier: str) -> bool:
386
+ """
387
+ Check if request is within rate limits.
388
+
389
+ Args:
390
+ identifier: Request identifier (IP, user ID, etc.)
391
+
392
+ Returns:
393
+ bool: True if request is within rate limits
394
+ """
395
+ try:
396
+ return self.security_manager.rate_limiter.check_rate_limit(identifier)
397
+ except Exception as e:
398
+ self.logger.error(f"Rate limit check failed: {str(e)}")
399
+ return True # Allow request if rate limiting fails
400
+
401
+ async def _execute_action(self, action: str, resource: str, data: Dict[str, Any]) -> Dict[str, Any]:
402
+ """
403
+ Execute the requested action.
404
+
405
+ Args:
406
+ action: Action to perform
407
+ resource: Resource to access
408
+ data: Action data
409
+
410
+ Returns:
411
+ Dict[str, Any]: Action result
412
+ """
413
+ # Simulate different microservice actions
414
+ if action == "get_user":
415
+ # Call user service
416
+ return await self.call_service("user-service", f"/api/v1/users/{data.get('user_id')}")
417
+ elif action == "create_order":
418
+ # Call order service
419
+ return await self.call_service("order-service", "/api/v1/orders", "POST", data)
420
+ elif action == "process_payment":
421
+ # Call payment service
422
+ return await self.call_service("payment-service", "/api/v1/payments", "POST", data)
423
+ elif action == "read":
424
+ return {"resource": resource, "data": {"example": "data"}}
425
+ elif action == "write":
426
+ return {"resource": resource, "data": data, "status": "written"}
427
+ else:
428
+ return {"error": f"Unknown action: {action}"}
429
+
430
+ def _get_required_permissions(self, action: str, resource: str) -> List[str]:
431
+ """
432
+ Get required permissions for action and resource.
433
+
434
+ Args:
435
+ action: Action to perform
436
+ resource: Resource to access
437
+
438
+ Returns:
439
+ List[str]: Required permissions
440
+ """
441
+ # Define permission mappings for microservices
442
+ permission_mappings = {
443
+ "get_user": ["read", "user"],
444
+ "create_order": ["write", "order"],
445
+ "process_payment": ["write", "payment"],
446
+ "read": ["read"],
447
+ "write": ["read", "write"],
448
+ "delete": ["read", "write", "delete"]
449
+ }
450
+
451
+ return permission_mappings.get(action, ["read"])
452
+
453
+ def _log_security_event(self, event_type: str, details: Dict[str, Any]):
454
+ """
455
+ Log security event.
456
+
457
+ Args:
458
+ event_type: Type of security event
459
+ details: Event details
460
+ """
461
+ try:
462
+ self.logger.info(
463
+ f"Security event: {event_type}",
464
+ extra={
465
+ "event_type": event_type,
466
+ "service": self.service_name,
467
+ "timestamp": details.get("timestamp"),
468
+ "username": details.get("username"),
469
+ "action": details.get("action"),
470
+ "resource": details.get("resource"),
471
+ "success": details.get("success"),
472
+ "request_id": details.get("request_id"),
473
+ **details
474
+ }
475
+ )
476
+ except Exception as e:
477
+ self.logger.error(f"Failed to log security event: {str(e)}")
478
+
479
+ async def health_check(self) -> Dict[str, Any]:
480
+ """
481
+ Perform health check for the microservice.
482
+
483
+ Returns:
484
+ Dict[str, Any]: Health check result
485
+ """
486
+ try:
487
+ # Check security manager health
488
+ security_healthy = self.security_manager is not None
489
+
490
+ # Check rate limiter health
491
+ rate_limit_healthy = self.security_manager.rate_limiter is not None
492
+
493
+ # Check service registry health
494
+ registry_healthy = len(self.service_registry) > 0
495
+
496
+ # Check SSL configuration
497
+ ssl_healthy = self.config.ssl.enabled and os.path.exists(self.config.ssl.cert_file)
498
+
499
+ overall_healthy = all([
500
+ security_healthy,
501
+ rate_limit_healthy,
502
+ registry_healthy,
503
+ ssl_healthy
504
+ ])
505
+
506
+ return {
507
+ "status": "healthy" if overall_healthy else "unhealthy",
508
+ "service": self.service_name,
509
+ "timestamp": datetime.utcnow().isoformat(),
510
+ "checks": {
511
+ "security_manager": security_healthy,
512
+ "rate_limiter": rate_limit_healthy,
513
+ "service_registry": registry_healthy,
514
+ "ssl_configuration": ssl_healthy
515
+ }
516
+ }
517
+ except Exception as e:
518
+ self.logger.error(f"Health check failed: {str(e)}")
519
+ return {
520
+ "status": "unhealthy",
521
+ "service": self.service_name,
522
+ "error": str(e),
523
+ "timestamp": datetime.utcnow().isoformat()
524
+ }
525
+
526
+ async def get_metrics(self) -> Dict[str, Any]:
527
+ """
528
+ Get microservice metrics.
529
+
530
+ Returns:
531
+ Dict[str, Any]: Metrics data
532
+ """
533
+ try:
534
+ # Get rate limiter metrics
535
+ rate_limit_stats = self.security_manager.rate_limiter.get_statistics()
536
+
537
+ # Get security manager status
538
+ security_status = self.get_security_status()
539
+
540
+ return {
541
+ "service": self.service_name,
542
+ "timestamp": datetime.utcnow().isoformat(),
543
+ "rate_limiting": rate_limit_stats,
544
+ "security": security_status,
545
+ "service_registry": {
546
+ "registered_services": len(self.service_registry),
547
+ "services": list(self.service_registry.keys())
548
+ }
549
+ }
550
+ except Exception as e:
551
+ self.logger.error(f"Failed to get metrics: {str(e)}")
552
+ return {
553
+ "service": self.service_name,
554
+ "error": str(e),
555
+ "timestamp": datetime.utcnow().isoformat()
556
+ }
557
+
558
+ def get_security_status(self) -> Dict[str, Any]:
559
+ """
560
+ Get security framework status.
561
+
562
+ Returns:
563
+ Dict[str, Any]: Security status information
564
+ """
565
+ return {
566
+ "service": self.service_name,
567
+ "ssl_enabled": self.config.ssl.enabled,
568
+ "auth_enabled": self.config.auth.enabled,
569
+ "rate_limiting_enabled": self.config.rate_limit.enabled,
570
+ "permissions_enabled": self.config.permissions.enabled,
571
+ "logging_enabled": self.config.logging.enabled,
572
+ "auth_methods": self.config.auth.methods,
573
+ "timestamp": datetime.utcnow().isoformat()
574
+ }
575
+
576
+
577
+ # Example usage and testing
578
+ class MicroserviceExampleTest:
579
+ """Test class for microservice example functionality."""
580
+
581
+ @staticmethod
582
+ async def test_authentication():
583
+ """Test authentication functionality."""
584
+ example = MicroserviceExample("test-service")
585
+
586
+ # Test API key authentication
587
+ credentials = {"api_key": "service_key_123"}
588
+ auth_result = example.authenticate_user(credentials)
589
+ assert auth_result.is_valid
590
+ assert auth_result.username == "user-service"
591
+ assert "service" in auth_result.roles
592
+
593
+ print("✅ API Key authentication test passed")
594
+
595
+ @staticmethod
596
+ async def test_permissions():
597
+ """Test permission checking."""
598
+ example = MicroserviceExample("test-service")
599
+
600
+ # Test service permissions
601
+ service_roles = ["service"]
602
+ user_roles = ["user"]
603
+ admin_roles = ["admin"]
604
+
605
+ # Service should have service permissions
606
+ assert example.check_permissions(service_roles, ["read", "write"])
607
+
608
+ # User should have user permissions
609
+ assert example.check_permissions(user_roles, ["read"])
610
+
611
+ # Admin should have all permissions
612
+ assert example.check_permissions(admin_roles, ["read", "write", "delete"])
613
+
614
+ print("✅ Permission checking test passed")
615
+
616
+ @staticmethod
617
+ async def test_rate_limiting():
618
+ """Test rate limiting functionality."""
619
+ example = MicroserviceExample("test-service")
620
+
621
+ # Test rate limiting
622
+ identifier = "test_service"
623
+ for i in range(5):
624
+ is_allowed = example.check_rate_limit(identifier)
625
+ print(f"Request {i+1}: {'Allowed' if is_allowed else 'Blocked'}")
626
+
627
+ print("✅ Rate limiting test completed")
628
+
629
+ @staticmethod
630
+ async def test_health_check():
631
+ """Test health check functionality."""
632
+ example = MicroserviceExample("test-service")
633
+
634
+ health = await example.health_check()
635
+ assert "status" in health
636
+ assert "service" in health
637
+ assert health["service"] == "test-service"
638
+
639
+ print("✅ Health check test passed")
640
+
641
+ @staticmethod
642
+ async def test_metrics():
643
+ """Test metrics functionality."""
644
+ example = MicroserviceExample("test-service")
645
+
646
+ metrics = await example.get_metrics()
647
+ assert "service" in metrics
648
+ assert "timestamp" in metrics
649
+ assert metrics["service"] == "test-service"
650
+
651
+ print("✅ Metrics test passed")
652
+
653
+
654
+ async def main():
655
+ """Main function for testing and example usage."""
656
+ # Run tests
657
+ print("Running Microservice Example Tests...")
658
+ await MicroserviceExampleTest.test_authentication()
659
+ await MicroserviceExampleTest.test_permissions()
660
+ await MicroserviceExampleTest.test_rate_limiting()
661
+ await MicroserviceExampleTest.test_health_check()
662
+ await MicroserviceExampleTest.test_metrics()
663
+
664
+ # Example usage
665
+ print("\nExample Usage:")
666
+ example = MicroserviceExample("user-service")
667
+
668
+ # Process a request
669
+ request_data = {
670
+ "credentials": {"api_key": "service_key_123"},
671
+ "action": "get_user",
672
+ "resource": "user_data",
673
+ "identifier": "192.168.1.100",
674
+ "data": {"user_id": "123"}
675
+ }
676
+
677
+ result = await example.process_request(request_data)
678
+ print(f"Request result: {result}")
679
+
680
+ # Get health status
681
+ health = await example.health_check()
682
+ print(f"Health status: {health}")
683
+
684
+ # Get metrics
685
+ metrics = await example.get_metrics()
686
+ print(f"Metrics: {metrics}")
687
+
688
+
689
+ if __name__ == "__main__":
690
+ asyncio.run(main())