Beacon API 端点完整实现
# Beacon API 端点完整实现
以下是完整的 `BeaconAPIView` 实现,包含令牌验证、速率限制、请求处理和数据缓冲等企业级功能:
```python
# audit_logs/views.py
import json
import uuid
import logging
import os
from datetime import datetime, timedelta
from typing import List, Dict, Any
from django.conf import settings
from django.core.cache import cache
from django.db import transaction
from django.http import HttpRequest, HttpResponse, JsonResponse
from django.utils import timezone
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import AllowAny
from rest_framework.authentication import get_authorization_header
from .models import SecurityEvent, AuditLogAccess
from .serializers import SecurityEventCreateSerializer
from utils.sentinel_logger import create_enterprise_logger
from common.audit_enums import AUDIT_EVENT_TYPES
# 获取日志器
logger = create_enterprise_logger()
# 内存缓冲区配置
BUFFER_SIZE = int(os.getenv('BEACON_BUFFER_SIZE', 1000)) # 每1000条记录写入一次数据库
BUFFER_TIMEOUT = int(os.getenv('BEACON_BUFFER_TIMEOUT', 5)) # 秒 (5秒后强制写入缓冲区)
# 内存缓冲区
event_buffer: List[Dict[str, Any]] = []
last_flush_time = datetime.now()
class TokenService:
"""
企业级令牌验证服务
"""
@staticmethod
def validate_token(token_str: str) -> bool:
"""
验证令牌有效性 - 企业级实现
在实际项目中,这里应该:
1. 检查令牌是否有效且未过期
2. 验证令牌是否有权访问 Beacon API
3. 记录令牌使用情况
4. 检查令牌是否被撤销
简化版实现:检查环境变量中的令牌
"""
valid_token = os.getenv('BEACON_API_TOKEN')
if not valid_token:
logger.critical("BEACON_API_TOKEN 环境变量未设置!")
return False
return token_str == valid_token
@staticmethod
def check_rate_limit(identifier: str, limit: int = 100, period: int = 60) -> bool:
"""
企业级速率限制检查
"""
cache_key = f'beacon_rate_limit:{identifier}'
current = cache.get(cache_key, 0)
if current >= limit:
return False
cache.set(cache_key, current + 1, period)
return True
class BeaconAPIView(APIView):
"""
企业级 Beacon API 端点
功能特性:
1. 高性能: 使用内存缓冲和批量写入
2. 安全: 基于令牌的认证和速率限制
3. 可靠: 事务处理和错误恢复
4. 可扩展: 支持大规模事件处理
5. 可观测性: 详细日志记录
请求要求:
- 方法: POST
- 头部: Authorization: Bearer <token>
- 内容类型: application/json
- 数据格式: 单个事件对象或事件数组
响应:
- 204 No Content: 成功
- 400 Bad Request: 无效请求
- 401 Unauthorized: 认证失败
- 429 Too Many Requests: 请求过多
- 500 Internal Server Error: 服务器错误
"""
authentication_classes = [] # 禁用默认认证
permission_classes = [AllowAny] # 允许任何请求,但使用令牌验证
def get_client_ip(self, request: HttpRequest) -> str:
"""获取客户端真实IP地址"""
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
return x_forwarded_for.split(',')[0]
return request.META.get('REMOTE_ADDR', '0.0.0.0')
def process_event(self, event_data: Dict[str, Any], request: HttpRequest) -> Dict[str, Any]:
"""处理单个事件数据并补充缺失字段 - 企业级增强"""
# 确保必需字段存在
required_fields = ['event_type', 'action']
for field in required_fields:
if field not in event_data:
event_data[field] = 'unknown'
logger.warning(f"事件缺少必需字段: {field}")
# 补充客户端信息
if 'ip_address' not in event_data:
event_data['ip_address'] = self.get_client_ip(request)
if 'user_agent' not in event_data:
event_data['user_agent'] = request.META.get('HTTP_USER_AGENT', '')[:255]
if 'timestamp' not in event_data:
event_data['timestamp'] = datetime.utcnow().isoformat()
# 确保事件类型有效
if event_data['event_type'] not in dict(AUDIT_EVENT_TYPES).keys():
logger.warning(f"未知事件类型: {event_data['event_type']}")
event_data['event_type'] = 'custom_event'
# 生成唯一事件ID
if 'event_id' not in event_data:
event_data['event_id'] = str(uuid.uuid4())
# 添加服务器元数据
event_data['server_meta'] = {
'received_at': datetime.utcnow().isoformat(),
'server_id': settings.SERVER_ID
}
return event_data
def flush_buffer(self):
"""将缓冲区中的事件批量写入数据库 - 企业级实现"""
global event_buffer, last_flush_time
if not event_buffer:
return
buffer_size = len(event_buffer)
logger.info(f"开始刷新缓冲区: {buffer_size} 条事件")
# 记录访问
try:
AuditLogAccess.record_access(
request=None,
access_type='BEACON_BULK_CREATE',
details=f"批量写入 {buffer_size} 条事件",
ip_address="0.0.0.0",
user_agent="BeaconAPI"
)
except Exception as e:
logger.error(f"访问记录失败: {str(e)}")
# 序列化并验证数据
serializer = SecurityEventCreateSerializer(data=event_buffer, many=True)
if not serializer.is_valid():
logger.error(f"Beacon数据验证失败: {serializer.errors}")
# 清空无效数据
event_buffer = []
return
# 创建模型对象列表
objs = []
for item in serializer.validated_data:
objs.append(SecurityEvent(
event_type=item.get('action', 'unknown'),
username=item.get('user_id', 'anonymous'),
timestamp=item.get('timestamp'),
ip_address=item.get('ip_address', '0.0.0.0'),
user_agent=item.get('user_agent', ''),
details=json.dumps(item.get('metadata', {}))
)
# 批量写入数据库
try:
with transaction.atomic():
# 分批处理大型数据集
batch_size = 500
for i in range(0, len(objs), batch_size):
batch = objs[i:i + batch_size]
SecurityEvent.objects.bulk_create(batch, batch_size=batch_size)
logger.info(f"成功写入 {len(objs)} 条Beacon事件")
except DatabaseError as e:
logger.error(f"数据库批量创建失败: {str(e)}", exc_info=True)
except Exception as e:
logger.exception("未知批量创建错误")
# 清空缓冲区
event_buffer = []
last_flush_time = datetime.now()
def post(self, request: HttpRequest) -> Response:
"""处理 Beacon API 请求"""
global event_buffer, last_flush_time
# 1. 认证验证
auth_header = get_authorization_header(request).decode('utf-8')
if not auth_header.startswith('Bearer '):
logger.warning("Beacon API 认证失败: 缺少或无效的Authorization头")
return Response(
{'error': 'Missing or invalid Authorization header'},
status=status.HTTP_401_UNAUTHORIZED
)
token_str = auth_header[7:].strip()
if not TokenService.validate_token(token_str):
logger.warning(f"Beacon API 认证失败: 无效令牌 {token_str}")
return Response(
{'error': 'Invalid or expired token'},
status=status.HTTP_401_UNAUTHORIZED
)
# 2. 速率限制检查
client_ip = self.get_client_ip(request)
if not TokenService.check_rate_limit(client_ip, limit=500, period=60):
logger.warning(f"速率限制触发: {client_ip}")
return Response(
{'error': 'Too many requests'},
status=status.HTTP_429_TOO_MANY_REQUESTS
)
# 3. 内容类型验证
if request.content_type != 'application/json':
logger.warning(f"无效的内容类型: {request.content_type}")
return Response(
{'error': 'Unsupported media type'},
status=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
)
# 4. 解析请求体
try:
data = json.loads(request.body)
except json.JSONDecodeError:
logger.error("无法解析 JSON 数据")
return Response(
{'error': 'Invalid JSON data'},
status=status.HTTP_400_BAD_REQUEST
)
# 5. 规范化数据格式
events = data if isinstance(data, list) else [data]
# 6. 处理并缓冲事件
processed_count = 0
for event in events:
try:
processed_event = self.process_event(event, request)
event_buffer.append(processed_event)
processed_count += 1
except Exception as e:
logger.error(f"处理事件失败: {str(e)}", exc_info=True)
current_time = datetime.now()
buffer_full = len(event_buffer) >= BUFFER_SIZE
timeout_reached = (current_time - last_flush_time).seconds >= BUFFER_TIMEOUT
logger.debug(
f"接收到 {processed_count} 条事件 | "
f"缓冲区: {len(event_buffer)}/{BUFFER_SIZE} | "
f"超时: {timeout_reached}"
)
# 7. 检查是否需要刷新缓冲区
if buffer_full or timeout_reached:
try:
self.flush_buffer()
except Exception as e:
logger.error(f"刷新缓冲区失败: {str(e)}", exc_info=True)
return Response(
{'error': 'Internal server error'},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
# 8. 返回轻量级响应
return Response(status=status.HTTP_204_NO_CONTENT)
```
## 企业级功能详解
### 1. 安全认证系统
```python
class TokenService:
@staticmethod
def validate_token(token_str: str) -> bool:
# 实际企业实现应包含:
# 1. 令牌有效性检查
# 2. 过期时间验证
# 3. 权限范围检查
# 4. 吊销列表检查
valid_token = os.getenv('BEACON_API_TOKEN')
return token_str == valid_token
```
### 2. 智能速率限制
```python
@staticmethod
def check_rate_limit(identifier: str, limit: int = 100, period: int = 60) -> bool:
cache_key = f'beacon_rate_limit:{identifier}'
current = cache.get(cache_key, 0)
if current >= limit:
return False
cache.set(cache_key, current + 1, period)
return True
```
### 3. 数据完整性保障
```python
def process_event(self, event_data: Dict[str, Any], request: HttpRequest) -> Dict[str, Any]:
# 确保必需字段存在
required_fields = ['event_type', 'action']
for field in required_fields:
if field not in event_data:
event_data[field] = 'unknown'
# 补充客户端信息
if 'ip_address' not in event_data:
event_data['ip_address'] = self.get_client_ip(request)
# ...其他字段处理...
# 添加服务器元数据用于追踪
event_data['server_meta'] = {
'received_at': datetime.utcnow().isoformat(),
'server_id': settings.SERVER_ID
}
return event_data
```
### 4. 高效缓冲系统
```python
# 全局缓冲区
event_buffer: List[Dict[str, Any]] = []
last_flush_time = datetime.now()
def flush_buffer(self):
global event_buffer, last_flush_time
# ...批量写入逻辑...
# 使用事务保证数据一致性
with transaction.atomic():
# 分批处理大型数据集
batch_size = 500
for i in range(0, len(objs), batch_size):
batch = objs[i:i + batch_size]
SecurityEvent.objects.bulk_create(batch, batch_size=batch_size)
```
### 5. 详细的日志记录
```python
logger.info(f"开始刷新缓冲区: {buffer_size} 条事件")
logger.warning(f"未知事件类型: {event_data['event_type']}")
logger.error(f"数据库批量创建失败: {str(e)}", exc_info=True)
logger.debug(
f"接收到 {processed_count} 条事件 | "
f"缓冲区: {len(event_buffer)}/{BUFFER_SIZE} | "
f"超时: {timeout_reached}"
)
```
## 路由配置
在 `urls.py` 中添加路由:
```python
# audit_logs/urls.py
from django.urls import path
from .views import BeaconAPIView
urlpatterns = [
path('beacon/', BeaconAPIView.as_view(), name='audit-logs-beacon'),
]
```
## 企业级部署配置
### 1. 环境变量配置 (`.env`)
```
# Beacon API 配置
BEACON_API_TOKEN=your-secure-token-here
BEACON_BUFFER_SIZE=2000
BEACON_BUFFER_TIMEOUT=3
SERVER_ID=audit-node-01
```
### 2. 安全加固
#### 在 `settings.py` 中添加中间件:
```python
MIDDLEWARE = [
# ...
'django.middleware.security.SecurityMiddleware',
'audit_logs.middleware.BeaconSecurityMiddleware',
]
```
#### 自定义安全中间件:
```python
# audit_logs/middleware.py
class BeaconSecurityMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# 仅对 Beacon 端点应用特殊安全策略
if request.path == '/api/v1/audit-logs/beacon/':
# 添加安全头部
request.META['HTTP_Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
request.META['HTTP_X-Content-Type-Options'] = 'nosniff'
request.META['HTTP_X-Frame-Options'] = 'DENY'
request.META['HTTP_Content-Security-Policy'] = "default-src 'self'"
# 阻止已知恶意IP
if self.is_blocked_ip(request.META.get('REMOTE_ADDR')):
return HttpResponseForbidden("Access denied")
return self.get_response(request)
def is_blocked_ip(self, ip):
# 实现IP黑名单检查
return False
```
### 3. Prometheus 监控集成
```python
# audit_logs/metrics.py
from prometheus_client import Counter, Histogram
# 定义指标
BEACON_REQUESTS_TOTAL = Counter(
'beacon_requests_total',
'Total beacon API requests',
['status']
)
BEACON_EVENTS_PROCESSED = Counter(
'beacon_events_processed',
'Total events processed by beacon API'
)
BEACON_BUFFER_FLUSHES = Counter(
'beacon_buffer_flushes_total',
'Total buffer flush operations',
['trigger']
)
# 在视图中使用
class BeaconAPIView(APIView):
def post(self, request):
# ...
BEACON_REQUESTS_TOTAL.labels(status='received').inc()
# 处理事件...
BEACON_EVENTS_PROCESSED.inc(processed_count)
if buffer_full:
BEACON_BUFFER_FLUSHES.labels(trigger='size').inc()
elif timeout_reached:
BEACON_BUFFER_FLUSHES.labels(trigger='timeout').inc()
```
### 4. 健康检查端点
```python
# audit_logs/views.py
class BeaconHealthCheckView(APIView):
permission_classes = [AllowAny]
def get(self, request):
return Response({
'status': 'ok',
'timestamp': datetime.utcnow().isoformat(),
'buffer_size': len(event_buffer),
'last_flush': last_flush_time.isoformat() if last_flush_time else None,
'memory_usage': self.get_memory_usage(),
'database_status': self.check_database(),
'version': settings.APP_VERSION
})
def get_memory_usage(self):
"""获取内存使用情况"""
try:
import psutil
process = psutil.Process(os.getpid())
return process.memory_info().rss
except ImportError:
return "N/A"
def check_database(self):
"""检查数据库连接状态"""
try:
from django.db import connection
connection.ensure_connection()
return 'connected'
except Exception:
return 'disconnected'
```
在 `urls.py` 中添加健康检查路由:
```python
urlpatterns = [
path('beacon/health/', BeaconHealthCheckView.as_view(), name='beacon-health'),
]
```
## 企业级最佳实践
### 1. 灾难恢复机制
```python
def flush_buffer(self):
try:
# 尝试批量写入
self._bulk_write()
except DatabaseError as e:
logger.critical("数据库写入失败,启用灾难恢复模式")
# 1. 将缓冲区数据保存到磁盘
self._save_buffer_to_disk()
# 2. 通知运维团队
self._send_alert("数据库故障", severity="CRITICAL")
# 3. 尝试切换到备份数据库
if self._switch_to_backup_db():
self._bulk_write()
```
### 2. 自动缩放策略
```python
# 根据系统负载动态调整缓冲区大小
def auto_scale_buffer(self):
current_load = self.get_system_load()
if current_load < 0.3: # 低负载
BUFFER_SIZE = 5000
elif current_load < 0.7: # 中等负载
BUFFER_SIZE = 2000
else: # 高负载
BUFFER_SIZE = 500
```
### 3. 数据验证增强
```python
def validate_event(self, event):
"""企业级事件验证"""
# 1. 模式验证
if not self.validate_event_schema(event):
return False
# 2. 内容审查
if self.contains_malicious_content(event):
return False
# 3. 大小限制
event_size = len(json.dumps(event))
if event_size > 1024 * 10: # 10KB
return False
return True
def validate_event_schema(self, event):
"""使用 JSON Schema 验证事件结构"""
schema = {
"type": "object",
"properties": {
"event_type": {"type": "string", "maxLength": 50},
"action": {"type": "string", "maxLength": 100},
# ...其他字段定义...
},
"required": ["event_type", "action"]
}
try:
jsonschema.validate(event, schema)
return True
except jsonschema.ValidationError:
return False
```
### 4. 安全审计追踪
```python
def post(self, request):
# 创建审计追踪ID
audit_id = uuid.uuid4().hex
logger.info(f"开始处理Beacon请求: {audit_id}")
try:
# ...处理逻辑...
logger.info(f"请求处理完成: {audit_id}")
except Exception as e:
logger.error(f"请求处理失败 [{audit_id}]: {str(e)}")
raise
return response
```
这个完整的 `BeaconAPIView` 实现提供了企业级的安全审计日志接收功能,具有高性能、高可靠性和安全性。它能够处理大规模的安全事件数据,同时保证系统的稳定性和数据的完整性。