安全与风控
配置 Tigris 对象存储的访问密钥、CORS…
在 Tigris 对象存储中配置访问密钥、CORS 规则、桶可见性和预签名 URL 安全时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
配置 Tigris 对象存储的访问密钥、特定
解决思路
- 如果 `tigris help` 不可用,执行 `npm install -g @tigrisdata/cli` 安装 Tigris CLI;若需安装,告知用户正在安装 `@tigrisdata/cli`。
- 创建密钥:`tigris access-keys create "my-key"`。
- 列出密钥:`tigris access-keys list`。
- 将密钥分配给桶:`tigris access-keys assign <tid> --bucket <name> --role Editor`。
- 撤销密钥:`tigris access-keys delete <tid>`。
- 设置 CORS:`tigris buckets cors set <bucket> --config cors.json`。
- 获取 CORS:`tigris buckets cors get <bucket>`。
- 删除 CORS:`tigris buckets cors delete <bucket>`。
- 创建访问密钥:`tigris access-keys create "production-app-key"`;保存输出的 `Access Key ID` 和 `Secret Access Key`,后者只显示一次。
- 分配 Editor 角色:`tigris access-keys assign tid_xxx --bucket my-app-uploads --role Editor`(读+写+删,用于上传/修改文件的应用服务器)。
- 分配 ReadOnly 角色:`tigris access-keys assign tid_xxx --bucket my-app-uploads --role ReadOnly`(只读,用于只读取/提供文件的服务)。
- 按用途拆分密钥:为应用服务器创建密钥并分配 `--bucket app-uploads --role Editor`。
- 按用途拆分密钥:为 CDN/读取服务创建密钥并分配 `--bucket app-uploads --role ReadOnly`。
- 按用途拆分密钥:为备份创建密钥并分配 `--bucket app-backups --role Editor`。
- 零停机轮换:创建新密钥 `tigris access-keys create "production-app-key-v2"`,并执行 `tigris access-keys assign tid_new --bucket my-app-uploads --role Editor`。
- 用新密钥更新应用环境变量 `TIGRIS_STORAGE_ACCESS_KEY_ID` / `TIGRIS_STORAGE_SECRET_ACCESS_KEY` 并部署。
- 验证应用在新密钥下工作。
- 撤销旧密钥:`tigris access-keys delete tid_old`。
- 审计:`tigris access-keys list` 列出所有访问密钥。
- 审计:`tigris access-keys info tid_xxx` 检查某个密钥可访问哪些桶。
- 浏览器直传/预签名 PUT URL 需要配置 CORS。
- 设置 CORS:`tigris buckets cors set my-app-uploads --config cors.json`。
- 开发环境规则:`AllowedOrigins` 为 `http://localhost:3000`、`http://localhost:5173`;`AllowedMethods` 为 `GET`、`PUT`、`POST`、`DELETE`、`HEAD`;`AllowedHeaders` 为 `*`;`ExposeHeaders` 为 `ETag`、`Content-Length`;`MaxAgeSeconds` 为 3600。
- 生产环境规则:`AllowedOrigins` 为 `https://myapp.com`、`https://www.myapp.com`;`AllowedMethods` 为 `GET`、`PUT`、`HEAD`;`AllowedHeaders` 为 `Content-Type`、`Content-MD5`、`Content-Disposition`;`ExposeHeaders` 为 `ETag`;`MaxAgeSeconds` 为 86400。
- 开发+生产合并规则:`AllowedOrigins` 为 `https://myapp.com`、`https://www.myapp.com`、`http://localhost:3000`;`AllowedMethods` 为 `GET`、`PUT`、`POST`、`DELETE`、`HEAD`;`AllowedHeaders` 为 `*`;`ExposeHeaders` 为 `ETag`、`Content-Length`;`MaxAgeSeconds` 为 3600。
- 宽松规则:`AllowedOrigins` 为 `*`;`AllowedMethods` 为 `GET`;`AllowedHeaders` 为 `*`;`MaxAgeSeconds` 为 86400。警告:仅对真正公开只读内容使用 `*` origin,禁止允许任意 origin 的 `PUT`/`DELETE`。
- 验证 CORS:`tigris buckets cors get my-app-uploads`。
- 用 curl 测试:`curl -I -H "Origin: https://myapp.com" -H "Access-Control-Request-Method: PUT" -X OPTIONS https://my-app-uploads.t3.storage.dev/test`。
- 私有桶(默认):只有认证请求可读,通过预签名 URL 访问,用于用户文档/敏感文件。
- 公开桶:任何有 URL 的人可读,直接 URL 访问,用于静态资源/公开图片/CDN 内容。
- 创建公开桶:`tigris buckets create my-public-assets --public`。
- 创建私有桶:`tigris buckets create my-private-docs`。
- 下载预签名 URL 过期时间设 5-60 分钟。
- 上传预签名 URL 过期时间设 5-15 分钟。
- 作用域:每个文件一个 URL,每个 URL 一个操作。
- TypeScript 短时下载 URL:`const { data } = await getPresignedUrl("documents/report.pdf", { operation: "get", expiresIn: 300 });`。
- TypeScript 短时上传 URL 并限制内容类型:`const { data } = await getPresignedUrl("uploads/photo.jpg", { operation: "put", expiresIn: 600, contentType: "image/jpeg" });`。
- 禁止:过期时间超过 24 小时。
- 禁止:为整个桶前缀生成预签名 URL。
- 禁止:在公开渠道分享预签名 URL(它们是密钥)。
- 禁止:把预签名 URL 当永久链接(改用公开桶 URL)。
- `.env` 中设置 `TIGRIS_STORAGE_ACCESS_KEY_ID=tid_xxx` 和 `TIGRIS_STORAGE_SECRET_ACCESS_KEY=tsec_yyy`,永不提交。
- `.gitignore` 必须包含 `.env`、`.env.local`、`.env.*.local`。
- CI/CD 使用平台密钥管理:GitHub Actions `gh secret set TIGRIS_STORAGE_ACCESS_KEY_ID`、`gh secret set TIGRIS_STORAGE_SECRET_ACCESS_KEY`。
- Vercel:`vercel env add TIGRIS_STORAGE_ACCESS_KEY_ID`。
- Fly.io:`fly secrets set TIGRIS_STORAGE_ACCESS_KEY_ID=tid_xxx`。
- 检查代码中无密钥:搜索 `tid_` 和 `tsec_`。
- 检查 `.env` 在 `.gitignore` 中。
- 检查密钥限定到桶,无未分配全局访问的密钥。
- 检查角色匹配需求,只读服务使用 `ReadOnly`。
- 检查 CORS 不过度宽松,无带写方法的 `*` origin。
- 检查预签名 URL 过期短,大多数场景低于 1 小时。
- 检查未使用密钥已撤销,无前团队成员或旧部署遗留密钥。
- 检查每个环境独立密钥,dev/staging/production 使用不同密钥。
- 密钥泄露后立即撤销:`tigris access-keys delete tid_compromised`。
- 创建替换密钥:`tigris access-keys create "replacement-key"`,并分配 `tigris access-keys assign tid_new --bucket my-bucket --role Editor`。
- 用新密钥更新所有部署(`.env`、CI/CD secrets、部署配置)。
- 审计访问:`tigris ls t3://my-bucket --recursive -l | sort -k4 -r | head -50`。
- 若密钥提交到 git,轮换并视整个 git 历史为已泄露,用 `git-filter-repo` 移除。
- 始终:每个环境和用途使用独立密钥。
- 始终:将密钥分配到特定桶并使用最小必需角色。
- 始终:定期轮换密钥(建议每季度)。
- 始终:生产 CORS 设置为特定 origin。
- 始终:使用短时预签名 URL。
- 绝不:提交密钥到 git。
- 绝不:所有环境使用同一密钥。
- 绝不:CORS 使用 `*` 且允许写方法。
- 绝不:公开分享预签名 URL。
- 绝不:保留未使用密钥为 active。
- CORS preflight 失败:检查 `AllowedOrigins` 包含精确 origin(含协议)。
- 密钥轮换后 Access denied:确保新密钥已分配到桶并具有正确角色。
- Secret key 丢失:无法恢复,创建新密钥并重新分配。
- 浏览器上传静默失败:检查 CORS 配置的 `AllowedMethods` 包含 `PUT`。
适用边界 · 注意事项
- 未使用 Tigris 对象存储或不能安装 `@tigrisdata/cli` 时不适用。
- 如果只想做通用 S3 兼容配置且不使用 Tigris CLI/角色/命令,应使用对应云厂商或 S3 工具。
- 不涉及浏览器直传、预签名 URL、公开桶或密钥轮换时,不需要完整套用本经验。