Files
wecom_it_smart_desk/docs/ExternalSystemAdapter设计文档.md

12 KiB
Raw Permalink Blame History

ExternalSystemAdapter 抽象层设计文档

版本:V1.0 | 日期:2026-06-11 | 作者:IT智能服务台项目组


一、设计目标

为联软、火绒、aTrust、eHR 四个外部系统提供统一适配层,实现:

  1. 接口统一:上层业务代码只依赖抽象接口,不感知底层系统差异
  2. 可替换性:Mock数据开发 → 真实API无缝切换,只需改配置
  3. 缓存透明:外部数据自动缓存+定时刷新,业务层无感
  4. 降级安全:外部系统不可用时自动降级,不阻断主流程
  5. 横向扩展:新增系统只需实现一个 Adapter,零改动业务层

二、系统角色与优先级

系统 角色 核心能力 认证方式 凭证状态
联软LV7000 主映射源(P0) 终端查询(含strusername)、硬件详情、在线状态 IP白名单+账号密码+Token 明天可拿
火绒企业版 安全源(P0) 终端列表、漏洞/病毒事件、一键隔离 HMAC-SHA1 AccessKey 现在可拿
aTrust VPN源(P1) 在线用户+VPN IP、终端查询、踢出用户 HMAC-SHA256签名 约一周
北森eHR 辅助静态数据(P2) 员工基础信息、任职信息 OAuth2.0 待对接HR

三、架构分层

┌─────────────────────────────────────────────────┐
│              上层业务代码(AI Wingman等)          │
├─────────────────────────────────────────────────┤
│           ExternalSystemService(统一门面)        │
│    ┌──────────┐ ┌──────────┐ ┌──────────┐       │
│    │ 缓存层   │ │ 降级策略 │ │ 配置管理 │       │
│    └──────────┘ └──────────┘ └──────────┘       │
├─────────────────────────────────────────────────┤
│           ExternalSystemAdapter(抽象基类)        │
│    ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────┐│
│    │ LianRuan │ │ HuoRong  │ │ aTrust   │ │eHR ││
│    │ Adapter  │ │ Adapter  │ │ Adapter  │ │ 适配││
│    └──────────┘ └──────────┘ └──────────┘ └────┘│
├─────────────────────────────────────────────────┤
│               MockAdapter(开发期)               │
└─────────────────────────────────────────────────┘

四、核心抽象接口

