Skip to content
15 changes: 7 additions & 8 deletions .flocks/plugins/tools/api/sangfor_xdr/_provider.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,11 @@ credential_fields:
input_type: text
required: false
default: "443"
- key: verify_ssl
label: Verify SSL
storage: config
config_key: verify_ssl
input_type: text
required: false
default: "false"
# NOTE: ``verify_ssl`` was previously declared here as a free-text
# credential field, which duplicated the generic "SSL 验证" toggle that
# ServiceDetailPanel renders for every API service (both write to the
# same ``raw_config["verify_ssl"]`` key). The duplicate text input has
# been removed — use the toggle below the credential form instead.
defaults:
timeout: 60
category: custom
Expand All @@ -52,4 +50,5 @@ notes: |
3. 将联动码填入 Auth Code 字段
4. 联动码内部包含 AK/SK,Handler 会自动解密并使用 HMAC-SHA256 签名
5. 签名完成后不可修改请求的任何内容
6. 内网部署环境可将 Verify SSL 设为 false
6. 内网部署环境请通过下方『SSL 验证』开关关闭证书校验
(与原 Verify SSL 输入框等价,已统一收敛到通用开关)
258 changes: 204 additions & 54 deletions .flocks/plugins/tools/api/sangfor_xdr/sangfor_xdr.handler.py

Large diffs are not rendered by default.

