# 蜜罐系统核心模块代码

## 2. 规则引擎 (`core/rule_engine.py`)
import time
import json
import logging
import os
from typing import List, Dict, Any, Optional
from plugins import CountermeasurePlugin

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class RuleEngine:
    '''
    规则引擎，负责解析规则并触发反制动作。
    '''

    def __init__(self, audit_log_file: str = 'logs/countermeasure_audit.log'):
        self.rules: List[Dict[str, Any]] = []
        self.countermeasures: Dict[str, CountermeasurePlugin] = {}
        self.audit_log_file = audit_log_file

    def load_rules(self, rules: List[Dict[str, Any]]):
        '''加载反制规则'''
        self.rules = rules
        logger.info(f"Loaded {len(rules)} rules.")

    def register_countermeasure(self, name: str, plugin: CountermeasurePlugin):
        '''注册反制动作插件'''
        self.countermeasures[name] = plugin
        logger.info(f"Registered countermeasure plugin: {name}")

    def evaluate_and_execute(self, request_context: Dict[str, Any], environment_id: str) -> List[Dict[str, Any]]:
        '''
        评估请求上下文并执行匹配的反制动作 (使用引擎内部加载的全局规则)
        :param request_context: 请求上下文信息
        :param environment_id: 触发反制的环境ID
        :return: 执行的反制动作结果列表
        '''
        # 使用引擎内部的全局规则列表
        return self._evaluate_and_execute_rules(self.rules, request_context, environment_id)

    def evaluate_and_execute_for_environment(self, request_context: Dict[str, Any], environment_rules: List[Dict[str, Any]], environment_id: str) -> List[Dict[str, Any]]:
        '''
        评估请求上下文并执行匹配的反制动作 (使用为特定环境指定的规则)
        :param request_context: 请求上下文信息
        :param environment_rules: 为该环境指定的规则列表
        :param environment_id: 触发反制的环境ID
        :return: 执行的反制动作结果列表
        '''
        # 使用传入的特定环境规则列表
        return self._evaluate_and_execute_rules(environment_rules, request_context, environment_id)

    def _evaluate_and_execute_rules(self, rules_to_evaluate: List[Dict[str, Any]], request_context: Dict[str, Any], environment_id: str) -> List[Dict[str, Any]]:
        '''
        内部方法：执行规则评估和反制动作
        :param rules_to_evaluate: 要评估的规则列表
        :param request_context: 请求上下文信息
        :param environment_id: 触发反制的环境ID
        :return: 执行的反制动作结果列表
        '''
        results = []
        for rule in rules_to_evaluate:
            if not rule.get('enabled', True):
                continue

            if self._match_conditions(rule.get('conditions', []), request_context):
                action_name = rule.get('action')
                cm_plugin = self.countermeasures.get(action_name)
                
                if cm_plugin:
                    try:
                        # 将规则配置传递给插件
                        context_with_config = request_context.copy()
                        context_with_config['config'] = rule.get('config', {})
                        
                        result = cm_plugin.execute(context_with_config)
                        execution_result = {
                            'rule_id': rule['id'],
                            'action': action_name,
                            'result': result
                        }
                        results.append(execution_result)
                        
                        # 记录审计日志
                        self._log_audit(rule['id'], environment_id, request_context, action_name, result)
                        
                    except Exception as e:
                        logger.error(f"Error executing countermeasure {action_name} for rule {rule['id']}: {e}")
                else:
                    logger.warning(f"Countermeasure plugin '{action_name}' not found for rule {rule['id']}")
        
        return results

    def _match_conditions(self, conditions: List[Dict[str, Any]], context: Dict[str, Any]) -> bool:
        '''匹配规则条件'''
        # 简化的条件匹配逻辑
        # 在实际应用中，可能需要更复杂的匹配，如正则表达式、范围比较等
        for condition in conditions:
            match = True
            for key, value in condition.items():
                if key in context and context[key] != value:
                    match = False
                    break
                elif key not in context:
                    match = False
                    break
            
            # 如果有一个条件完全匹配，则认为规则匹配
            if match:
                return True
        
        return False
    
    def _log_audit(self, rule_id: str, environment_id: str, request_context: Dict[str, Any], action: str, result: Dict[str, Any]):
        '''记录审计日志'''
        log_entry = {
            'timestamp': time.time(), # 简化时间戳，实际应用中应使用 ISO 8601 格式
            'rule_id': rule_id,
            'environment_id': environment_id,
            'request': self._sanitize_context(request_context),
            'action': action,
            'result': result
        }
        
        try:
            # 确保日志目录存在
            log_dir = os.path.dirname(self.audit_log_file)
            if log_dir:
                os.makedirs(log_dir, exist_ok=True)
                
            with open(self.audit_log_file, 'a', encoding='utf-8') as f:
                f.write(json.dumps(log_entry) + '\n')
        except Exception as e:
            logger.error(f"Failed to write audit log: {e}")
            
    def _sanitize_context(self, context: Dict[str, Any]) -> Dict[str, Any]:
        '''对请求上下文进行脱敏处理，避免记录敏感信息'''
        # 这里只是一个示例，实际应用中需要根据具体情况脱敏
        sanitized = context.copy()
        # 例如，可以移除或哈希化 IP 地址等
        # sanitized['ip'] = hash(sanitized.get('ip', '')) 
        return sanitized