- 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
5.6 KiB
5.6 KiB
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 secretdeploy/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: 验证
浏览器测试:
- 访问
https://sub.tksea.top/portal/ - 登录(会同时设置 CRM session cookie)
- 打开浏览器 DevTools → Application → Cookies
- 确认看到
crm_sessioncookie(httpOnly)和crm_subjectcookie - 尝试创建/管理用户 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-Proxyheader 值是否一致 - 检查两个密钥是否完全匹配(无多余空格)
CRM 返回 trusted subject header required
- 检查 nginx 是否正确添加了
map $http_cookie $portal_subject - 检查浏览器是否有
crm_sessioncookie(登录后应该自动设置) - 检查 cookie 是否被浏览器阻止(SameSite/Secure 设置)
Portal 前端无法登录 CRM session
- 检查浏览器 console 是否有 CORS 错误
- 检查
/portal-admin-api/location 是否正确配置 - 确认 CRM 服务正在监听
127.0.0.1:18190
安全配置建议
-
密钥管理
- 使用
openssl rand -hex 32生成强密钥 - 不要在任何地方记录或提交密钥
- 考虑使用 HashiCorp Vault 或 AWS Secrets Manager
- 使用
-
HTTPS
- 生产环境必须启用 HTTPS
- 设置
Secureflag 在 cookies 上
-
Cookie 设置
crm_session: httpOnly, SameSite=Lax, Secure (HTTPS only)crm_subject: SameSite=Lax, Secure (HTTPS only)
回滚计划
如果需要回滚:
- 还原 nginx 配置(删除 map 和 header 设置)
- 还原
.env.crm(移除 TRUSTED_* 配置) - 重载 nginx / 重启 CRM
portal 会回退到之前的 bearer token 认证模式。
验证清单
- 生成并记录了 64 字符 hex secret
- 更新了
.env.crm配置 - 更新了 nginx 配置
- 重载了 nginx 配置
- 重启了 CRM 服务
- 浏览器测试通过(可以看到 crm_session cookie)
- API 测试通过(可以创建 user-key)
- 完整链路测试通过(create → chat → pause → resume → delete)