23 changes: 13 additions & 10 deletions .flocks/plugins/tools/api/sangfor_xdr/sangfor_xdr_alerts.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
name: sangfor_xdr_alerts
description: >
Manage Sangfor XDR security alerts. Query alerts by time range,
update alert disposition status, retrieve alert proof/evidence,
and view alert details. Essential for security incident triage.
update alert disposition status, and retrieve alert proof/evidence.
Essential for security incident triage.
description_cn: >
管理深信服 XDR 安全告警。支持按时间范围查询告警列表、
批量修改告警处置状态、获取告警举证信息和告警详情。
适用于安全事件分诊和告警运营。
批量修改告警处置状态、获取告警举证信息。适用于安全事件分诊和告警运营。
(注:标准开放接口列表中没有 alerts/:uuid/detail,告警详情请使用 list
并按 uuId 过滤获取。)
category: custom
enabled: true
requires_confirmation: false
Expand All @@ -21,10 +22,10 @@ inputSchema:
告警操作类型:
- `list` :查询安全告警列表(按时间范围分页查询)
- `update_status` :批量修改告警处置状态
- `status_list` :查询告警处置状态枚举列表
- `get_proof` :根据告警 UUID 获取举证信息
- `get_detail` :根据告警 UUID 获取告警详情
enum: [list, update_status, status_list, get_proof, get_detail]
- `status_list` :根据告警 UUID 数组批量查询告警当前处置状态
(POST /alerts/dealstatus/list,body 为 `["alert-uuid1", ...]`)
- `get_proof` :根据告警 UUID 获取举证信息(GET /alerts/:uuid/proof)
enum: [list, update_status, status_list, get_proof]
default: list
start_time:
type: integer
Expand All @@ -44,10 +45,12 @@ inputSchema:
default: 1
uuid:
type: string
description: 告警唯一ID(get_proof / get_detail 时必填)。
description: 告警唯一ID(get_proof 时必填)。
uuids:
type: array
description: 告警 UUID 数组(update_status 时必填)。
description: >
告警 UUID 数组(update_status 必填;status_list 时为查询主体,
留空则发送 `[]`,部分 XDR 版本会返回"参数不合法",建议显式提供至少一个 UUID)。
items:
type: string
deal_status:
Expand Down
18 changes: 11 additions & 7 deletions .flocks/plugins/tools/api/sangfor_xdr/sangfor_xdr_incidents.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ description_cn: >
管理深信服 XDR 安全事件。支持按时间范围查询事件列表、
批量修改事件处置状态、获取事件举证信息,以及查询事件关联实体
(主机、内外网IP、文件、进程、DNS),是安全事件响应的核心工具。
(注:标准开放接口列表中没有 incidents/:uuid/detail,事件详情请使用 list
并按 uuId 过滤获取。)
category: custom
enabled: true
requires_confirmation: false
Expand All @@ -21,11 +23,11 @@ inputSchema:
事件操作类型:
- `list` :查询安全事件列表
- `update_status` :批量修改事件处置状态
- `status_list` :查询事件处置状态枚举列表
- `get_proof` :根据事件 UUID 获取举证信息
- `get_entities` :根据事件 UUID 获取处置实体(需指定 entity_type
- `get_detail` :根据事件 UUID 获取事件详情
enum: [list, update_status, status_list, get_proof, get_entities, get_detail]
- `status_list` :根据事件 UUID 数组批量查询事件当前处置状态
(POST /incidents/dealstatus/list,body 为 `["incident-uuid1", ...]`)
- `get_proof` :根据事件 UUID 获取举证信息(GET /incidents/:uuid/proof
- `get_entities` :根据事件 UUID 获取处置实体(GET /incidents/:uuid/entities/{type},需指定 entity_type)
enum: [list, update_status, status_list, get_proof, get_entities]
default: list
start_time:
type: integer
Expand All @@ -43,10 +45,12 @@ inputSchema:
default: 1
uuid:
type: string
description: 事件唯一ID(get_proof / get_entities / get_detail 时必填)。
description: 事件唯一ID(get_proof / get_entities 时必填)。
uuids:
type: array
description: 事件 UUID 数组(update_status 时必填)。
description: >
事件 UUID 数组(update_status 必填;status_list 时为查询主体,
留空则发送 `[]`,部分 XDR 版本会返回"参数不合法",建议显式提供至少一个 UUID)。
items:
type: string
deal_status:
Expand Down
11 changes: 10 additions & 1 deletion .flocks/plugins/tools/api/sangfor_xdr/sangfor_xdr_vulns.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ inputSchema:
description: >
脆弱性操作类型:
- `baseline` :获取基线合规数据
- `vuln_list` :获取漏洞列表
- `vuln_list` :获取漏洞、弱密码数据(POST /vuls/risk/list)
- `update_status` :修改漏洞修复状态
- `source_device` :获取数据源设备列表
enum: [baseline, vuln_list, update_status, source_device]
Expand All @@ -32,6 +32,15 @@ inputSchema:
type: integer
description: 页码,从 1 开始。
default: 1
data_type:
type: string
description: >
脆弱性类型(vuln_list 时使用,spec 中此字段为唯一必填项;
缺失会触发"请求参数校验失败"):
- `loophole` :漏洞数据(默认)
- `weakpwd` :弱密码数据
enum: [loophole, weakpwd]
default: loophole
ids:
type: array
description: 漏洞 ID 列表(update_status 时使用)。
Expand Down
49 changes: 48 additions & 1 deletion flocks/tool/tool_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import ast
import importlib.util
import inspect
import re
import urllib.parse
from pathlib import Path
Expand Down Expand Up @@ -395,8 +396,54 @@ def _build_script_handler(cfg: dict, yaml_path: Path) -> ToolHandler:
if not callable(fn):
raise TypeError(f"'{function_name}' in {script_path} is not callable")

# Inspect the target function signature once so the wrapper can adapt the
# invocation to legacy handlers that either:
# * read parameters from ``ctx.params`` (signature: ``(ctx) -> ...``); or
# * take parameters as explicit keyword arguments / ``**kwargs``.
#
# Without this adaptation, callers like the test-credentials flow that
# invoke ``ToolRegistry.execute(tool_name, **params)`` would either raise
# ``TypeError: got an unexpected keyword argument`` or
# ``AttributeError: 'ToolContext' object has no attribute 'params'``.
fn_sig = inspect.signature(fn)
fn_params = fn_sig.parameters
fn_has_var_kw = any(
p.kind == inspect.Parameter.VAR_KEYWORD for p in fn_params.values()
)
# Skip the first positional argument (always the ``ctx`` we supply
# ourselves) so a user-provided kwarg named ``ctx`` cannot trigger
# ``TypeError: got multiple values for argument 'ctx'``.
_param_items = list(fn_params.items())
if _param_items and _param_items[0][1].kind in (
inspect.Parameter.POSITIONAL_OR_KEYWORD,
inspect.Parameter.POSITIONAL_ONLY,
):
_param_items = _param_items[1:]
fn_param_names = {
name
for name, p in _param_items
if p.kind
in (
inspect.Parameter.POSITIONAL_OR_KEYWORD,
inspect.Parameter.KEYWORD_ONLY,
)
}

async def handler(ctx: ToolContext, **kwargs: Any) -> ToolResult:
result = await fn(ctx, **kwargs)
# Always expose the raw kwargs on the context so handlers that read
# from ``ctx.params`` (e.g. ``params = dict(ctx.params)``) keep working
# regardless of whether the caller created a fresh ``ToolContext``.
try:
ctx.params = kwargs # type: ignore[attr-defined]
except AttributeError:
pass

if fn_has_var_kw:
call_kwargs = kwargs
else:
call_kwargs = {k: v for k, v in kwargs.items() if k in fn_param_names}

result = await fn(ctx, **call_kwargs)
if isinstance(result, ToolResult):
return result
return ToolResult(success=True, output=result)
Expand Down
Loading
Loading