Files
wecom_it_smart_desk/backend/app/integrations/huorong/models.py
T

374 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# 企微IT智能服务台 — 火绒集成数据模型
# =============================================================================
# 说明:火绒API请求/响应的 Pydantic 数据模型
# 包含:终端信息、漏洞信息、病毒事件、任务下发等
# =============================================================================
from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field, model_validator
# ==========================================================================
# 通用响应模型
# ==========================================================================
class HuorongApiResponse(BaseModel):
"""火绒API统一响应模型。
火绒所有API返回格式一致(官方API文档 v1):
成功时: { "errno": 0, "errmsg": "", "data": { ... } }
失败时: { "errno": 1, "errmsg": "Authentication failed" }
官方错误码定义:
- errno=0: 成功
- errno=1: 认证失败
- errno=2: 参数错误
- errno=3: 服务器内部错误
- errno=4: API未授权
注意:火绒API始终使用 errno(不是 errcode)。
使用 model_validator 在验证前将 errno 归一化为 errcode
保持内部代码统一使用 errcode 字段。
Attributes:
errcode: 错误码,0表示成功(从 errno 归一化而来)
errmsg: 错误描述(成功时为空字符串)
data: 业务数据(成功时非None)
"""
@model_validator(mode='before')
@classmethod
def normalize_error_fields(cls, data: Any) -> Any:
"""将火绒API返回的 errno 字段归一化为 errcode。
火绒API在认证失败等错误场景下返回 errno 而非 errcode
此验证器在 Pydantic 字段校验前将 errno 转换为 errcode
统一后续处理逻辑。
Args:
data: 原始输入数据(通常为dict)
Returns:
归一化后的数据
"""
if isinstance(data, dict) and 'errno' in data and 'errcode' not in data:
data['errcode'] = data.pop('errno')
return data
errcode: int = Field(..., description="错误码,0=成功")
errmsg: str = Field(default="ok", description="错误描述")
data: Optional[Any] = Field(default=None, description="业务数据")
# ==========================================================================
# 终端基本信息 — /api/clnts/_list 返回
# ==========================================================================
class TerminalBasicInfo(BaseModel):
"""终端基本信息(_list 接口返回的每条记录)。
字段名严格按照火绒API文档实际返回值定义。
注意:API返回的字段名与之前猜测不同,已根据官方文档修正。
Attributes:
id: 内部数据库ID
client_id: 终端唯一ID(40位十六进制字符串,用于所有任务下发)
client_name: 客户端名称
computer_name: 计算机名
local_ip: 本地IP
connect_ip: 连接IP(客户端连接控制中心使用的IP)
mac: MAC地址
group_id: 分组ID
os_version: 操作系统版本
version: 火绒客户端版本
definitions: 病毒库更新时间
is_online: 在线状态
last_connect_time: 最后连接时间(Unix时间戳)
last_seen_time: 最后可见时间(Unix时间戳)
first_appear_time: 首次出现时间(Unix时间戳)
"""
id: Optional[int] = Field(default=None, description="内部数据库ID")
client_id: str = Field(..., description="终端唯一ID")
client_name: str = Field(default="", description="客户端名称")
computer_name: str = Field(default="", description="计算机名")
local_ip: str = Field(default="", description="本地IP")
connect_ip: str = Field(default="", description="连接IP")
mac: str = Field(default="", description="MAC地址")
group_id: Optional[Any] = Field(default=None, description="分组IDint或str")
os_version: str = Field(default="", description="操作系统版本")
version: str = Field(default="", description="火绒客户端版本")
definitions: str = Field(default="", description="病毒库更新时间")
is_online: bool = Field(default=False, description="在线状态")
last_connect_time: Optional[int] = Field(default=None, description="最后连接时间")
last_seen_time: Optional[int] = Field(default=None, description="最后可见时间")
first_appear_time: Optional[int] = Field(default=None, description="首次出现时间")
class TerminalListRequest(BaseModel):
"""终端列表查询请求。
Attributes:
group_id: 分组ID(可选,不传则查全部分组)
page: 页码(从1开始)
per_page: 每页条数
"""
group_id: Optional[str] = Field(default=None, description="分组ID")
page: int = Field(default=1, ge=1, description="页码")
per_page: int = Field(default=20, ge=1, le=100, description="每页条数")
# ==========================================================================
# 终端详细信息v2 — /api/clnts/_info2 返回
# ==========================================================================
class HardwareInfo(BaseModel):
"""终端硬件信息。
Attributes:
cpu: CPU信息
memory: 内存信息
disk: 磁盘信息
motherboard: 主板信息
network_card: 网卡信息
"""
cpu: str = Field(default="", description="CPU信息")
memory: str = Field(default="", description="内存信息")
disk: str = Field(default="", description="磁盘信息")
motherboard: str = Field(default="", description="主板信息")
network_card: str = Field(default="", description="网卡信息")
class SoftwareInfo(BaseModel):
"""已安装软件条目。
Attributes:
name: 软件名称
version: 版本号
publisher: 发布者
"""
name: str = Field(default="", description="软件名称")
version: str = Field(default="", description="版本号")
publisher: str = Field(default="", description="发布者")
class AssetInfo(BaseModel):
"""资产信息。
Attributes:
asset_tag: 资产标签
serial_number: 序列号
"""
asset_tag: str = Field(default="", description="资产标签")
serial_number: str = Field(default="", description="序列号")
class NetworkConfig(BaseModel):
"""网络配置信息。
Attributes:
ip: IP地址
gateway: 网关
dns: DNS服务器
adapter_info: 网卡适配器信息
"""
ip: str = Field(default="", description="IP地址")
gateway: str = Field(default="", description="网关")
dns: str = Field(default="", description="DNS服务器")
adapter_info: str = Field(default="", description="网卡适配器信息")
class TerminalDetailV2(BaseModel):
"""终端详细信息v2(_info2 接口返回)。
通过 optional_fields 参数指定需要返回的信息块:
- hardware: 硬件信息
- software: 已安装软件
- assets: 资产信息
- netconf: 网络配置
Attributes:
client_id: 终端唯一ID
computer_name: 计算机名
hardware: 硬件信息(可选)
software: 已安装软件列表(可选)
assets: 资产信息(可选)
netconf: 网络配置(可选)
"""
client_id: str = Field(..., description="终端唯一ID")
computer_name: str = Field(default="", description="计算机名")
hardware: Optional[HardwareInfo] = Field(default=None, description="硬件信息")
software: Optional[List[SoftwareInfo]] = Field(default=None, description="已安装软件")
assets: Optional[AssetInfo] = Field(default=None, description="资产信息")
netconf: Optional[NetworkConfig] = Field(default=None, description="网络配置")
class TerminalDetailRequest(BaseModel):
"""终端详细信息查询请求。
Attributes:
client_id: 终端唯一ID
optional_fields: 需要返回的可选信息块列表
"""
client_id: str = Field(..., description="终端唯一ID")
optional_fields: List[str] = Field(
default_factory=lambda: ["hardware", "software", "assets", "netconf"],
description="可选信息块: hardware/software/assets/netconf",
)
# ==========================================================================
# 漏洞信息 — /api/clnts/_leak 返回
# 说明:_leak 接口返回的是"存在高危漏洞未修复的终端列表",
# 每条记录是终端信息(非漏洞详情),API不返回具体漏洞CVE列表。
# 外层还有 all_client(终端总数)和 risk_client(高危终端数)统计。
# ==========================================================================
class TerminalLeakInfo(BaseModel):
"""存在高危漏洞的终端信息(_leak 接口返回的每条记录)。
注意:_leak 返回的是终端维度数据,不是漏洞维度。
字段名严格按照火绒API文档实际返回值定义。
与 _list 接口的字段名不同!
Attributes:
cid: 终端唯一ID_leak 中叫 cid_list 中叫 client_id
hostname: 计算机名(_leak 中叫 hostname_list 中叫 computer_name
client_name: 终端名称
group_name: 分组名称
group_id: 分组ID
ip_addr: 本地IP_leak 中叫 ip_addr_list 中叫 local_ip
call_ip: 连接IP_leak 中叫 call_ip_list 中叫 connect_ip
mac: MAC地址
osver: 操作系统版本(_leak 中叫 osver_list 中叫 os_version
os_type: 终端类型(如 Windows
prodver: 火绒客户端版本(_leak 中叫 prodver_list 中叫 version
virdb: 病毒库版本(Unix时间戳,_leak 中叫 virdb_list 中叫 definitions
stat: 在线状态码(1=离线, 2=在线, 3=异常,_list 中是 is_online 布尔值)
"""
cid: str = Field(..., description="终端唯一ID")
hostname: str = Field(default="", description="计算机名")
client_name: str = Field(default="", description="终端名称")
group_name: str = Field(default="", description="分组名称")
group_id: Optional[Any] = Field(default=None, description="分组ID")
ip_addr: str = Field(default="", description="本地IP")
call_ip: str = Field(default="", description="连接IP")
mac: str = Field(default="", description="MAC地址")
osver: str = Field(default="", description="操作系统版本")
os_type: str = Field(default="", description="终端类型")
prodver: str = Field(default="", description="火绒客户端版本")
virdb: Optional[Any] = Field(default=None, description="病毒库版本(Unix时间戳)")
stat: int = Field(default=1, description="在线状态码: 1=离线 2=在线 3=异常")
# ==========================================================================
# 病毒事件 — /api/clnts/_virus_events 返回
# 说明:_virus_events 返回终端维度的病毒日志统计,
# 含总数(count)和4种处理结果(result)的明细。
# 请求需指定 type: 0=按client_id查, 1=按group_id查, 2=查全部
# ==========================================================================
class VirusHandleResult(BaseModel):
"""病毒事件处理结果统计。
Attributes:
success: 处理成功数
fail: 处理失败数
ignored: 暂不处理数
trusted: 已信任数
"""
success: int = Field(default=0, description="处理成功数")
fail: int = Field(default=0, description="处理失败数")
ignored: int = Field(default=0, description="暂不处理数")
trusted: int = Field(default=0, description="已信任数")
class VirusEventStats(BaseModel):
"""终端病毒事件统计(_virus_events 接口返回的每条记录)。
字段名严格按照火绒API文档实际返回值定义。
与 _list 接口的字段名基本一致。
Attributes:
group_id: 分组ID
client_id: 终端唯一ID
client_name: 终端名称
computer_name: 计算机名
local_ip: 本地IP
connect_ip: 连接IP
mac: MAC地址
count: 病毒日志总数
result: 处理结果统计(success/fail/ignored/trusted
"""
group_id: Optional[Any] = Field(default=None, description="分组ID")
client_id: str = Field(..., description="终端唯一ID")
client_name: str = Field(default="", description="终端名称")
computer_name: str = Field(default="", description="计算机名")
local_ip: str = Field(default="", description="本地IP")
connect_ip: str = Field(default="", description="连接IP")
mac: str = Field(default="", description="MAC地址")
count: int = Field(default=0, description="病毒日志总数")
result: Optional[VirusHandleResult] = Field(default=None, description="处理结果统计")
# ==========================================================================
# 终端任务 — /api/task/_create
# ==========================================================================
class TaskCreateRequest(BaseModel):
"""终端任务创建请求。
支持的任务类型:
- quick_scan: 快速扫描
- full_scan: 全盘扫描
- custom_scan: 自定义扫描
- netctrl: 终端隔离/解除
- message: 发送通知
Attributes:
task_type: 任务类型
client_ids: 目标终端ID列表
net_isolation: 是否隔离(仅 netctrl 类型有效)
message_content: 通知内容(仅 message 类型有效)
"""
task_type: str = Field(..., description="任务类型: quick_scan/full_scan/custom_scan/netctrl/message")
client_ids: List[str] = Field(..., min_length=1, description="目标终端ID列表")
net_isolation: Optional[bool] = Field(default=None, description="是否隔离(仅netctrl类型)")
message_content: Optional[str] = Field(default=None, description="通知内容(仅message类型)")
# ==========================================================================
# 终端安全画像(聚合模型,供前端直接使用)
# ==========================================================================
class TerminalSecurityProfile(BaseModel):
"""终端安全画像(聚合模型)。
将终端基本信息+安全状态聚合成一个模型,供坐席端直接展示。
Attributes:
client_id: 终端唯一ID
computer_name: 计算机名
ip: 本地IP
mac: MAC地址
os_version: 操作系统版本
is_online: 在线状态
group_name: 分组名称
hardware: 硬件概要
high_risk_leaks: 高危漏洞数
uncleaned_virus: 未处理病毒事件数
security_score: 安全评分(0-100,综合漏洞+病毒+在线状态)
"""
client_id: str = Field(..., description="终端唯一ID")
computer_name: str = Field(default="", description="计算机名")
ip: str = Field(default="", description="本地IP")
mac: str = Field(default="", description="MAC地址")
os_version: str = Field(default="", description="操作系统版本")
is_online: bool = Field(default=False, description="在线状态")
group_name: str = Field(default="", description="分组名称")
hardware: Optional[HardwareInfo] = Field(default=None, description="硬件概要")
high_risk_leaks: int = Field(default=0, description="高危漏洞数")
uncleaned_virus: int = Field(default=0, description="未处理病毒事件数")
security_score: int = Field(default=100, description="安全评分(0-100)")