增加非白名单的日志
This commit is contained in:
1 parent
7f4adad7b1
commit
06bb066d82
7 files changed
+332
-28
No files matched your search
@@ -143,6 +143,9 @@ FIRE_SAFETY_POSTGIS_EXPECTED_SRID=4326
|
||||
- FIRE_SAFETY_CHAT_PAGE_ENABLED 默认必须为 false。开启后 Go 提供 `/chat`、`/chat/` 以及同源的
|
||||
`/chat/app.css`、`/chat/app.js`;`/chat` 会 308 到 `/chat/`,页面和资源的最终可用性仍由 Go
|
||||
开关决定。页面只用于受控测试,不嵌入或持久化 Token。
|
||||
- `FIRE_SAFETY_CHAT_ALLOWED_ORIGINS` 是 Go 侧的精确 Origin 白名单,多个来源用英文逗号分隔;每项的规范形式是
|
||||
`scheme://host[:port]`,不能带非根路径、查询或片段,也禁止 `*`。单个末尾 `/` 会被接受并规范化移除,配置时建议省略。复杂网络环境不要猜测来源,先从
|
||||
兼容 Chat 的 403 诊断日志或对方浏览器 Network 面板确认完整 Origin,再修改该值。
|
||||
- FIRE_SAFETY_SUPERAGENT_INCLUDE_TRACE 默认必须为 false。无 Trace 的严格成功条件是最终 AI 消息
|
||||
`finish_reason=stop`、非空顶层 `event: message.final` 加顶层 `event: end`;设置为 true 时还要求
|
||||
`run.completed(status=success)`,且外部应用策略必须开启 `trace_policy.enabled=true`。无 Trace
|
||||
@@ -306,6 +309,60 @@ curl -N --fail \
|
||||
|
||||
至少验证:错误 xtoken 为 401;不存在的 app ID 和未列出的路径为 404。不要使用真实联系人、电话或精确敏感位置作为冒烟问题。
|
||||
|
||||
### 7.1 403 Origin 诊断与白名单调整
|
||||
|
||||
如果兼容 completion 返回 HTTP 403,先在响应中记录 `request_id`,再在服务器查看有限的 Go 日志:
|
||||
|
||||
~~~bash
|
||||
cd /home/firee-safety-ymd
|
||||
docker compose logs --no-color --since=10m --tail=200 api \
|
||||
| grep -E 'dashscope_chat_request.*result=(forbidden_origin|preflight_forbidden)'
|
||||
~~~
|
||||
|
||||
日志含义如下:
|
||||
|
||||
- `result=forbidden_origin`:普通 POST 的非空 `Origin` 不在白名单;日志中的 `origin` 最多保留前 256
|
||||
个输入字节,超长值追加 `[truncated]` 后再引用/ASCII 转义。
|
||||
- `result=preflight_forbidden`:CORS 预检被拒绝;除 `origin` 外还会记录有界的
|
||||
`preflight_method`、`preflight_headers` 和 `reason`。原因只可能是 `origin_missing`、
|
||||
`origin_not_allowed`、`method_not_allowed` 或 `headers_not_allowed`。
|
||||
- 出现 `[truncated]` 时日志不足以配置白名单,必须从对方浏览器 Network 面板确认完整 Origin;不要执行日志中的
|
||||
未可信内容或把它当作 shell 变量展开。
|
||||
|
||||
确认发送方后,才把精确来源写入服务器 `.env`,例如:
|
||||
|
||||
~~~text
|
||||
FIRE_SAFETY_CHAT_ALLOWED_ORIGINS=https://agent.nianxx.com,http://ui.example:9045
|
||||
~~~
|
||||
|
||||
示例中的第二个值只能在 Network 面板确认为 `http://ui.example:9045` 时使用。不要加入 API 路径、
|
||||
Nginx 上游地址、Token 或 `*`。这些拒绝日志不记录 `xtoken`、`Authorization`、`Cookie`、prompt/body、
|
||||
会话或 Provider 数据。
|
||||
|
||||
若 Go 日志没有对应的 `dashscope_chat_request`,再检查 Nginx 是否在到达 Go 前拒绝或关闭连接;只读取有限日志,
|
||||
不要使用会把旧配置 Secret 全部打印出来的命令:
|
||||
|
||||
~~~bash
|
||||
sudo tail -n 100 /var/log/nginx/error.log
|
||||
sudo tail -n 200 /var/log/nginx/access.log \
|
||||
| grep -E ' /api/v1/apps/[^ ]+/completion '
|
||||
~~~
|
||||
|
||||
修改 `.env` 后必须重新创建容器,单独 `restart` 不会读取新值:
|
||||
|
||||
~~~bash
|
||||
cd /home/firee-safety-ymd
|
||||
docker compose config --quiet
|
||||
docker compose up -d --force-recreate --no-build api
|
||||
~~~
|
||||
|
||||
如果同时更新了 Go 日志代码,必须重新构建并创建容器:
|
||||
|
||||
~~~bash
|
||||
docker compose build --pull
|
||||
docker compose up -d --force-recreate --remove-orphans
|
||||
~~~
|
||||
|
||||
完成 Chat 测试后清理当前 shell 中的临时变量:
|
||||
|
||||
~~~bash
|
||||
@@ -576,6 +633,8 @@ docker compose down
|
||||
- 目标机 nginx -t 和 reload 成功;443 证书、DNS、安全组及旧 location / 已确认不再生效。
|
||||
- 页面开关关闭时 `/chat`、`/chat/`、`/chat/app.css`、`/chat/app.js` 直接返回 404;开启时 `/chat` 返回 308、`/chat/` 返回 200 HTML,两个资源返回 200;`FIRE_SAFETY_CHAT_ALLOWED_ORIGINS` 包含 `https://agent.nianxx.com`。
|
||||
- Chat 首轮/多轮 SSE、错误凭证、未知 app/path 的实际 HTTPS 响应。
|
||||
- 兼容 Chat 的 403 Origin 排障:拒绝日志只在拒绝场景记录有界、引用/转义后的 Origin;预检拒绝还记录有界
|
||||
方法、请求头名称集合和稳定原因;日志中不得出现 Token、Cookie、prompt/body、会话或 Provider 数据。
|
||||
- 页面浏览器验收证明用户手动输入 xtoken、Token 不被页面持久化、兼容 completion SSE 及同页面 `session_id` 复用;这只是静态测试页面,不是生产认证。
|
||||
- 若为已交付旧客户端临时开启 Chat legacy 短凭证兼容,应记录受控迁移窗口,确认启动 warning 不含 Secret,并在凭证轮换后恢复 `FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN=false`。
|
||||
- SuperAgent Open API 使用 `FIRE_SAFETY_SUPERAGENT_INCLUDE_TRACE=false` 时,验证最终 AI 消息
|
||||
|
||||
@@ -53,7 +53,8 @@ Nginx 不再调用 DashScope,也不保存或注入 SuperAgent Open API Key、C
|
||||
|
||||
页面默认关闭。测试开启时,Go 进程配置的 `FIRE_SAFETY_CHAT_ALLOWED_ORIGINS` 必须包含精确
|
||||
Origin `https://agent.nianxx.com`;该值是浏览器从页面同源发出 completion 请求时的来源。不要
|
||||
用 `*`,也不要把 Token 写入 Nginx。
|
||||
用 `*`,也不要把 Token 写入 Nginx。Nginx 必须保留客户端的 `Origin` Header 原样交给 Go,不要在
|
||||
代理层删除、改写或用固定值覆盖它;白名单判断和 403 诊断日志均由 Go 完成。
|
||||
|
||||
`limit_req_zone` 必须位于 Nginx `http` context,不能放进 `server` 或 `location`。示例文件假定它被 `conf.d/*.conf` 从 `http {}` 中 include;如果部署系统不是这样 include,应把两条 `limit_req_zone` 指令单独移到 `http {}`,并保留 `server`/`upstream` 在合法上下文。
|
||||
|
||||
@@ -118,7 +119,51 @@ FIRE_SAFETY_POSTGIS_DSN=<readonly-postgresql-dsn>
|
||||
|
||||
MCP 是普通 JSON 请求,不需要 SSE 的关闭响应缓冲设置;示例使用 30 秒读写超时,仍关闭上游自动重试。
|
||||
|
||||
## 5. 启用与检查
|
||||
## 5. 兼容 Chat 403 Origin 诊断
|
||||
|
||||
兼容 completion 返回 HTTP 403 时,先用响应中的 `request_id` 与 Go 日志关联。Go 只在拒绝场景记录
|
||||
受限诊断字段:
|
||||
|
||||
- 普通请求的非空 Origin 不在白名单时,记录 `result=forbidden_origin`;`origin` 最多保留前 256 个
|
||||
输入字节,超长值追加 `[truncated]` 后再引用/ASCII 转义;
|
||||
- CORS 预检拒绝时,记录 `result=preflight_forbidden`、同样有界的 `origin`、`preflight_method`、
|
||||
`preflight_headers` 和 `reason`;
|
||||
- `reason` 只表示 `origin_missing`、`origin_not_allowed`、`method_not_allowed` 或
|
||||
`headers_not_allowed`;成功请求不记录 Origin。
|
||||
|
||||
这些日志值是非可信请求输入,经过引用/转义且有长度边界;日志不记录 `xtoken`、`Authorization`、
|
||||
`Cookie`、prompt/body、会话或 Provider 数据。仅在受限运维终端读取有限日志,不要把完整日志粘贴到公开工单:
|
||||
|
||||
```bash
|
||||
cd /home/firee-safety-ymd
|
||||
docker compose logs --no-color --since=10m --tail=200 api \
|
||||
| grep -E 'dashscope_chat_request.*result=(forbidden_origin|preflight_forbidden)'
|
||||
```
|
||||
|
||||
如果日志值带 `[truncated]`,不能据此配置白名单;回到对方浏览器的 Network 面板读取完整 `Origin`。
|
||||
确认来源后,使用规范形式 `scheme://host[:port]`,不能带非根路径、查询或片段,多个来源用英文逗号分隔,
|
||||
禁止 `*`。单个末尾 `/` 会被接受并规范化移除,配置时建议省略。例如仅当 Network 面板确认来源确为
|
||||
`http://ui.example:9045` 时,才配置:
|
||||
|
||||
```text
|
||||
FIRE_SAFETY_CHAT_ALLOWED_ORIGINS=https://agent.nianxx.com,http://ui.example:9045
|
||||
```
|
||||
|
||||
修改 `.env` 后必须重新创建容器;只改配置时可不重建镜像:
|
||||
|
||||
```bash
|
||||
cd /home/firee-safety-ymd
|
||||
docker compose config --quiet
|
||||
docker compose up -d --force-recreate --no-build api
|
||||
```
|
||||
|
||||
若同时更新了 Go 代码,必须先拉取明确 revision,再执行 `docker compose build --pull` 和
|
||||
`docker compose up -d --force-recreate --remove-orphans`。修改 Nginx 配置本身时,仍须先执行
|
||||
`sudo nginx -t`,通过后再 reload。Nginx 层若返回 HTML 403 或连接被关闭,而 Go 没有对应
|
||||
`dashscope_chat_request` 日志,应检查实际生效的 server/location、旧配置和 Nginx error log,不能通过
|
||||
删除 `Origin` 或恢复旧的全路径 DashScope 代理绕过问题。
|
||||
|
||||
## 6. 启用与检查
|
||||
|
||||
启动 Go 服务前,在服务器的进程环境中加载 Secret。不要把 Secret 直接写进命令行或 shell 历史;可以在受保护的环境文件中加载后,再通过 Header 环境变量展开:
|
||||
|
||||
@@ -228,7 +273,7 @@ curl --fail \
|
||||
|
||||
预期 `initialize` 返回协议版本 `2025-06-18`,initialized notification 返回 HTTP 202,`tools/list` 返回 7 个固定工具。只收到 HTTP 200 但 JSON-RPC 中含 `error` 也属于失败,不能把它当作 MCP 已就绪。
|
||||
|
||||
## 6. 验收边界与回滚
|
||||
## 7. 验收边界与回滚
|
||||
|
||||
完成 `nginx -t` 和 reload 后,应至少验证:
|
||||
|
||||
@@ -246,7 +291,7 @@ curl --fail \
|
||||
路径均直接返回 404。这样不会自动关闭兼容 completion;如果也要关闭对话 API,再按 Chat 配置和对应回滚流程
|
||||
处理。页面开关和 Nginx 路由均应保留清晰的变更记录。
|
||||
|
||||
## 7. 未确认事项
|
||||
## 8. 未确认事项
|
||||
|
||||
- 目标公网机器的 Nginx 版本、include 层级、TLS 终止位置和证书续期方式;示例同时监听 80 做 HTTPS 跳转,安全组需按实际策略决定是否允许 80。
|
||||
- `agent.nianxx.com` 的 DNS、安全组、反向代理来源 IP 和 SuperAgent 对 MCP 回调的网络策略。
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
| 项 | 内容 |
|
||||
| --- | --- |
|
||||
| 项目 | `fire-safety-ymd` |
|
||||
| 状态 | SuperAgent 出站、用户对话 API v1 与空间只读 MCP 代码控制已实现;真实环境、最终用户授权和持久审计待完成 |
|
||||
| 最近更新 | 2026-09-05 |
|
||||
| 状态 | SuperAgent 出站、用户对话 API v1、兼容 Chat 403 Origin 诊断日志与空间只读 MCP 代码控制已实现;真实环境、最终用户授权和持久审计待完成 |
|
||||
| 最近更新 | 2026-09-07 |
|
||||
|
||||
## 1. 目的
|
||||
|
||||
@@ -63,7 +63,12 @@ MCP 第一阶段已按以下只读边界实现:
|
||||
- 权限不足与“没有数据”使用不同稳定状态,避免 Agent 猜测。
|
||||
- 调用记录至少关联 request ID、可信主体、工具名、授权范围、耗时、结果类别和数据源版本;审计日志不保存无必要的完整敏感正文。
|
||||
|
||||
当前日志已记录 request ID、操作、耗时和结果类别;可信主体、数据源版本和持久审计尚未实现,因此生产前仍需补齐。
|
||||
当前日志已记录 request ID、操作、耗时和结果类别;可信主体、数据源版本和持久审计尚未实现,因此生产前仍需补齐。兼容
|
||||
`completion` 的拒绝路径另有受限诊断字段:非预检请求仅在 Origin 被拒绝时记录
|
||||
`result=forbidden_origin` 和实际 Origin;CORS 预检拒绝记录
|
||||
`result=preflight_forbidden`、实际 Origin、请求方法、请求头名称集合和稳定 `reason`。
|
||||
每个请求 Header 最多保留前 256 个输入字节,超长值追加 `[truncated]` 后再引用/ASCII 转义;成功请求不记录
|
||||
Origin。日志绝不记录 `xtoken`、`Authorization`、`Cookie`、prompt/body、会话 ID 或 Provider 数据。
|
||||
|
||||
任何写工具、资源调度或状态变更都需要新的 Spec、幂等设计、人工确认边界、审计和安全 Review,不属于默认扩展。
|
||||
|
||||
@@ -109,10 +114,31 @@ MCP 第一阶段已按以下只读边界实现:
|
||||
| 精确设施或风险区域坐标 | 业务敏感 | 按权限最少披露,不记录完整结果集 |
|
||||
| 用户问题和对话 | 可能含敏感信息 | 默认不记录原文,使用摘要或分类字段 |
|
||||
| 工具名、耗时、结果类别 | 运行元数据 | 可记录,不附敏感 payload |
|
||||
| 兼容 Chat 被拒绝的 Origin 诊断字段 | 受限请求元数据 | 仅拒绝时记录引用/转义且有界的 Origin;预检附方法、请求头名称集合和原因;禁止 Secret 与请求正文 |
|
||||
|
||||
生产前需确定数据分类负责人、日志访问角色、保留周期、删除流程和安全事件响应方式。
|
||||
|
||||
当前 Chat 日志只记录 request ID、结果类别、是否复用和耗时,不记录消息、回答、对话 ID、Provider Session 或 Trace payload。`docs/import/db-samples/*.sql` 含真实联系人、电话和精确坐标,仅作为本地只读输入并由 Git 忽略;不得执行或进入版本历史。长期测试数据必须另做脱敏 fixture。
|
||||
当前 Chat 日志只记录 request ID、结果类别、是否复用和耗时,不记录消息、回答、对话 ID、Provider Session 或 Trace payload。
|
||||
兼容 `completion` 的 403 Origin 诊断是例外但仍受严格边界约束:`dashscope_chat_request` 在
|
||||
`result=forbidden_origin` 时记录有界的 `origin`;每个请求 Header 最多保留前 256 个输入字节,超长值追加
|
||||
`[truncated]` 后再引用/ASCII 转义。在
|
||||
`result=preflight_forbidden` 时再记录同样有界的 `preflight_method`、`preflight_headers` 和稳定
|
||||
`reason`(`origin_missing`、`origin_not_allowed`、`method_not_allowed` 或 `headers_not_allowed`)。
|
||||
这些字段只用于定位发送方的精确浏览器 Origin,不是授权凭证;不记录 `xtoken`、`Authorization`、`Cookie`、
|
||||
prompt/body、会话或 Provider 数据。`docs/import/db-samples/*.sql` 含真实联系人、电话和精确坐标,仅作为本地只读输入并由 Git 忽略;不得执行或进入版本历史。长期测试数据必须另做脱敏 fixture。
|
||||
|
||||
### 8.1 兼容 Chat 403 诊断与 Origin 白名单
|
||||
|
||||
本节只适用于 DashScope 风格兼容 `completion`。收到 HTTP 403 后,运维人员在受限日志中按 `request_id`
|
||||
关联响应;`result=forbidden_origin` 表示普通请求的 Origin 不在白名单,`result=preflight_forbidden`
|
||||
还需根据 `reason` 判断是来源、方法还是请求头名称集合不符合预检契约。日志中的值是经过引用/转义的非可信输入,
|
||||
不能当作 shell 代码执行;出现 `[truncated]` 时必须回到浏览器 Network 面板确认完整值。
|
||||
|
||||
确认发送方后,将精确的浏览器来源配置到 `FIRE_SAFETY_CHAT_ALLOWED_ORIGINS`:多个值用英文逗号分隔,
|
||||
每项的规范形式是 `scheme://host[:port]`,不能带非根路径、查询或片段,也禁止 `*`;单个末尾 `/` 会被接受并
|
||||
规范化移除,配置时建议省略。例如页面来源确实为 `http://example.test:9045` 时才加入该值;不要把 API
|
||||
路径、Nginx 上游地址或 `xtoken` 放入白名单。
|
||||
修改环境配置后必须重新 build(代码变更时)并 recreate 运行容器,不能依赖 `restart` 重新加载配置。
|
||||
|
||||
## 9. 应急场景安全
|
||||
|
||||
|
||||
Reference in new issue
Block a user