""" 审计日志模块 记录系统关键操作,用于安全审计和合规追踪 """ from typing import Optional from datetime import datetime import logging from uuid import UUID logger = logging.getLogger(__name__) class AuditAction: """审计操作类型常量""" # 认证相关 LOGIN = "LOGIN" LOGOUT = "LOGOUT" REGISTER = "REGISTER" PASSWORD_CHANGE = "PASSWORD_CHANGE" # 数据操作 CREATE = "CREATE" READ = "READ" UPDATE = "UPDATE" DELETE = "DELETE" # 权限相关 PERMISSION_CHANGE = "PERMISSION_CHANGE" ROLE_CHANGE = "ROLE_CHANGE" # 系统操作 CONFIG_CHANGE = "CONFIG_CHANGE" SYSTEM_START = "SYSTEM_START" SYSTEM_STOP = "SYSTEM_STOP" async def log_audit_event( action: str, user_id: Optional[UUID] = None, project_id: Optional[UUID] = None, resource_type: Optional[str] = None, resource_id: Optional[str] = None, ip_address: Optional[str] = None, request_method: Optional[str] = None, request_path: Optional[str] = None, request_data: Optional[dict] = None, response_status: Optional[int] = None, session=None, ): """ 记录审计日志 Args: action: 操作类型 user_id: 用户ID project_id: 项目ID resource_type: 资源类型 resource_id: 资源ID ip_address: IP地址 request_method: 请求方法 request_path: 请求路径 request_data: 请求数据(敏感字段需脱敏) response_status: 响应状态码 session: 元数据库会话(可选) """ from app.infra.db.metadata.database import SessionLocal from app.infra.repositories.audit_repository import AuditRepository if request_data: request_data = sanitize_sensitive_data(request_data) if session is None: async with SessionLocal() as session: audit_repo = AuditRepository(session) await audit_repo.create_log( user_id=user_id, project_id=project_id, action=action, resource_type=resource_type, resource_id=resource_id, ip_address=ip_address, request_method=request_method, request_path=request_path, request_data=request_data, response_status=response_status, ) else: audit_repo = AuditRepository(session) await audit_repo.create_log( user_id=user_id, project_id=project_id, action=action, resource_type=resource_type, resource_id=resource_id, ip_address=ip_address, request_method=request_method, request_path=request_path, request_data=request_data, response_status=response_status, ) logger.info( "Audit log created: action=%s, user=%s, project=%s, resource=%s:%s", action, user_id, project_id, resource_type, resource_id, ) def sanitize_sensitive_data(data: dict) -> dict: """ 脱敏敏感数据 Args: data: 原始数据 Returns: 脱敏后的数据 """ sensitive_fields = [ "password", "passwd", "pwd", "secret", "token", "api_key", "apikey", "credit_card", "ssn", "social_security", ] sanitized = data.copy() for key in sanitized: if isinstance(sanitized[key], dict): sanitized[key] = sanitize_sensitive_data(sanitized[key]) elif any(sensitive in key.lower() for sensitive in sensitive_fields): sanitized[key] = "***REDACTED***" return sanitized