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(默认)或jumpstream.window: 窗口大小(chunk 数量),指“模拟一批送检多少”(per_index/jump都使用;默认100)stream.delays.*: 模拟延迟,支持50ms/1s等time.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_index,window=100,detect=50ms,其余延迟默认0ms)。
- 默认使用
所有默认结果/动作都可通过 WithDefaultResult / WithDefaultAction 覆盖;也可以通过配置文件中每条 rule 的 response.action / response.message 控制 unsafe 的动作与提示,并用 response_rules[].stream 控制流式 DetectResult 的返回节奏。