Files
story/docs/load-alerting-and-production-security.md
T

104 lines
8.0 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.
# 压测、告警与生产安全门禁
## 1. 生产配置启动门禁
当`APP_ENV=prod`时,进程在连接外部依赖前执行配置校验,任一条件不满足即拒绝启动:
- OIDC签发方和JWKS地址必须使用HTTPS;
- PostgreSQL连接不能使用`sslmode=disable`;
- Redis必须配置非占位密码;
- API设备凭据必须按设备从受控Secrets/KMS CSI目录解析,生产禁止单一静态开发密钥;
- RTC应用必须使用正式AppID/AppKey和火山正式Token格式;
- Worker必须使用火山RTC HTTPS签名VoiceChat接口以及非占位AK/SK,禁止本地模拟供应商;
- 分页游标和分享签名密钥必须至少32字符、不得使用本地/示例值且彼此不同;
- 对象存储必须启用TLS,内外端点不能指向本机,访问凭据不得使用本地/示例值;
- Callback签名密钥不得使用本地/示例值。
生产密钥不得写入Git、镜像、Compose文件或普通配置文件。部署平台应通过Secret Manager/KMS、短期工作负载身份或只读内存挂载注入,并建立轮换、吊销、双密钥过渡和访问审计。当前仓库只提供启动门禁,不宣称已经接入任何特定云厂商的密钥托管。
所有后端长期敏感配置均支持`NAME_FILE`约定,包括数据库连接串、Redis密码、RTC AppKey、火山AK/SK/临时Token、方舟API Key、对象存储凭据、设备本地开发密钥以及游标、分享、供应商回调和告警签名密钥。文件必须使用容器内绝对路径并小于等于64KiB;同一密钥的`NAME`与`NAME_FILE`同时配置时服务拒绝启动。该能力用于直接消费Docker/Kubernetes Secret或KMS CSI挂载文件,不等同于已经完成某个云厂商的身份授权与轮换验收。
本地开发已通过目录解析器测试验证不同设备密钥隔离、越界引用拒绝、短密钥拒绝,以及原子替换文件后无需重启即可读取新密钥。`scripts/verify-local-secret-rotation.ps1`保留用于验证旧的进程级环境注入路径;两者都不能替代真实KMS/HSM、量产设备注入、双密钥过渡和吊销审计。
## 2. 压测入口
`test/load/api-readiness.js`提供固定到达率压测。`acceptance`配置为50 RPS持续30分钟,门禁为失败率低于0.1%、p95低于500毫秒、p99低于1秒;`smoke`配置用于提交前短测。该数值是研发压测门禁,不是未经真实环境验证的产品SLA。
```powershell
docker run --rm -v "${PWD}/test/load:/scripts:ro" grafana/k6 run `
-e BASE_URL=http://host.docker.internal:58080 `
-e PROFILE=acceptance /scripts/api-readiness.js
# 500次/秒供应商回调,持续10分钟,并对账30万唯一事件
pwsh -NoProfile -File .\scripts\load-provider-callbacks.ps1 `
-Profile acceptance -ConversationPool 100
# 1000活跃通话、500条SSE、10000媒体分片、100并发隐私删除
pwsh -NoProfile -File .\scripts\load-conversation-state.ps1
pwsh -NoProfile -File .\scripts\load-sse-connections.ps1 -Connections 500
pwsh -NoProfile -File .\scripts\load-media-manifest.ps1
pwsh -NoProfile -File .\scripts\load-privacy-delete.ps1
```
如需叠加真实OIDC授权读取,将短期测试令牌通过进程环境传入`ACCESS_TOKEN`。禁止把令牌写进脚本或提交仓库。负载脚本必须使用隔离租户和合成数据;带夹具的包装脚本会在结束后执行数据库对账和精确清理。压测应在与生产容量相近的测试环境执行;本地结果只能形成研发回归基线,不能替代生产容量结论。完整本地结果、夹具边界和失败修正记录见[性能、恢复、安全与兼容性专项验证报告](performance-recovery-security-compatibility.md)。
## 3. Prometheus告警
`deploy/prometheus/rules/platform-alerts.yml`定义以下基础规则:
| 告警 | 条件 | 建议动作 |
|---|---|---|
| `PlatformServiceDown` | 连续2分钟无法抓取服务 | 检查部署、健康依赖和网络 |
| `PlatformHighHTTP5xxRate` | 5分钟窗口5xx高于5%,持续5分钟 | 按服务、路由和trace定位错误 |
| `PlatformHighP95Latency` | 路由p95高于1.5秒,持续10分钟 | 检查数据库、Redis、对象存储和下游供应商 |
| `OutboxDeadLetterPresent` | 存在死信 | 核对错误码,修复后人工重放 |
| `OutboxPendingBacklog` | pending超过100且持续10分钟 | 检查Worker容量及下游可用性 |
| `PrivacyDeletionPartialFailure` | 隐私请求存在`PARTIAL_FAILED` | 立即对账六子系统并保留处置证据 |
| `FirmwareAssignmentFailure` | 存在失败设备 | 暂停批次,分析设备结果,必要时回滚 |
| `FirmwareRolloutStalled` | 运行批次15分钟无更新 | 检查命令投递、设备在线和下载权限 |
业务告警扫描器还会从`provider_dependency_state`生成`PROVIDER_UNAVAILABLE`事件。连续临时失败达到部署阈值后只暂停新启动,不阻断停止与回收;历史网页和普通查询不依赖供应商在线状态。恢复演练必须证明外呼调用数在熔断窗口内不再因新启动增加、停止任务仍有尝试、告警出现,并在供应商恢复后最终收敛。
本地Compose已挂载规则目录,并自动配置Grafana业务、技术、安全三类仪表盘;Prometheus采集API、Callbacks和Worker三类目标。正式环境还需对接告警接收器、值班分组、抑制规则和升级策略,并基于真实容量重新校准阈值。
业务扫描器还生成供应商通知积压和证书到期信号。证书通过`ops_resource_reference`登记为受控引用,只保存引用、核验时间和到期时间,不保存私钥或证书正文;30天内到期为高等级,7天内提升为严重等级。
## 4. 恢复与安全专项入口
```powershell
# 真实pg_dump/pg_restore到隔离数据库并核对迁移、表、外键和关键计数
pwsh -NoProfile -File .\scripts\verify-postgres-restore.ps1
# API/Callbacks/Worker重启、停机Outbox恢复和Redis热状态重建
pwsh -NoProfile -File .\scripts\verify-runtime-recovery.ps1
# 本地长期设备签名密钥轮换,不重建镜像
pwsh -NoProfile -File .\scripts\verify-local-secret-rotation.ps1
# 认证、授权、输入、签名、防重放、安全响应头和日志正文过滤
pwsh -NoProfile -File .\scripts\security-http-smoke.ps1
# 后端依赖可达漏洞、前端依赖、仓库密钥和最终镜像
docker run --rm -v "${PWD}:/src" -w /src golang:1.26.6-alpine `
sh -c "go run golang.org/x/vuln/cmd/govulncheck@v1.1.4 ./..."
npm --prefix web audit --audit-level=high
docker run --rm -v "${PWD}:/src" zricethezav/gitleaks:v8.30.1 `
detect --source=/src --config=/src/.gitleaks.toml --no-banner
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock `
-v data-terminal-trivy-cache:/root/.cache/trivy aquasec/trivy:0.74.0 `
image --scanners vuln --ignore-unfixed --severity HIGH,CRITICAL `
data-terminal-cloud-api:latest
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock `
-v data-terminal-trivy-cache:/root/.cache/trivy aquasec/trivy:0.74.0 `
image --scanners vuln --ignore-unfixed --severity HIGH,CRITICAL `
data-terminal-cloud-web:latest
```
Web最终镜像使用非特权UID 101和8080监听;构建基线为Nginx 1.30.4 unprivileged Alpine并在镜像构建时应用当前系统安全更新。配置扫描必须确认Dockerfile不存在root运行高危项,镜像扫描必须同时覆盖API和Web最终运行层。
CI进一步使用镜像摘要固定Gitleaks、Trivy和Syft,并输出CycloneDX SBOM。浏览器矩阵由`node test/e2e/browser-matrix.mjs`执行,Safari必须在macOS真浏览器补测。宿主Go版本可能落后于镜像构建器,因此最终`govulncheck`证据必须在与生产构建一致的Go版本中生成。
## 5. 上线前证据
生产候选版本至少应保存:构建提交号、SBOM和镜像摘要,单元/集成/迁移/接口契约结果,依赖与镜像漏洞报告,密钥扫描报告,压测报告,故障恢复演练,固件暂停/回滚演练,隐私删除六子系统对账,以及真实供应商和真机连续通话记录。缺少外部账号、硬件或生产基础设施时,应明确标为“待外部验证”,不能用本地模拟结果替代。