4.1 数据模型(统一DTO

class TerminalInfo(BaseModel):
    """统一终端信息模型 — 所有Adapter返回同一结构"""
    source_system: str           # 数据来源系统标识
    computer_name: str           # 计算机名
    ip_addresses: List[str]      # IP地址列表(含VPN虚拟IP
    mac_addresses: List[str]      # MAC地址列表
    os_version: Optional[str]     # 操作系统版本
    is_online: bool               # 是否在线
    logged_in_user: Optional[str] # 当前登录用户账号(映射核心字段)
    logged_in_user_name: Optional[str]  # 用户姓名
    department: Optional[str]     # 所属部门
    hardware_summary: Optional[Dict]    # 硬件摘要(CPU/内存/磁盘)
    last_seen: Optional[datetime]       # 最后在线时间
    raw_data: Optional[Dict]            # 原始响应(调试用,生产可关闭)

class SecurityStatus(BaseModel):
    """统一安全状态模型"""
    source_system: str
    terminal_id: str
    virus_events: Optional[Dict]     # 病毒事件统计
    vulnerabilities: Optional[List]    # 高危漏洞列表
    is_isolated: bool                 # 是否被隔离
    isolation_source: Optional[str]   # 隔离来源系统

class VpnSession(BaseModel):
    """VPN会话模型(仅aTrust"""
    source_system: str = "atrust"
    username: str
    display_name: Optional[str]
    remote_ip: str
    vpn_ip: Optional[str]       # 虚拟内网IP
    is_trusted: bool
    last_login: Optional[datetime]

4.2 Adapter抽象基类

from abc import ABC, abstractmethod
from typing import Optional, List

class ExternalSystemAdapter(ABC):
    """外部系统适配器抽象基类
    
    每个外部系统实现此接口,上层业务只依赖此接口。
    """
    
    @property
    @abstractmethod
    def system_name(self) -> str:
        """系统标识名称,如 'lianruan' / 'huorong' / 'atrust' / 'ehr'"""
        ...
    
    @property
    @abstractmethod
    def is_available(self) -> bool:
        """当前系统是否可用(凭证已配置+网络可达)"""
        ...
    
    @abstractmethod
    async def health_check(self) -> bool:
        """健康检查 — 验证凭证和网络连通性"""
        ...
    
    # ── 终端查询能力 ──
    
    async def get_terminal_by_user(self, username: str) -> Optional[TerminalInfo]:
        """通过员工账号查询终端信息(映射核心方法)
        
        联软:queryDevByParams(strusername=xxx)
        火绒:_list(ip=xxx) 需配合联软IP交叉匹配
        aTrustqueryAll(bindUserList) 终端绑定用户
        eHR:不提供终端数据,返回None
        """
        return None  # 默认不支持,子类按需覆写
    
    async def get_terminal_by_computer(self, computer_name: str) -> Optional[TerminalInfo]:
        """通过计算机名查询终端信息"""
        return None
    
    async def get_terminal_detail(self, terminal_id: str) -> Optional[TerminalInfo]:
        """查询终端详细信息(硬件/软件/网络配置)"""
        return None
    
    # ── 安全能力 ──
    
    async def get_security_status(self, terminal_id: str) -> Optional[SecurityStatus]:
        """获取终端安全状态(病毒/漏洞/隔离状态)"""
        return None
    
    async def isolate_terminal(self, terminal_id: str, reason: str) -> bool:
        """隔离终端(仅火绒支持,需admin角色二次确认)"""
        raise NotImplementedError(f"{self.system_name} 不支持终端隔离")
    
    async def unisolate_terminal(self, terminal_id: str) -> bool:
        """解除终端隔离"""
        raise NotImplementedError(f"{self.system_name} 不支持解除隔离")
    
    # ── VPN/在线状态 ──
    
    async def get_vpn_sessions(self, username: Optional[str] = None) -> List[VpnSession]:
        """查询VPN在线会话(仅aTrust支持)"""
        return []
    
    async def get_online_status(self, username: str) -> bool:
        """查询用户是否在线"""
        return False

4.3 统一门面服务

class ExternalSystemService:
    """外部系统统一门面 — 上层业务只调用此类"""
    
    def __init__(self, adapters: Dict[str, ExternalSystemAdapter], cache: CacheService):
        self._adapters = adapters  # {"lianruan": LianRuanAdapter, ...}
        self._cache = cache
    
    async def find_user_terminal(self, username: str) -> Optional[TerminalInfo]:
        """查找用户终端 — 优先联软,降级aTrust,最后eHR
        
        做什么:按映射优先级依次查询,任一系统返回即停止
        为什么:联软strusername精确匹配最可靠,aTrust次之
        """
        # 1. 联软(主源,strusername精确匹配)
        result = await self._query_with_cache("lianruan", "get_terminal_by_user", username)
        if result:
            return result
        
        # 2. aTrustVPN源,bindUserList匹配)
        result = await self._query_with_cache("atrust", "get_terminal_by_user", username)
        if result:
            return result
        
        # 3. eHR(静态辅助,无终端数据)
        return None
    
    async def get_terminal_security(self, terminal_id: str) -> Optional[SecurityStatus]:
        """获取终端安全状态 — 仅火绒"""
        return await self._query_with_cache("huorong", "get_security_status", terminal_id)
    
    async def isolate_terminal(self, terminal_id: str, reason: str, operator: str) -> bool:
        """隔离终端 — 仅火绒,需operator记录审计日志"""
        logger.warning(f"终端隔离操作: terminal={terminal_id}, operator={operator}, reason={reason}")
        return await self._adapters["huorong"].isolate_terminal(terminal_id, reason)

五、缓存策略

数据类型 缓存TTL 刷新策略 说明
终端映射(员工→终端) 30分钟 定时刷新+访问时检查 映射关系不常变
终端详情(硬件/软件) 60分钟 懒加载 硬件配置极少变
安全状态(漏洞/病毒) 5分钟 短TTL+事件驱动 安全状态需近实时
VPN在线状态 1分钟 短TTL 在线状态变化快
eHR员工信息 24小时 每日凌晨全量同步 静态数据

缓存key格式:ext:{system}:{method}:{param_hash}


六、降级策略

故障场景 处理方式 用户影响
单个系统不可用 跳过该系统,尝试下一优先级 部分数据缺失,不阻断
所有外部系统不可用 返回缓存数据(如有)+ 明确标注"数据可能过时" 信息可能过时
缓存+外部系统均不可用 返回空结果+告警通知坐席 无法获取外部数据
火绒隔离操作失败 重试1次 → 失败则记录待执行队列 → 告警坐席 安全操作不静默失败

七、配置管理

class ExternalSystemConfig(BaseModel):
    """外部系统连接配置 — 从环境变量或配置中心读取"""
    
    # 联软
    lianruan_base_url: str = "http://192.168.x.x:30098"
    lianruan_api_account: Optional[str] = None
    lianruan_api_password: Optional[str] = None
    
    # 火绒
    huorong_base_url: str = "http://huorong.oa.servyou-it.com:8080"
    huorong_access_key_id: Optional[str] = None
    huorong_access_key_secret: Optional[str] = None
    
    # aTrust
    atrust_base_url: str = "https://atrust.servyou-it.com:4433"
    atrust_api_id: Optional[str] = None
    atrust_api_secret: Optional[str] = None
    atrust_directory_domain: Optional[str] = None
    
    # eHR
    ehr_base_url: Optional[str] = None
    ehr_client_id: Optional[str] = None
    ehr_client_secret: Optional[str] = None
    
    # 全局
    cache_enabled: bool = True
    mock_mode: bool = False  # True时所有请求走MockAdapter

八、目录结构

backend/app/services/external/
├── __init__.py           # 模块导出
├── base.py               # 抽象基类 ExternalSystemAdapter + 数据模型
├── config.py             # 配置管理 ExternalSystemConfig
├── cache.py              # 缓存装饰器和策略
├── mock.py               # MockAdapter(开发期使用)
├── lianruan_adapter.py   # 联软适配器
├── huorong_adapter.py    # 火绒适配器
├── atrust_adapter.py     # aTrust适配器
├── ehr_adapter.py        # eHR适配器
└── service.py            # ExternalSystemService 统一门面

九、实施路径

阶段 内容 依赖
Step 1 base.py + config.py + mock.py + service.py + cache.py 无,立即可做
Step 2 huorong_adapter.py 凭证现在可拿
Step 3 lianruan_adapter.py 凭证明天可拿
Step 4 atrust_adapter.py 凭证约一周
Step 5 ehr_adapter.py 待对接HR团队

十、与项目阶段的对应关系

项目阶段 Adapter用途 对接系统
阶段一(1C) 不使用 — MVP只跑会话管理
阶段二(2B) 联软终端查询 + 火绒安全状态 联软+火绒
阶段二(2C) 火绒漏洞/病毒/隔离 火绒
阶段三(3B) aTrust VPN数据 + AI混合排查 aTrust
阶段三(3C) eHR员工信息 + 标注体系 eHR