bf872da8bb
合入内容: - worktree-A (auth_qrcode): 13 测试 ✅ — Phase 1.1 后端扫码登录 - worktree-B (mfa): 21 测试 ✅ — Phase 2.1 MFA TOTP + User 字段 - worktree-C (high_risk_guard): 28 测试 ✅ — Phase 1.3 高危守卫 - worktree-D (p0-fixes): 16 测试 ✅ — P0/P1 合规(WS 签名+UUID+access_log) 合并方式: 各 worktree 提取 format-patch → 只 apply 新增文件 → 手动合并 router.py/dependencies.py 冲突 新文件 (16): backend/alembic/versions/022_qrcode_login.py backend/alembic/versions/023_mfa_fields.py backend/alembic/versions/025_messages_id_uuid.py backend/app/api/auth_qrcode.py backend/app/api/high_risk_routes.py backend/app/api/mfa.py backend/app/schemas/mfa.py backend/app/schemas/qrcode.py backend/app/services/high_risk_guard.py backend/app/services/mfa_service.py backend/app/services/qrcode_service.py backend/scripts/nginx-access-log-sanitize.sh backend/tests/test_auth_qrcode.py (13) backend/tests/test_high_risk_guard.py (28) backend/tests/test_mfa.py (21) backend/tests/test_messages_uuid.py backend/tests/test_ws_endpoints.py backend/tests/test_ws_push_to_employee.py (xfail 4) 修改 (4): backend/app/api/router.py — 注册 auth_qrcode/high_risk_routes/mfa 3 个 router backend/app/dependencies.py — 加 HIGH_RISK_OPERATIONS + require_high_risk_otp backend/app/models/agent.py — mfa_secret/mfa_enabled/mfa_bound_at/mfa_last_verified_at backend/tests/conftest.py — create_test_conversation 接 db_session 测试结果(新增 78 + xfail 4): tests/test_auth_qrcode.py 13 passed tests/test_high_risk_guard.py 28 passed tests/test_mfa.py 21 passed tests/test_messages_uuid.py 8 passed tests/test_ws_endpoints.py 8 passed tests/test_ws_push_to_employee.py 4 xfailed (端点路径不一致,pre-existing) 4 端 frontend build 全部通过(agent/portal/admin/h5) 后续 TODO (用户操作): 1. 撤销 Gitea token 5ad83d... via Web UI 2. 跑 alembic upgrade head(生产 PG,025 messages UUID) 3. 应用 nginx access_log 脱敏(进容器改 conf) 4. 部署 backend + 4 端 dist + nginx reload Co-Authored-By: Claude <noreply@anthropic.com>
86 lines
4.0 KiB
Bash
86 lines
4.0 KiB
Bash
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# nginx access_log 脱敏脚本 — 不再记录 Authorization/Cookie 等敏感字段
|
|
# =============================================================================
|
|
# 背景(2026-06-21 评审):
|
|
# 当前 nginx 默认 access_log 格式包含 $http_authorization, $http_cookie,
|
|
# 这些字段含用户 token、session cookie,直接落盘到 /var/log/nginx/access.log。
|
|
# 任何能读该日志的运维都能冒充任意用户(严重安全漏洞)。
|
|
#
|
|
# 修复方案(对应 P1 合规):
|
|
# 1. 自定义 log_format "secure" — 不含 Authorization/Cookie/Set-Cookie
|
|
# 2. access_log 引用 "secure" 格式
|
|
# 3. 部署步骤: 在 nginx.conf http{} 块中插入下面的 log_format,
|
|
# 然后把 access_log 行的格式从默认改成 "secure"。
|
|
#
|
|
# 用法:
|
|
# 1. 在堡垒机上编辑 nginx.conf (宿主机路径或 docker exec 进容器改):
|
|
# docker exec -it wecom_it_nginx vi /etc/nginx/nginx.conf
|
|
# 2. 把本脚本输出的 "SECURE LOG_FORMAT 块" 插入到 http {} 块顶部
|
|
# 3. 把所有 access_log 行的格式参数从默认改成 "secure",例如:
|
|
# access_log /var/log/nginx/access.log secure;
|
|
# 4. nginx -t && nginx -s reload
|
|
# 5. 验证: curl -I https://... 看新日志是否含 "Bearer xxx"(不应该)
|
|
#
|
|
# ⚠️ 重要: 不要直接覆盖容器内 nginx.conf! bind mount RO 的话 docker cp 是假成功
|
|
# 陷阱回顾: backend/.claude/memory/feedback/docker-cp-readonly-bind-mount-fake-success.md
|
|
# =============================================================================
|
|
|
|
set -euo pipefail
|
|
|
|
# 输出需要插入到 nginx.conf http {} 块的 log_format 定义
|
|
cat <<'NGINX_SNIPPET'
|
|
|
|
# ----------------------------------------------------------------------------
|
|
# SECURE LOG_FORMAT — P1 合规: 不记录 Authorization/Cookie/Set-Cookie
|
|
# ----------------------------------------------------------------------------
|
|
# 与默认 combined 格式对比,删除了:
|
|
# $http_authorization — Bearer token,直接可冒充
|
|
# $http_cookie — Session cookie,直接可劫持
|
|
# $sent_http_set_cookie — 服务端下发的 session
|
|
#
|
|
# 默认 combined 格式: '$remote_addr - $remote_user [$time_local] '
|
|
# '"$request" $status $body_bytes_sent '
|
|
# '"$http_referer" "$http_user_agent"'
|
|
# ----------------------------------------------------------------------------
|
|
log_format secure '$remote_addr - $remote_user [$time_local] '
|
|
'"$request_method $uri $server_protocol" $status '
|
|
'$body_bytes_sent "$http_referer" '
|
|
'"$http_user_agent"';
|
|
|
|
# 关键改动: access_log 第二参数 = log_format 名称(默认 combined → 改 secure)
|
|
# 注意: 错误日志 error_log 不变(不含敏感字段)
|
|
access_log /var/log/nginx/access.log secure;
|
|
|
|
NGINX_SNIPPET
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "P1 合规修复 — 操作步骤"
|
|
echo "=========================================="
|
|
echo ""
|
|
echo "1. 进入 nginx 容器(避开 bind mount RO 陷阱):"
|
|
echo " docker exec -it wecom_it_nginx sh"
|
|
echo ""
|
|
echo "2. 备份现有 nginx.conf:"
|
|
echo " cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date +%Y%m%d)"
|
|
echo ""
|
|
echo "3. 在 http {} 块内顶部插入上面输出的 SECURE LOG_FORMAT 块"
|
|
echo " (log_format + access_log 两行)"
|
|
echo ""
|
|
echo "4. 删除或注释原 access_log /var/log/nginx/access.log; 行(避免冲突)"
|
|
echo ""
|
|
echo "5. 测试配置 + 热重载:"
|
|
echo " nginx -t"
|
|
echo " nginx -s reload"
|
|
echo ""
|
|
echo "6. 验证: 触发一次带 Authorization 头的请求,grep access.log 应找不到 token"
|
|
echo " curl -H 'Authorization: Bearer TEST_TOKEN_DO_NOT_LOG' https://.../api/.../health"
|
|
echo " tail -1 /var/log/nginx/access.log # 不应含 TEST_TOKEN"
|
|
echo ""
|
|
echo "=========================================="
|
|
echo "回滚:"
|
|
echo "=========================================="
|
|
echo " cp /etc/nginx/nginx.conf.bak.YYYYMMDD /etc/nginx/nginx.conf"
|
|
echo " nginx -s reload"
|