Files
sub2api-cn-relay-manager/docs/TRUSTED_SUBJECT_DEPLOY_GUIDE.md

195 lines
5.6 KiB
Markdown
Raw Normal View 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 上执行:
```bash
TRUSTED_PROXY_SECRET=$(openssl rand -hex 32)
echo "Generated secret: $TRUSTED_PROXY_SECRET"
# 保存此密钥,需要同时配置到 nginx 和 CRM
```
#### 步骤 2: 更新 CRM 配置
编辑 `/home/ubuntu/.env.crm`(或实际运行目录):
```bash
# 在文件末尾添加:
# 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` 块内添加:
```nginx
# 从 httpOnly cookie 提取 portal subject放在 server 块内)
map $http_cookie $portal_subject {
default "";
~*crm_session=([^;]+) $1;
}
```
修改 `/portal-admin-api/` location
```nginx
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: 重启服务
```bash
# 测试 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` cookiehttpOnly`crm_subject` cookie
5. 尝试创建/管理用户 Key应该可以正常工作
API 测试:
```bash
# 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