easyai-ai-gateway/docs/security/ssf-session-revocation.md
chengcheng ffb85b73af feat(ssf): 托管机器凭据并支持动态恢复
Gateway 连接表单接收认证中心一次性交付的 machine Client 凭据,后端立即写入 SecretStore,数据库和公开响应只保留引用及公开 Client ID。SSF 管理 Token、Verification 和 RFC 7662 内省统一从动态凭据读取,支持现有连接无重启修复及进程重启恢复,环境变量仅保留为旧部署回退。\n\n验证:go test ./apps/api/...;pnpm nx test web;真实重启、OIDC 登录与 session-revoked 1.29 秒失效验收。
2026-07-17 09:13:57 +08:00

69 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SSF/CAEP 实时会话撤销运行手册
Gateway 可选接收 Auth Center 通过 RFC 8935 Push 投递的 RFC 8417 Security Event Token并处理 OpenID CAEP `session-revoked`。功能由数据库中的连接资源控制:没有连接时保持原有 OIDC、BFF、API Key 和 Legacy JWT 行为;不再使用 `OIDC_SECURITY_EVENTS_ENABLED`
## 用户接入流程
用户只执行两项操作:
1. 在认证中心 Application 的“安全事件流”页面选择现有 RFC 7662 机器 Client点击“准备 Gateway 接入”。认证中心自动合并 SSF 管理 Scope不会创建第二个 Client。
2. Receiver 就绪后点击“生成一次性连接凭据”,立即复制 machine Client ID/Secret。
3. 在 Gateway“系统设置 → 认证中心安全事件”中填写 SSF Issuer 和这组一次性凭据,点击“连接认证中心”。
Gateway 后端先把 machine Secret 写入 SecretStore随后自动读取 Discovery、生成并托管 256 bit Push Bearer、创建 paused Stream、完成 Verification、首次启用 Stream并进入 360 秒 RFC 7662 bootstrap。浏览器只在两端连接表单的短暂操作期间接触 machine SecretPush Bearer 和 Secret 引用始终不可见,数据库、响应和日志不保存明文。管理员不编辑 Secret 文件,也不需要重启 Gateway。
环境前置配置只保留 OIDC 公共参数和 Gateway 公共地址:
- `OIDC_ISSUER`、`OIDC_TENANT_ID`
- `AI_GATEWAY_PUBLIC_BASE_URL`,生产必须是认证中心可访问的 HTTPS 地址。
`OIDC_INTROSPECTION_CLIENT_ID/SECRET` 仅作为旧部署兼容回退,不再是新连接必填项。新连接把 machine 凭据动态托管到 SecretStoreOIDC fallback、SSF 管理 Token 和 Verification 共用这一份凭据,重启后继续生效。
第一版一个 Gateway 部署只允许一个认证中心连接。下游业务服务无需接入 SSF。
## SecretStore
本地和 Docker 使用 `file` 驱动。服务自动创建目录并强制目录 `0700`、文件 `0600`Docker Compose 将目录放在持久化 `api_data` 卷中。用户不写入任何 `ssf-delivery-*` 文件。
Kubernetes 使用 `kubernetes` 驱动和一个部署时预创建的空 Secret
```text
OIDC_SECURITY_EVENTS_SECRET_STORE=kubernetes
OIDC_SECURITY_EVENTS_KUBERNETES_NAMESPACE=easyai
OIDC_SECURITY_EVENTS_KUBERNETES_SECRET_NAME=easyai-gateway-security-events
```
参考清单见 `deploy/kubernetes/security-events-secret-rbac.yaml`。ServiceAccount 只能对这个固定 Secret 执行 `get/update/patch`,不能创建、删除或读取其他 Secret。数据库、API、浏览器、日志和审计只保存或展示非敏感连接元数据。
## 动态运行与状态
Receiver 路由始终注册:没有连接时返回无敏感信息的 `404`;存在连接但凭据丢失时返回 `503` 并进入 `introspection_fallback`。OIDC Evaluator 始终挂载但在无连接时无副作用。
连接生命周期包括 `connecting`、`verifying`、`bootstrap`、`enabled`、`degraded`、`rotating`、`disconnect_pending` 和 `retiring`。健康时每 60 秒一次 Verification不随业务请求 QPS 增长180 秒无匹配 Verification 时切换 RFC 7662。内省也不可用时 OIDC Fail ClosedAPI Key 继续工作。
Verification 成功后仅在首次连接和主动轮换时自动启用 Stream。认证中心管理员之后手工暂停或禁用 StreamGateway 的“重新验证”只检查链路,不会擅自恢复远端状态。
## 轮换与断开
“轮换凭据”由 Gateway 自动完成:生成 next、Receiver 同时接受 current/next、暂停并更新远端 Stream、Verification、重新启用、保留旧值至少 180 秒,最后提升 next 并删除旧值。中途失败保留两个凭据和 `rotating` 状态,可安全重试。
“断开连接”先删除远端 Stream再进入至少 360 秒 `retiring`,期间继续应用撤销水位和 RFC 7662避免旧 Token 因关闭功能重新有效。远端不可用时保持 `disconnect_pending` 并指数退避重试;不会提前删除 Push Secret。收据、水位和脱敏审计数据不会清表。
所有写管理接口要求 Gateway `Manager` 权限、`Idempotency-Key` 和 `If-Match`
```text
GET /api/admin/system/identity/security-events/connection
PUT /api/admin/system/identity/security-events/connection
POST /api/admin/system/identity/security-events/connection/verify
POST /api/admin/system/identity/security-events/connection/rotate-credential
DELETE /api/admin/system/identity/security-events/connection
```
## 监控、回滚与验收
`GET /metrics` 输出接收结果、删除 Session 数、水位拒绝数、Verification 年龄、健康模式、内省结果、JWKS 失败和处理延迟。至少告警 Verification age 超过 120 秒、fallback 超过 5 分钟、内省失败、SET 拒绝增长以及撤销 P99 超过 3 秒。日志只记录脱敏 Trace/Audit ID 和错误类别。
回滚时先在认证中心暂停 Stream再通过 Gateway 安全断开保留迁移表、水位和审计。Legacy HS256 Token 和 API Key 不在本协议撤销范围内。
真实链路只使用明确标记为测试用途的 Application并且必须在自动化测试后执行。报告包含脱敏 Trace、Claims、截图、Audit ID、投递延迟、fallback 和恢复证据;需要人工或第三方操作时记录 `SKIPPED_HUMAN_OR_THIRD_PARTY_REQUIRED`