Automated Action 2adbcd0535 Complete multi-tenant SaaS platform with external integrations
- Implemented comprehensive multi-tenant data isolation using database-level security
- Built JWT authentication system with role-based access control (Super Admin, Org Admin, User, Viewer)
- Created RESTful API endpoints for user and organization operations
- Added complete audit logging for all data modifications with IP tracking
- Implemented API rate limiting and input validation with security middleware
- Built webhook processing engine with async event handling and retry logic
- Created external API call handlers with circuit breaker pattern and error handling
- Implemented data synchronization between external services and internal data
- Added integration health monitoring and status tracking
- Created three mock external services (User Management, Payment, Communication)
- Implemented idempotency for webhook processing to handle duplicates gracefully
- Added comprehensive security headers and XSS/CSRF protection
- Set up Alembic database migrations with proper SQLite configuration
- Included extensive documentation and API examples

Architecture features:
- Multi-tenant isolation at database level
- Circuit breaker pattern for external API resilience
- Async background task processing
- Complete audit trail with user context
- Role-based permission system
- Webhook signature verification
- Request validation and sanitization
- Health monitoring endpoints

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-27 21:14:30 +00:00

99 lines
3.5 KiB
Python

from fastapi import Request
import re
class ValidationMiddleware:
def __init__(self):
self.suspicious_patterns = [
r'<script[^>]*>.*?</script>', # XSS
r'union\s+select', # SQL injection
r'drop\s+table', # SQL injection
r'insert\s+into', # SQL injection
r'delete\s+from', # SQL injection
r'update\s+.*\s+set', # SQL injection
r'exec\s*\(', # Command injection
r'eval\s*\(', # Code injection
r'javascript:', # XSS
r'vbscript:', # XSS
r'data:text/html', # Data URL XSS
]
self.compiled_patterns = [re.compile(pattern, re.IGNORECASE) for pattern in self.suspicious_patterns]
def validate_input(self, text: str) -> bool:
"""Check if input contains suspicious patterns"""
if not text:
return True
for pattern in self.compiled_patterns:
if pattern.search(text):
return False
return True
def sanitize_headers(self, headers: dict) -> bool:
"""Validate request headers"""
dangerous_headers = ['x-forwarded-host', 'x-original-url', 'x-rewrite-url']
for header_name, header_value in headers.items():
if header_name.lower() in dangerous_headers:
if not self.validate_input(str(header_value)):
return False
# Check for header injection
if '\n' in str(header_value) or '\r' in str(header_value):
return False
return True
def validate_json_payload(self, payload: dict) -> bool:
"""Recursively validate JSON payload"""
if isinstance(payload, dict):
for key, value in payload.items():
if isinstance(value, str):
if not self.validate_input(value):
return False
elif isinstance(value, (dict, list)):
if not self.validate_json_payload(value):
return False
elif isinstance(payload, list):
for item in payload:
if isinstance(item, str):
if not self.validate_input(item):
return False
elif isinstance(item, (dict, list)):
if not self.validate_json_payload(item):
return False
return True
validation_middleware = ValidationMiddleware()
def validate_request_size(request: Request) -> bool:
"""Validate request size to prevent DoS attacks"""
content_length = request.headers.get('content-length')
if content_length:
try:
size = int(content_length)
# Limit to 10MB
if size > 10 * 1024 * 1024:
return False
except ValueError:
return False
return True
def security_headers_middleware(request: Request, call_next):
"""Add security headers to responses"""
response = call_next(request)
# Add security headers
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "DENY"
response.headers["X-XSS-Protection"] = "1; mode=block"
response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
response.headers["Content-Security-Policy"] = "default-src 'self'"
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
return response