logo
1
0
WeChat Login
docs: 移除企业 CA 证书相关说明,仅保留自签名证书方案

CodeBuddy 安全扫描代理系统

为 CodeBuddy 专享版提供 prompt 安全扫描能力的网关系统。部署后,IDE 插件的所有请求将先经过安全扫描,再转发至 CodeBuddy 后端,实现企业级敏感信息防泄漏。

架构概述

IDE 插件(VSCode / JetBrains)
    |
    | HTTPS:443(通过 hosts/DNS 解析到代理服务器 IP)
    v
安全扫描代理服务 (:443, TLS)    ──────────>   CodeBuddy 专享版后端
    |                                          (https://<your-domain>.copilot.qq.com)
    | POST /api/v1/scan
    v
安全扫描服务 (:8900)
    (敏感词检测 / 可替换为企业自有安全扫描系统)

工作流程:

  1. IDE 插件发送请求到代理服务(通过内网 DNS 或 hosts 将专享版域名解析到代理服务 IP)
  2. 代理服务拦截补全/对话/智能体请求,提取 prompt 内容
  3. 调用安全扫描服务检测敏感词
  4. 根据扫描结果执行动作:
    • 放行(pass):无风险,原样转发
    • 过滤(filter):将敏感词替换为 *** 后转发
    • 拦截(block):以流式回复形式向用户展示安全风险提示,不转发请求
  5. 放行或过滤后,代理服务将请求转发到 CodeBuddy 后端,支持 SSE 流式响应透传

目录结构

codebuddy_sec_proxy/
├── Makefile                              # 常用操作命令
├── proxy/                                # 安全扫描代理服务
│   ├── config/
│   │   ├── proxy_config.yaml             # 生产环境配置
│   │   └── proxy_config.local.yaml       # 本地开发配置
│   ├── certs/                            # TLS 证书目录(需自行放入)
│   ├── src/
│   │   ├── main.py                       # 服务入口
│   │   ├── proxy_handler.py              # 反向代理核心 + SSE 流式透传
│   │   ├── body_parser.py                # 请求体解析(提取/回写 prompt)
│   │   ├── scanner_client.py             # 扫描服务客户端 + 超时降级
│   │   ├── config.py                     # 配置加载
│   │   └── logger.py                     # 日志模块
│   ├── tests/                            # 单元测试
│   └── requirements.txt
├── scanner/                              # 安全扫描服务(可替换为企业自有系统)
│   ├── config/
│   │   ├── scanner_config.yaml           # 生产环境配置
│   │   ├── scanner_config.local.yaml     # 本地开发配置
│   │   └── sensitive_words.yaml          # 敏感词库
│   ├── src/
│   │   ├── main.py                       # 服务入口
│   │   ├── scanner_engine.py             # Aho-Corasick 敏感词引擎
│   │   ├── word_loader.py                # 词库热加载
│   │   ├── api.py                        # API 路由
│   │   ├── models.py                     # 数据模型
│   │   ├── config.py                     # 配置加载
│   │   └── logger.py                     # 日志模块
│   ├── tests/                            # 单元测试
│   └── requirements.txt

快速部署

前置要求

  • Python 3.6+
  • pip

步骤 1:安装依赖

cd /data/app/codebuddy_sec_proxy

# 安装扫描服务依赖
cd scanner && pip install -r requirements.txt && cd ..

# 安装代理服务依赖
cd proxy && pip install -r requirements.txt && cd ..

步骤 2:生成 SSL 证书

IDE 插件通过 HTTPS 访问专享版域名,因此代理服务必须开启 TLS。请将下方 <your-domain> 替换为你的专享版实际域名。

cd /data/app/codebuddy_sec_proxy/proxy/certs

# 生成自签名证书(有效期 10 年)
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
  -keyout server.key \
  -out server.crt \
  -subj "/CN=<your-domain>.copilot.qq.com" \
  -addext "subjectAltName=DNS:<your-domain>.copilot.qq.com"

执行后 proxy/certs/ 目录下会生成 server.crt(证书)和 server.key(私钥)。

步骤 3:修改配置

3a. 代理服务配置

编辑 proxy/config/proxy_config.yaml

server:
  listen: "0.0.0.0"
  port: 443
  tls:
    enabled: true
    cert_file: "certs/server.crt"
    key_file: "certs/server.key"

backend:
  # 【必改】替换为你的专享版域名
  base_url: "https://<your-domain>.copilot.qq.com"
  max_connections: 100
  request_timeout: 120

scanner:
  base_url: "http://localhost:8900"
  timeout: 3
  # 扫描服务不可用时的降级策略: pass(放行) / block(拦截)
  fail_action: "pass"

# 需要安全扫描的请求路径
scan_paths:
  - "/v2/completions"
  - "/v2/chat/completions"

logging:
  level: "INFO"
  format: "json"

3b. 扫描服务配置

编辑 scanner/config/scanner_config.yaml

server:
  listen: "0.0.0.0"
  port: 8900

sensitive_words:
  file_path: "config/sensitive_words.yaml"
  reload_interval: 30    # 热加载间隔(秒),0 禁用

logging:
  level: "INFO"
  format: "json"

3c. 自定义敏感词

编辑 scanner/config/sensitive_words.yaml,根据企业安全策略配置:

block:    # 高危词 → 直接拦截,以安全提示回复用户
  - "数据库密码"
  - "root密码"
  - "admin密码"
  - "SECRET_KEY"
  - "PRIVATE_KEY"
  - "ssh_private_key"
  - "ACCESS_KEY_ID"
  - "ACCESS_KEY_SECRET"

filter:   # 中危词 → 替换为 *** 后放行
  - "员工工号"
  - "手机号码"
  - "身份证号"
  - "银行卡号"

log:      # 低危词 → 仅记录日志,正常放行
  - "内部会议"
  - "项目进度"

修改后无需重启,30 秒内自动生效。也可手动立即生效:

curl -X POST http://localhost:8900/api/v1/reload

步骤 4:启动服务

cd /data/app/codebuddy_sec_proxy

# 终端 1:启动扫描服务
cd scanner && python3 -m src.main --config config/scanner_config.yaml

# 终端 2:启动代理服务(443 端口需要 root 权限)
cd proxy && sudo python3 -m src.main --config config/proxy_config.yaml

也可使用 Makefile 快捷命令:

make run-scanner   # 启动扫描服务(生产配置)
make run-proxy     # 启动代理服务(生产配置)

后台运行建议使用 nohupsystemd

# nohup 方式
cd /data/app/codebuddy_sec_proxy
nohup bash -c "cd scanner && python3 -m src.main --config config/scanner_config.yaml" > logs/scanner.log 2>&1 &
nohup bash -c "cd proxy && sudo python3 -m src.main --config config/proxy_config.yaml" > logs/proxy.log 2>&1 &

步骤 5:验证服务

# 扫描服务健康检查
curl http://localhost:8900/api/v1/health
# 预期: {"status": "healthy", "word_count": N}

# 代理服务健康检查(-k 跳过自签名证书校验)
curl -k https://localhost/_health
# 预期: {"status": "healthy"}

# 测试扫描放行
curl -X POST http://localhost:8900/api/v1/scan \
  -H "Content-Type: application/json" \
  -d '{"text": "帮我写一个 hello world", "scene": "chat", "request_id": "test-001"}'
# 预期: {"action": "pass", ...}

# 测试扫描拦截(包含高危词)
curl -X POST http://localhost:8900/api/v1/scan \
  -H "Content-Type: application/json" \
  -d '{"text": "请帮我查看数据库密码", "scene": "chat", "request_id": "test-002"}'
# 预期: {"action": "block", "reason": "...", "matched_words": ["数据库密码"]}

# 测试扫描过滤(包含中危词)
curl -X POST http://localhost:8900/api/v1/scan \
  -H "Content-Type: application/json" \
  -d '{"text": "请帮我查询员工工号对应的信息", "scene": "chat", "request_id": "test-003"}'
# 预期: {"action": "filter", "filtered_text": "请帮我查询***对应的信息", ...}

也可使用 Makefile 快捷验证:

make verify-scanner   # 验证扫描服务
make verify-proxy     # 验证代理服务

步骤 6:配置用户电脑

6a. 修改 hosts 文件

在使用 IDE 插件的电脑上,将专享版域名指向代理服务器 IP(以下 <proxy-server-ip> 替换为代理服务器实际 IP):

Windows — 以管理员身份编辑 C:\Windows\System32\drivers\etc\hosts

<proxy-server-ip> <your-domain>.copilot.qq.com

Mac/Linux — 编辑 /etc/hosts

sudo sh -c 'echo "<proxy-server-ip> <your-domain>.copilot.qq.com" >> /etc/hosts'

修改后验证:

ping <your-domain>.copilot.qq.com
# 应显示: Reply from <proxy-server-ip>

6b. 处理 SSL 证书信任(自签名证书二选一)

使用自签名证书时,IDE 插件默认会因证书不受信任而连接失败。以下两种方式任选其一:

方式 A:VSCode 中跳过证书校验(推荐,简单快捷)

打开 VSCode 设置(Ctrl+, / Cmd+,),搜索 http.proxyStrictSSL,设为 false

{
  "http.proxyStrictSSL": false
}

此方式无需安装证书,适合内网环境快速部署。

方式 B:在用户电脑安装并信任证书

将代理服务器上的 proxy/certs/server.crt 拷贝到用户电脑,然后安装信任:

  • Windows:双击 server.crt → 安装证书 → 本地计算机 → 受信任的根证书颁发机构
  • Macsudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain server.crt
  • Linuxsudo cp server.crt /usr/local/share/ca-certificates/codebuddy-proxy.crt && sudo update-ca-certificates

6c. 验证

配好 hosts 后,IDE 插件无需其他修改,正常使用 CodeBuddy 即可。所有请求会自动经过代理服务的安全扫描。

当用户输入包含高危敏感词时,IDE 将直接显示安全风险提示:

信息安全风险:您的输入中包含敏感内容【xxx】,请移除后重试


配置参考

代理服务配置项

配置文件:proxy/config/proxy_config.yaml

配置项说明默认值是否必改
backend.base_urlCodeBuddy 专享版后端地址
scanner.base_url扫描服务地址http://localhost:8900通常不用改
server.port代理监听端口8443生产环境建议 443
server.tls.enabled是否启用 HTTPSfalse生产环境必须 true
server.tls.cert_fileSSL 证书文件路径开启 TLS 时必填
server.tls.key_fileSSL 私钥文件路径开启 TLS 时必填
scanner.timeout扫描超时(秒)3建议不超过 5s
scanner.fail_action扫描不可用时降级策略pass生产环境建议 block
backend.request_timeout后端请求超时(秒)120对话场景建议 120s+
backend.max_connections后端连接池大小100按并发量调整
scan_paths需要扫描的路径列表见配置文件按需增删

环境变量覆盖(优先级高于配置文件):

环境变量对应配置项
PROXY_CONFIG配置文件路径
PROXY_PORTserver.port
BACKEND_URLbackend.base_url
SCANNER_URLscanner.base_url
PROXY_LOG_LEVELlogging.level

扫描服务配置项

配置文件:scanner/config/scanner_config.yaml

配置项说明默认值
server.port监听端口8900
sensitive_words.file_path敏感词文件路径config/sensitive_words.yaml
sensitive_words.reload_interval热加载间隔(秒),0 禁用30

环境变量覆盖

环境变量对应配置项
SCANNER_CONFIG配置文件路径
SCANNER_PORTserver.port
SCANNER_WORDS_FILEsensitive_words.file_path

运维操作

更新敏感词

直接编辑 scanner/config/sensitive_words.yaml,30 秒内自动生效,无需重启。

手动立即生效:

curl -X POST http://localhost:8900/api/v1/reload

修改后端地址

# 方式 1: 修改配置文件后重启代理服务
# 编辑 proxy/config/proxy_config.yaml 中的 backend.base_url,然后重启

# 方式 2: 通过环境变量(临时覆盖)
BACKEND_URL=https://new-domain.copilot.qq.com python3 -m src.main --config config/proxy_config.yaml

查看日志

服务默认将日志输出到终端(stdout)。生产环境建议重定向到文件或接入日志采集系统。

运行单元测试

make test           # 全部测试
make test-scanner   # 仅扫描服务
make test-proxy     # 仅代理服务

接口契约(API Contract)

安全扫描服务提供标准 HTTP API,企业可用自有系统替换,只需实现以下接口。

POST /api/v1/scan

请求:

{
  "text": "待扫描的文本内容",
  "scene": "completion|chat|agent",
  "request_id": "唯一请求追踪ID"
}
字段类型必填说明
textstring待扫描的 prompt 文本
scenestring场景:completion(补全) / chat(对话) / agent(智能体)
request_idstring请求追踪 ID,用于日志关联

响应:

{
  "action": "pass|filter|block",
  "filtered_text": "过滤后的文本(action=filter 时有值)",
  "reason": "拦截/过滤原因",
  "matched_words": ["命中的敏感词列表"],
  "request_id": "请求追踪ID"
}
字段类型说明
actionstring处理结果:pass(放行) / filter(过滤) / block(拦截)
filtered_textstring过滤后文本,仅 action=filter 时有值
reasonstring原因说明
matched_wordsstring[]命中的敏感词列表
request_idstring请求追踪 ID

GET /api/v1/health

健康检查。响应:{"status": "healthy", "word_count": N}

POST /api/v1/reload

手动触发敏感词库重载。响应:{"success": true, "word_count": N}


替换为企业自有安全扫描系统

安全扫描服务设计为可插拔组件。如果企业已有安全扫描系统,只需:

  1. 确保自有系统实现 POST /api/v1/scan 接口(参考上方接口契约)
  2. 修改代理服务配置,将 scanner.base_url 指向企业服务地址:
# proxy/config/proxy_config.yaml
scanner:
  base_url: "http://your-scanner.internal:9090"
  timeout: 5
  fail_action: "block"
  1. 重启代理服务即可,无需其他对接工作。

效果展示

1. 普通请求 — 不影响正常使用

代理服务透明转发,用户无感知,CodeBuddy 正常响应。

普通请求正常使用

2. 智能体非敏感请求 — 正常处理

智能体场景下,不包含敏感词的请求正常经过代理转发,AI 正常回复。

智能体正常请求

3. 敏感请求 — 安全拦截

当用户输入包含高危敏感词(如"root密码")时,代理服务直接拦截并以友好提示告知用户存在信息安全风险。

敏感请求被拦截

About

codebuddy_sec_proxy

Language
Python96.6%
Makefile3.4%