logo
0
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密码")时,代理服务直接拦截并以友好提示告知用户存在信息安全风险。

敏感请求被拦截