feat: strengthen P0 security and operations
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
# 配置与后台任务
|
||||
|
||||
本文列出 API 和 DbMigrator 当前实际读取的配置。敏感值应通过环境变量、Secret Manager 或部署平台密钥注入,不能提交到仓库。
|
||||
本文列出 API、Worker 和 DbMigrator 当前实际读取的配置。敏感值应通过环境变量、Secret Manager 或部署平台密钥注入,不能提交到仓库。
|
||||
|
||||
## 进程与依赖
|
||||
|
||||
| 进程 | PostgreSQL | Redis | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `Tiku.Api` | 必需 | Development 可选;Production 必需 | 提供 HTTP API、认证、缓存和 Hosted Service 后台处理 |
|
||||
| `Tiku.Api` | 必需 | Development 可选;Production 必需 | 提供 HTTP API、认证、授权和缓存 |
|
||||
| `Tiku.Worker` | 必需 | 不需要 | 承载周期任务、任务队列、租户导出和安全扫描 |
|
||||
| `Tiku.DbMigrator` | 必需 | 不需要 | 执行 Migration、内置目录 seed 和管理员引导 |
|
||||
|
||||
Development 未配置 Redis 时,安全服务使用进程内/数据库防线。Production 不允许 Redis 降级;后台任务在所有环境统一使用 PostgreSQL。
|
||||
@@ -54,11 +55,11 @@ dotnet run --project Tiku.DbMigrator -- --bootstrap-platform-admin
|
||||
|
||||
Redis key 使用环境前缀;配置解析会强制 `AbortOnConnectFail=false`。Redis 不是用户、Session、权限、套餐或用量的权威数据源。
|
||||
|
||||
## 后台处理配置
|
||||
## Worker 与后台处理配置
|
||||
|
||||
```json
|
||||
{
|
||||
"BackgroundProcessing": {
|
||||
"Worker": {
|
||||
"Enabled": true,
|
||||
"JobPollSeconds": 2,
|
||||
"JobParallelism": 4,
|
||||
@@ -89,7 +90,18 @@ Redis key 使用环境前缀;配置解析会强制 `AbortOnConnectFail=false`
|
||||
|
||||
域名只有在 `AllowedCnameTargets`、DNS JSON endpoint、Gateway URL 和 API key 配置完成后,才可能从 Pending/Failed 进入 Active。仅 DNS 验证成功不代表 TLS 已就绪。
|
||||
|
||||
后台任务状态和 `RunAfter` 存在 PostgreSQL。API Hosted Service 使用 `FOR UPDATE SKIP LOCKED`、五分钟租约和有限重试处理即时、延时及失败待重试任务。`BackgroundProcessing:Enabled=false` 会关闭全部四个后台循环,通常只用于测试或维护。
|
||||
后台任务状态和 `RunAfter` 存在 PostgreSQL。Worker 使用 `FOR UPDATE SKIP LOCKED`、五分钟租约和有限重试处理即时、延时及失败待重试任务;周期循环使用 PostgreSQL advisory lock 防止多实例重复执行。`Worker:Enabled=false` 会关闭全部四个后台循环,通常只用于测试或维护。
|
||||
|
||||
API 和 Worker 必须使用同一 PostgreSQL 数据库与一致的对象存储配置。迁移必须在两者启动前由 `Tiku.DbMigrator` 单独执行。
|
||||
|
||||
容器镜像从仓库根目录构建:
|
||||
|
||||
```bash
|
||||
docker build -f Tiku.Api/Dockerfile -t tiku-api .
|
||||
docker build -f Tiku.Worker/Dockerfile -t tiku-worker .
|
||||
```
|
||||
|
||||
API 和 Worker 应独立设置副本数与资源限制。先完成 Migration,再启动 Worker,最后开放 API 流量;不要在容器入口自动执行 Migration。
|
||||
|
||||
## 安全与网络配置
|
||||
|
||||
@@ -120,21 +132,53 @@ Production 启动至少需要核对:
|
||||
|
||||
## 对象存储与外部 Provider
|
||||
|
||||
对象存储读取 `Storage` / `Storage:AliyunOss`,也支持 `STORAGE_*` 与 `ALIYUN_OSS_*` 环境变量。当前默认实现是阿里云 OSS,并强制租户 key 前缀、上传大小和 MIME allowlist。
|
||||
对象存储读取 `Storage` / `Storage:AliyunOss`,API 与 Worker 都支持 `STORAGE_*` 与 `ALIYUN_OSS_*` 环境变量。当前默认实现是阿里云 OSS,并强制租户 key 前缀、上传大小和 MIME allowlist。租户导出使用 `application/gzip`,该类型不能从 allowlist 删除。
|
||||
|
||||
## ClamAV 资源安全扫描
|
||||
|
||||
API 和 Worker 都读取 `Security:ClamAV`:
|
||||
|
||||
```json
|
||||
{
|
||||
"Security": {
|
||||
"ClamAV": {
|
||||
"Host": "clamav",
|
||||
"Port": 3310,
|
||||
"TimeoutSeconds": 30,
|
||||
"ChunkBytes": 65536,
|
||||
"StreamMaxLength": 524288000
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Worker 使用 ClamAV `INSTREAM` 协议,不在本地落盘待扫描对象。启动校验要求 `StreamMaxLength >= Storage:MaxUploadBytes`;同时必须把 clamd 自身的 `StreamMaxLength` 配到相同或更高值。扫描结果为 FOUND 时资源标记为 Failed 并记录病毒签名;ClamAV 超时或不可用时任务保留 Pending 并退避重试。只有 `Passed` 或系统明确标记为可信的 `NotRequired` 资源可以签发访问地址。
|
||||
|
||||
身份、短信、支付、通知和 AI 的租户配置由业务后台写入 `TenantExternalProvider`;敏感值写入加密的 `TenantSecret`。全局默认配置不能绕过租户 Provider 状态和 Secret 边界。
|
||||
|
||||
## 健康检查与观测
|
||||
|
||||
- `GET /api/health`:轻量 liveness,只说明 API 进程可响应。
|
||||
- `GET /api/health/ready`:检查 PostgreSQL 和已配置 Redis;依赖未就绪时返回 503。
|
||||
- `GET /api/health/ready`:检查 PostgreSQL 和已配置 Redis;依赖未就绪时返回 503,匿名响应只包含总体状态和检查时间。
|
||||
- `GET /api/platform-admin/operations/health`:需要 `platform:operations:view`,返回 PostgreSQL、Redis、Worker heartbeat、ClamAV 和对象存储配置状态。
|
||||
- `GET /api/platform-admin/operations/workers`:查询 Worker 心跳、周期循环和 stale 状态。
|
||||
- `GET /api/platform-admin/operations/job-metrics`:查询队列状态、最老 Pending 任务与过期租约。
|
||||
- 设置 `OpenTelemetry:OtlpEndpoint` 后导出 ASP.NET Core、HTTP client 和数据库观测数据。
|
||||
- Serilog 输出结构化请求日志;数据库性能拦截器记录慢查询指标。
|
||||
|
||||
Readiness 为绿色不等于认证授权、跨租户隔离或后台任务恢复演练已通过,发布仍需执行对应集成测试。
|
||||
|
||||
## 租户归档与导出发布门禁
|
||||
|
||||
- 租户归档是逻辑归档,禁止硬删除。
|
||||
- 归档前必须存在 24 小时内成功完成的租户导出,且不能有 Processing 后台任务。
|
||||
- 导出包是 `tar.gz`,包含 manifest、租户、成员、域名和资源元数据;明确排除密码哈希、令牌、密钥明文、Data Protection keys 和全局平台数据。
|
||||
- 归档会撤销该租户授权域 Session、禁用域名并失效运行时缓存;恢复后租户为 `Suspended`,域名为 `Pending`,必须重新审核后再激活。
|
||||
- Owner 转移目标必须是已有 Active 成员,并在同一事务内同步成员角色和后台角色绑定。
|
||||
- 发布前至少演练一次导出可下载、归档阻断条件、归档、恢复和 Owner 转移。
|
||||
|
||||
## 从 RabbitMQ 版本切换
|
||||
|
||||
移除消息表的 Migration 与旧 API/Worker 不兼容。发布时使用维护窗口:停止旧 API 和 Worker,确认 RabbitMQ Consumer 已退出并备份 PostgreSQL,运行 `Tiku.DbMigrator`,再部署新 API。未消费的后台任务消息可丢弃,因为对应任务记录已经写入 `background_jobs`;安全消息不保存授权真相。
|
||||
移除消息表的 Migration 与旧 API/Worker 不兼容。发布时使用维护窗口:停止旧 API 和 Worker,确认 RabbitMQ Consumer 已退出并备份 PostgreSQL,运行 `Tiku.DbMigrator`,再部署新 API 与新 Worker。未消费的后台任务消息可丢弃,因为对应任务记录已经写入 `background_jobs`;安全消息不保存授权真相。
|
||||
|
||||
切换时不强制重置 `processing` 任务。旧租约最多五分钟后由新 API 接管。回滚需要先停止新 API,执行 Migration Down 重建空 inbox/outbox 表,再恢复 RabbitMQ 配置和旧 API/Worker;历史消息不会恢复。
|
||||
切换时不强制重置 `processing` 任务。旧租约最多五分钟后由新 Worker 接管。回滚需要先停止新 API 与 Worker,执行 Migration Down 重建空 inbox/outbox 表,再恢复 RabbitMQ 配置和旧 API/Worker;历史消息不会恢复。
|
||||
|
||||
Reference in New Issue
Block a user