跳到主要内容

CyberGuard Mock

CyberGuard Mock 用于本地或测试环境模拟 CyberGuard 服务,便于验证 guard 插件的检测逻辑。

它基于 Connect server(支持 Connect/gRPC/gRPC-Web),默认使用 h2c(未加密 HTTP/2)。

独立运行(本地联调)

go run ./test/cmd/cyberguard-mock -addr 127.0.0.1:8089

启动后将输出监听地址,例如:

cyberguard mock listening at http://127.0.0.1:8089

在 Gateway 的静态配置或动态配置中,将 Guard 的 check_service_url 指向这个地址即可:

plugins:
guard:
check_service_url: http://127.0.0.1:8089

更多 Guard 配置说明见 Guard

使用配置文件(推荐)

支持通过配置文件定义 mock 规则(YAML/JSON):

go run ./test/cmd/cyberguard-mock -addr 127.0.0.1:8089 -config ./test/mock/cyberguard/config.example.yaml

示例配置文件见 test/mock/cyberguard/config.example.yaml,可按需拷贝修改。

配置项说明

下面是常用字段(均为字符串包含匹配):

  • chat_completion.request_rules[]

    • match.contains[]:任意消息内容包含任一关键词即命中;为空表示匹配所有(可选)。
    • response.result: safe|unsafe(默认 safe
    • response.action: pass|alert|override|block(对应 Guard action 枚举;默认:safe→pass,unsafe→block)
    • response.message: unsafe 时返回的提示文案(可选)
    • response.override_id: override 动作的 id(可选)
  • chat_completion.response_rules[]

    • match.contains[]:流式/非流式响应内容包含任一关键词即命中;为空表示匹配所有(可选)。
    • response.*:同 request_rules[]
    • stream:仅影响 ChatCompletionStream 的 DetectResult 返回节奏(可选;未配置则使用默认参数)。
      • stream.mode: per_index(默认)或 jump
      • stream.window: 窗口大小(chunk 数量),指“模拟一批送检多少”(per_index/jump 都使用;默认 100
      • stream.delays.*: 模拟延迟,支持 50ms/1stime.ParseDuration 格式,也支持整数毫秒
        • detect: 模拟一次“批检测/窗口检测”本身耗时(窗口=window;默认 50ms
          • 实际返回前的总等待时间约为:detect + <对应阶段的延迟>
        • first: 首次检测完成以后,再延迟多久返回 DetectResult(默认 0ms
        • per_index: per_index 模式下,每次检测完成以后,再延迟多久返回(默认 0ms
        • window: jump 模式下,每次窗口检测完成以后,再延迟多久返回(默认 0ms
        • eom: 收到 EOM 后,最终一次检测完成以后,再延迟多久返回(默认 0ms
  • embeddings.rules[]

    • match.contains[]:每个 input 字符串命中关键词则该条结果为 unsafe;为空表示匹配所有(可选)。
    • response.*:同 request_rules[]

规则按数组顺序匹配(命中第一个就返回)。为了保证“未配置/未命中时默认 pass”,从配置文件加载时 mock 会在每个 rules 列表末尾自动追加一个 safe + pass 的匹配所有规则,因此你通常只需要写需要拦截的规则即可。

如果想统一控制流式 DetectResult 的返回节奏,建议把 stream 配在 chat_completion.response_rules[] 的最后一个“匹配所有”规则上(contains: [])。

测试中使用(按需启动)

在 Go 测试里可以直接启动 mock server,测试结束自动回收:

import (
"testing"

cyberguardmock "aidy/test/mock/cyberguard"
)

func TestGuardWithMock(t *testing.T) {
server := cyberguardmock.StartTest(t)
// server.URL 用作 guard.check_service_url
_ = server.URL
}

测试里加载配置文件

cfg, err := cyberguardmock.LoadFileConfig("./test/mock/cyberguard/config.example.yaml")
if err != nil {
t.Fatal(err)
}

server := cyberguardmock.StartTest(t, cyberguardmock.WithFileConfig(cfg))
_ = server.URL

测试里动态自定义返回

server := cyberguardmock.StartTest(t, cyberguardmock.WithChatCompletionFunc(
func(ctx context.Context, req *guardpbv3.ChatCompletionRequest) (*guardpbv3.ChatCompletionResponse, error) {
_ = ctx
_ = req
return cyberguardmock.SafeChatCompletionResponse(), nil
},
))
_ = server.URL

行为与优先级

当同时配置了多种方式时,mock 会按以下优先级处理(越靠前优先级越高):

1) With*Func(完全自定义) 2) With*Response(静态指定响应) 3) 配置文件规则(如 chat_completion.request_rules[] / chat_completion.response_rules[] / embeddings.rules[]) 4) 默认行为(safe + pass)

默认行为

  • Health:返回 STATUS_READY
  • ChatCompletion:返回 safe + pass。
  • CheckEmbeddings:返回与 input 数量一致的结果(至少 1 条),默认 safe + pass;可用 embeddings.rules[] 覆盖为 unsafe。
  • ChatCompletionStream
    • 默认使用 per_index:按 window 聚合成“批”送检;每完成一批检测后,对该批内每个 chunk.index 返回一条 safe DetectResult。
    • jump:当收到 2*window 个 chunk 时返回前 window 的检测成功(checked_index 为前半段最后一个 index),EOM 时补齐剩余(checked_index=最后一次 chunk.index)。
    • 若匹配到的 response_rules[] 未配置 stream,则使用默认参数(mode=per_indexwindow=100detect=50ms,其余延迟默认 0ms)。

所有默认结果/动作都可通过 WithDefaultResult / WithDefaultAction 覆盖;也可以通过配置文件中每条 rule 的 response.action / response.message 控制 unsafe 的动作与提示,并用 response_rules[].stream 控制流式 DetectResult 的返回节奏。