Files
sub2api-cn-relay-manager/docs/TRUSTED_SUBJECT_DEPLOY_GUIDE.md
phamnazage-jpg 4e2ee087fd feat(vNext.4): implement trusted-subject security chain for portal user key self-service
- Add portal_auth.go: Portal user session auth with HMAC-signed cookies
- Add /api/portal/session/{login,logout,state} endpoints
- Update nginx config template: cookie-to-header trusted proxy pattern
- Update frontend: sync CRM session on login/logout
- Add TRUSTED_SUBJECT_DEPLOY_GUIDE.md with remote43 deployment steps
- Update EXECUTION_BOARD.md: mark trusted-subject blocking issue as resolved

This implements the secure chain:
  Browser → Portal → nginx (cookie→header) → CRM (verify proxy secret)

Required remote43 actions:
1. Generate 64-char hex secret
2. Update .env.crm with TRUSTED_* config
3. Update nginx with cookie map and header injection
4. Restart services

Fixes EXECUTION_BOARD.md 2026-06-08 blocking issue
2026-06-09 07:48:03 +08:00

5.6 KiB
Raw Blame History

vNext.4 Trusted-Subject 安全链部署指南

解决 2026-06-08 EXECUTION_BOARD.md 中记录的线上阻塞问题

问题描述

remote43 当前 nginx /portal-admin-api/ 未注入 X-CRM-Authenticated-Subject / X-CRM-Trusted-Proxy,导致无法在现网安全完成新的 user-key 真验闭环。

解决方案

实施受信代理安全链:

用户浏览器 ← → Portal 前端 ← → nginx (cookie→header 转换) ← → CRM
                      ↑                           ↓
                设置 httpOnly cookie      验证并注入受信 header

所需变更

1. CRM 二进制更新 (已完成)

新增文件:

  • internal/app/portal_auth.go - Portal user session 认证模块
  • internal/app/portal_auth_test.go - 测试用例

变更文件:

  • internal/app/http_api.go - 添加 /api/portal/session/* 路由
  • internal/app/bootstrap.go - 传递 trusted proxy secret
  • deploy/tksea-portal/index.html - 添加 CRM session 登录/登出
  • deploy/tksea-portal/nginx.sub.tksea.top.conf.example - nginx 配置模板
  • .env.example - 环境变量模板

2. remote43 部署步骤

步骤 1: 生成共享密钥

在 remote43 上执行:

TRUSTED_PROXY_SECRET=$(openssl rand -hex 32)
echo "Generated secret: $TRUSTED_PROXY_SECRET"
# 保存此密钥,需要同时配置到 nginx 和 CRM

步骤 2: 更新 CRM 配置

编辑 /home/ubuntu/.env.crm(或实际运行目录):

# 在文件末尾添加:
# Trusted Subject Proxy Configuration
SUB2API_CRM_TRUSTED_SUBJECT_HEADER=X-CRM-Authenticated-Subject
SUB2API_CRM_TRUSTED_PROXY_SECRET_HEADER=X-CRM-Trusted-Proxy
SUB2API_CRM_TRUSTED_PROXY_SECRET=<步骤1生成的64字符密钥>

步骤 3: 更新 nginx 配置

编辑 /etc/nginx/sites-enabled/sub.tksea.top.conf

server 块内添加:

# 从 httpOnly cookie 提取 portal subject放在 server 块内)
map $http_cookie $portal_subject {
    default "";
    ~*crm_session=([^;]+) $1;
}

修改 /portal-admin-api/ location

location /portal-admin-api/ {
    proxy_pass http://127.0.0.1:18190/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    # 关键:从验证过的 cookie 提取并注入 subject
    proxy_set_header X-CRM-Authenticated-Subject $portal_subject;
    # 受信代理密钥(必须与 CRM 配置一致)
    proxy_set_header X-CRM-Trusted-Proxy "<步骤1生成的64字符密钥>";

    proxy_http_version 1.1;
}

注意

  • 删除原来的 proxy_set_header X-Portal-Subject "";
  • 确保密钥替换为实际生成的 64 字符 hex 字符串

步骤 4: 重启服务

# 测试 nginx 配置
sudo nginx -t

# 重载 nginx
sudo systemctl reload nginx

# 重启 CRM
sudo systemctl restart crm
# 或使用:
# pkill -f "crm" && cd /home/ubuntu && ./server &

步骤 5: 验证

浏览器测试:

  1. 访问 https://sub.tksea.top/portal/
  2. 登录(会同时设置 CRM session cookie
  3. 打开浏览器 DevTools → Application → Cookies
  4. 确认看到 crm_session cookiehttpOnlycrm_subject cookie
  5. 尝试创建/管理用户 Key应该可以正常工作

API 测试:

# 1. 登录获取 session cookie
curl -c cookies.txt -X POST https://sub.tksea.top/portal-admin-api/api/portal/session/login \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com"}'

# 2. 使用 cookie 访问 user-key API
curl -b cookies.txt https://sub.tksea.top/portal-admin-api/api/keys

# 3. 创建新 key
curl -b cookies.txt -X POST https://sub.tksea.top/portal-admin-api/api/keys \
  -H "Content-Type: application/json" \
  -d '{"key_name":"test-key","logical_group_id":"gpt-shared"}'

3. 故障排除

CRM 返回 unauthorized / trusted proxy authentication required

  • 检查 .env.crm 中的 SUB2API_CRM_TRUSTED_PROXY_SECRET 是否正确设置
  • 检查 nginx 中的 X-CRM-Trusted-Proxy header 值是否一致
  • 检查两个密钥是否完全匹配(无多余空格)

CRM 返回 trusted subject header required

  • 检查 nginx 是否正确添加了 map $http_cookie $portal_subject
  • 检查浏览器是否有 crm_session cookie登录后应该自动设置
  • 检查 cookie 是否被浏览器阻止SameSite/Secure 设置)

Portal 前端无法登录 CRM session

  • 检查浏览器 console 是否有 CORS 错误
  • 检查 /portal-admin-api/ location 是否正确配置
  • 确认 CRM 服务正在监听 127.0.0.1:18190

安全配置建议

  1. 密钥管理

    • 使用 openssl rand -hex 32 生成强密钥
    • 不要在任何地方记录或提交密钥
    • 考虑使用 HashiCorp Vault 或 AWS Secrets Manager
  2. HTTPS

    • 生产环境必须启用 HTTPS
    • 设置 Secure flag 在 cookies 上
  3. Cookie 设置

    • crm_session: httpOnly, SameSite=Lax, Secure (HTTPS only)
    • crm_subject: SameSite=Lax, Secure (HTTPS only)

回滚计划

如果需要回滚:

  1. 还原 nginx 配置(删除 map 和 header 设置)
  2. 还原 .env.crm(移除 TRUSTED_* 配置)
  3. 重载 nginx / 重启 CRM

portal 会回退到之前的 bearer token 认证模式。

验证清单

  • 生成并记录了 64 字符 hex secret
  • 更新了 .env.crm 配置
  • 更新了 nginx 配置
  • 重载了 nginx 配置
  • 重启了 CRM 服务
  • 浏览器测试通过(可以看到 crm_session cookie
  • API 测试通过(可以创建 user-key
  • 完整链路测试通过create → chat → pause → resume → delete