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
This commit is contained in:
@@ -97,11 +97,19 @@ block = textwrap.dedent("""\
|
||||
}
|
||||
|
||||
location /portal-admin-api/ {
|
||||
# 必须由受信登录/鉴权层把用户 subject 放进 \$portal_subject,不能信任浏览器自带 header。
|
||||
# 同时 CRM 需配置:
|
||||
# SUB2API_CRM_TRUSTED_SUBJECT_HEADER=X-CRM-Authenticated-Subject
|
||||
# SUB2API_CRM_TRUSTED_PROXY_SECRET_HEADER=X-CRM-Trusted-Proxy
|
||||
# SUB2API_CRM_TRUSTED_PROXY_SECRET=<same-secret-as-nginx>
|
||||
proxy_pass http://127.0.0.1:${REMOTE_CRM_PORT}/;
|
||||
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;
|
||||
proxy_set_header X-Portal-Subject "";
|
||||
proxy_set_header X-CRM-Authenticated-Subject \$portal_subject;
|
||||
proxy_set_header X-CRM-Trusted-Proxy "REPLACE_WITH_SUB2API_CRM_TRUSTED_PROXY_SECRET";
|
||||
proxy_http_version 1.1;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,12 +75,19 @@ render_remote43_crm_env() {
|
||||
local repo_root="${4:-}"
|
||||
local admin_username="${5:-admin}"
|
||||
local admin_password="${6:-$admin_token}"
|
||||
local trusted_subject_header="${SUB2API_CRM_TRUSTED_SUBJECT_HEADER:-}"
|
||||
local trusted_proxy_secret_header="${SUB2API_CRM_TRUSTED_PROXY_SECRET_HEADER:-X-CRM-Trusted-Proxy}"
|
||||
local trusted_proxy_secret="${SUB2API_CRM_TRUSTED_PROXY_SECRET:-}"
|
||||
local sqlite_dsn_q admin_token_q repo_root_q admin_username_q admin_password_q
|
||||
local trusted_subject_header_q trusted_proxy_secret_header_q trusted_proxy_secret_q
|
||||
printf -v sqlite_dsn_q '%q' "$sqlite_dsn"
|
||||
printf -v admin_token_q '%q' "$admin_token"
|
||||
printf -v repo_root_q '%q' "$repo_root"
|
||||
printf -v admin_username_q '%q' "$admin_username"
|
||||
printf -v admin_password_q '%q' "$admin_password"
|
||||
printf -v trusted_subject_header_q '%q' "$trusted_subject_header"
|
||||
printf -v trusted_proxy_secret_header_q '%q' "$trusted_proxy_secret_header"
|
||||
printf -v trusted_proxy_secret_q '%q' "$trusted_proxy_secret"
|
||||
|
||||
cat <<EOF
|
||||
SUB2API_CRM_LISTEN_ADDR=127.0.0.1:$crm_port
|
||||
@@ -91,6 +98,9 @@ SUB2API_CRM_ADMIN_PASSWORD=$admin_password_q
|
||||
SUB2API_CRM_ADMIN_SESSION_TTL=12h
|
||||
SUB2API_CRM_REPO_ROOT=$repo_root_q
|
||||
SUB2API_CRM_RECONCILE_WORKER_ENABLED=false
|
||||
SUB2API_CRM_TRUSTED_SUBJECT_HEADER=$trusted_subject_header_q
|
||||
SUB2API_CRM_TRUSTED_PROXY_SECRET_HEADER=$trusted_proxy_secret_header_q
|
||||
SUB2API_CRM_TRUSTED_PROXY_SECRET=$trusted_proxy_secret_q
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user