tigris-security-access-control
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTigris Security & Access Control
Tigris 安全与访问控制
Configure access keys, CORS rules, bucket visibility, and presigned URL security for Tigris object storage. Covers key lifecycle management, role-based access, and security auditing.
为Tigris对象存储配置访问密钥、CORS规则、存储桶可见性和预签名URL安全,涵盖密钥生命周期管理、基于角色的访问控制和安全审计。
Prerequisites
前置条件
Before doing anything else, install the Tigris CLI if it's not already available:
bash
tigris help || npm install -g @tigrisdata/cliIf you need to install it, tell the user: "I'm installing the Tigris CLI () so we can work with Tigris object storage."
@tigrisdata/cli在进行任何操作前,如果还没有安装Tigris CLI,请先安装:
bash
tigris help || npm install -g @tigrisdata/cli如果需要安装,请告知用户:“我正在安装Tigris CLI (),以便我们使用Tigris对象存储。”
@tigrisdata/cliQuick Reference
快速参考
| Operation | Command |
|---|---|
| Create key | |
| List keys | |
| Assign to bucket | |
| Revoke key | |
| Set CORS | |
| Get CORS | |
| Remove CORS | |
| 操作 | 命令 |
|---|---|
| 创建密钥 | |
| 列出密钥 | |
| 分配到存储桶 | |
| 撤销密钥 | |
| 设置CORS | |
| 获取CORS | |
| 删除CORS | |
Access Key Lifecycle
访问密钥生命周期
Create
创建
bash
tigris access-keys create "production-app-key"bash
tigris access-keys create "production-app-key"Output:
输出:
Access Key ID: tid_xxx
Access Key ID: tid_xxx
Secret Access Key: tsec_yyy ← shown ONLY once, save immediately
Secret Access Key: tsec_yyy ← 仅展示一次,请立即保存
undefinedundefinedAssign to Bucket
分配到存储桶
bash
undefinedbash
undefinedEditor: read + write + delete
Editor: 读 + 写 + 删除
tigris access-keys assign tid_xxx --bucket my-app-uploads --role Editor
tigris access-keys assign tid_xxx --bucket my-app-uploads --role Editor
ReadOnly: read only
ReadOnly: 仅可读
tigris access-keys assign tid_xxx --bucket my-app-uploads --role ReadOnly
| Role | Read | Write | Delete | Use When |
|------|------|-------|--------|----------|
| `Editor` | Yes | Yes | Yes | App servers that upload/modify files |
| `ReadOnly` | Yes | No | No | Services that only read/serve files |tigris access-keys assign tid_xxx --bucket my-app-uploads --role ReadOnly
| 角色 | 读 | 写 | 删除 | 适用场景 |
|------|------|-------|--------|----------|
| `Editor` | 是 | 是 | 是 | 需要上传/修改文件的应用服务器 |
| `ReadOnly` | 是 | 否 | 否 | 仅需要读取/分发文件的服务 |Scope Keys Narrowly
缩小密钥权限范围
Create separate keys for different concerns:
bash
undefined为不同用途创建独立的密钥:
bash
undefinedKey for the app server (read/write to uploads bucket)
应用服务器专用密钥(对上传存储桶有读写权限)
tigris access-keys create "app-server"
tigris access-keys assign tid_app --bucket app-uploads --role Editor
tigris access-keys create "app-server"
tigris access-keys assign tid_app --bucket app-uploads --role Editor
Key for the CDN/read service (read-only)
CDN/读取服务专用密钥(只读权限)
tigris access-keys create "cdn-reader"
tigris access-keys assign tid_cdn --bucket app-uploads --role ReadOnly
tigris access-keys create "cdn-reader"
tigris access-keys assign tid_cdn --bucket app-uploads --role ReadOnly
Key for backups (write to backup bucket only)
备份服务专用密钥(仅对备份存储桶有写入权限)
tigris access-keys create "backup-writer"
tigris access-keys assign tid_bak --bucket app-backups --role Editor
undefinedtigris access-keys create "backup-writer"
tigris access-keys assign tid_bak --bucket app-backups --role Editor
undefinedRotate Keys (Zero Downtime)
密钥轮换(零停机)
bash
undefinedbash
undefined1. Create new key
1. 创建新密钥
tigris access-keys create "production-app-key-v2"
tigris access-keys assign tid_new --bucket my-app-uploads --role Editor
tigris access-keys create "production-app-key-v2"
tigris access-keys assign tid_new --bucket my-app-uploads --role Editor
2. Update application environment with new key
2. 使用新密钥更新应用环境变量
(deploy with new TIGRIS_STORAGE_ACCESS_KEY_ID / SECRET)
(部署时使用新的 TIGRIS_STORAGE_ACCESS_KEY_ID / SECRET)
3. Verify app works with new key
3. 验证应用使用新密钥运行正常
4. Revoke old key
4. 撤销旧密钥
tigris access-keys delete tid_old
undefinedtigris access-keys delete tid_old
undefinedList and Audit
列出与审计
bash
undefinedbash
undefinedList all access keys
列出所有访问密钥
tigris access-keys list
tigris access-keys list
Check which buckets a key can access
查看某个密钥可访问的存储桶
tigris access-keys info tid_xxx
---tigris access-keys info tid_xxx
---CORS Configuration
CORS配置
CORS is required for browser-based uploads (direct uploads, presigned PUT URLs).
基于浏览器的上传(直接上传、预签名PUT URL)需要配置CORS。
Set CORS Rules
设置CORS规则
bash
tigris buckets cors set my-app-uploads --config cors.jsonbash
tigris buckets cors set my-app-uploads --config cors.jsonDevelopment (Localhost)
开发环境(本地主机)
json
{
"CORSRules": [
{
"AllowedOrigins": ["http://localhost:3000", "http://localhost:5173"],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag", "Content-Length"],
"MaxAgeSeconds": 3600
}
]
}json
{
"CORSRules": [
{
"AllowedOrigins": ["http://localhost:3000", "http://localhost:5173"],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag", "Content-Length"],
"MaxAgeSeconds": 3600
}
]
}Production (Specific Domain)
生产环境(指定域名)
json
{
"CORSRules": [
{
"AllowedOrigins": ["https://myapp.com", "https://www.myapp.com"],
"AllowedMethods": ["GET", "PUT", "HEAD"],
"AllowedHeaders": ["Content-Type", "Content-MD5", "Content-Disposition"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 86400
}
]
}json
{
"CORSRules": [
{
"AllowedOrigins": ["https://myapp.com", "https://www.myapp.com"],
"AllowedMethods": ["GET", "PUT", "HEAD"],
"AllowedHeaders": ["Content-Type", "Content-MD5", "Content-Disposition"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 86400
}
]
}Combined Dev + Production
开发+生产合并配置
json
{
"CORSRules": [
{
"AllowedOrigins": [
"https://myapp.com",
"https://www.myapp.com",
"http://localhost:3000"
],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag", "Content-Length"],
"MaxAgeSeconds": 3600
}
]
}json
{
"CORSRules": [
{
"AllowedOrigins": [
"https://myapp.com",
"https://www.myapp.com",
"http://localhost:3000"
],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag", "Content-Length"],
"MaxAgeSeconds": 3600
}
]
}Permissive (Any Origin)
宽松配置(任意来源)
json
{
"CORSRules": [
{
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET"],
"AllowedHeaders": ["*"],
"MaxAgeSeconds": 86400
}
]
}Warning: Only use origins for truly public, read-only content. Never allow / from any origin.
"*"PUTDELETEjson
{
"CORSRules": [
{
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET"],
"AllowedHeaders": ["*"],
"MaxAgeSeconds": 86400
}
]
}警告: 仅当内容是完全公开的只读内容时才使用来源,绝对不允许允许任意来源发起/请求。
"*"PUTDELETEVerify CORS
验证CORS
bash
undefinedbash
undefinedCheck current CORS config
查看当前CORS配置
tigris buckets cors get my-app-uploads
tigris buckets cors get my-app-uploads
Test with curl
使用curl测试
curl -I -H "Origin: https://myapp.com"
-H "Access-Control-Request-Method: PUT"
-X OPTIONS
https://my-app-uploads.t3.storage.dev/test
-H "Access-Control-Request-Method: PUT"
-X OPTIONS
https://my-app-uploads.t3.storage.dev/test
---curl -I -H "Origin: https://myapp.com"
-H "Access-Control-Request-Method: PUT"
-X OPTIONS
https://my-app-uploads.t3.storage.dev/test
-H "Access-Control-Request-Method: PUT"
-X OPTIONS
https://my-app-uploads.t3.storage.dev/test
---Public vs Private Buckets
公开vs私有存储桶
| Setting | Who Can Read | URL Access | Use For |
|---|---|---|---|
| Private (default) | Only authenticated requests | Presigned URLs | User documents, sensitive files |
| Public | Anyone with URL | Direct URL | Static assets, public images, CDN content |
bash
undefined| 设置 | 可读取对象 | 访问方式 | 适用场景 |
|---|---|---|---|
| 私有(默认) | 仅认证通过的请求 | 预签名URL | 用户文档、敏感文件 |
| 公开 | 所有持有URL的用户 | 直接URL | 静态资源、公开图片、CDN内容 |
bash
undefinedCreate public bucket
创建公开存储桶
tigris buckets create my-public-assets --public
tigris buckets create my-public-assets --public
Create private bucket (default)
创建私有存储桶(默认)
tigris buckets create my-private-docs
---tigris buckets create my-private-docs
---Presigned URL Security
预签名URL安全
Best Practices
最佳实践
| Parameter | Recommendation |
|---|---|
| Expiration (download) | 5-60 minutes for most use cases |
| Expiration (upload) | 5-15 minutes |
| Scope | One URL per file, one operation per URL |
typescript
import { getPresignedUrl } from "@tigrisdata/storage";
// Short-lived download URL
const { data } = await getPresignedUrl("documents/report.pdf", {
operation: "get",
expiresIn: 300, // 5 minutes
});
// Short-lived upload URL with content type restriction
const { data } = await getPresignedUrl("uploads/photo.jpg", {
operation: "put",
expiresIn: 600,
contentType: "image/jpeg", // Client must upload this type
});| 参数 | 建议 |
|---|---|
| 过期时间(下载) | 大多数场景下设置5-60分钟 |
| 过期时间(上传) | 5-15分钟 |
| 适用范围 | 一个URL对应一个文件,一个URL仅支持一种操作 |
typescript
import { getPresignedUrl } from "@tigrisdata/storage";Never Do
短有效期下载URL
- Set expiration longer than 24 hours
- Generate presigned URLs for entire bucket prefixes
- Share presigned URLs in public channels (they're secrets)
- Use presigned URLs as permanent links (use public bucket URLs instead)
const { data } = await getPresignedUrl("documents/report.pdf", {
operation: "get",
expiresIn: 300, // 5分钟
});
Environment Variable Security
限制内容类型的短有效期上传URL
bash
undefinedconst { data } = await getPresignedUrl("uploads/photo.jpg", {
operation: "put",
expiresIn: 600,
contentType: "image/jpeg", // 客户端必须上传该类型文件
});
undefined.env (never commit this file)
禁止操作
TIGRIS_STORAGE_ACCESS_KEY_ID=tid_xxx
TIGRIS_STORAGE_SECRET_ACCESS_KEY=tsec_yyy
```bash- 过期时间设置超过24小时
- 为整个存储桶前缀生成预签名URL
- 在公共渠道分享预签名URL(它们属于机密信息)
- 将预签名URL用作永久链接(请改用公开存储桶URL)
.gitignore (must include)
环境变量安全
.env
.env.local
.env.*.local
For CI/CD, use your platform's secrets management:
```bashbash
undefinedGitHub Actions
.env(永远不要提交该文件)
gh secret set TIGRIS_STORAGE_ACCESS_KEY_ID
gh secret set TIGRIS_STORAGE_SECRET_ACCESS_KEY
TIGRIS_STORAGE_ACCESS_KEY_ID=tid_xxx
TIGRIS_STORAGE_SECRET_ACCESS_KEY=tsec_yyy
```bashVercel
.gitignore(必须包含)
vercel env add TIGRIS_STORAGE_ACCESS_KEY_ID
.env
.env.local
.env.*.local
对于CI/CD场景,请使用对应平台的机密管理功能:
```bashFly.io
GitHub Actions
fly secrets set TIGRIS_STORAGE_ACCESS_KEY_ID=tid_xxx
---gh secret set TIGRIS_STORAGE_ACCESS_KEY_ID
gh secret set TIGRIS_STORAGE_SECRET_ACCESS_KEY
Security Audit Checklist
Vercel
- No keys in code — search for and
tid_in your repotsec_ - in
.env— credentials never committed.gitignore - Keys scoped to buckets — no unassigned keys with global access
- Roles match need — read-only services use role
ReadOnly - CORS not overly permissive — no origin with write methods
"*" - Presigned URLs have short expiry — under 1 hour for most cases
- Unused keys revoked — no stale keys from former team members or old deployments
- Separate keys per environment — dev/staging/production use different keys
vercel env add TIGRIS_STORAGE_ACCESS_KEY_ID
Key Compromise Response
Fly.io
If an access key is exposed (committed to git, leaked in logs, etc.):
bash
undefinedfly secrets set TIGRIS_STORAGE_ACCESS_KEY_ID=tid_xxx
---1. Immediately revoke the compromised key
安全审计清单
tigris access-keys delete tid_compromised
- 代码中无密钥 — 在代码仓库中搜索和
tid_确认没有泄露tsec_ - 已加入
.env— 凭证永远不会被提交.gitignore - 密钥权限限定到指定存储桶 — 没有未分配的全局访问权限密钥
- 角色与需求匹配 — 只读服务使用角色
ReadOnly - CORS权限不过度宽松 — 没有允许来源搭配写入方法的配置
"*" - 预签名URL有效期短 — 大多数场景下有效期不超过1小时
- 未使用的密钥已撤销 — 没有来自前团队成员或旧部署的过期密钥
- 不同环境使用独立密钥 — 开发/测试/生产环境使用不同的密钥
2. Create a new key
密钥泄露应对流程
tigris access-keys create "replacement-key"
tigris access-keys assign tid_new --bucket my-bucket --role Editor
如果访问密钥被泄露(提交到git、日志泄露等):
bash
undefined3. Update all deployments with the new key
1. 立即撤销泄露的密钥
(update .env, CI/CD secrets, deployment configs)
—
4. Audit access — check for unauthorized uploads/downloads
—
tigris ls t3://my-bucket --recursive -l | sort -k4 -r | head -50
tigris access-keys delete tid_compromised
5. If key was committed to git, rotate and consider the entire
2. 创建新密钥
git history compromised — use git-filter-repo to remove it
—
---tigris access-keys create "replacement-key"
tigris access-keys assign tid_new --bucket my-bucket --role Editor
Critical Rules
3. 使用新密钥更新所有部署配置
—
(更新.env、CI/CD机密、部署配置)
—
4. 审计访问记录 — 检查是否有未授权的上传/下载操作
Always: Create separate keys per environment and concern | Assign keys to specific buckets with minimum required role | Rotate keys periodically (quarterly recommended) | Set CORS to specific origins in production | Use short-lived presigned URLs
Never: Commit keys to git | Use a single key for all environments | Set CORS to with write methods | Share presigned URLs publicly | Keep unused keys active
"*"tigris ls t3://my-bucket --recursive -l | sort -k4 -r | head -50
Known Issues
5. 如果密钥已经被提交到git,除了轮换密钥外还需认为整个git历史已被泄露 — 使用git-filter-repo移除泄露的密钥
| Problem | Fix |
|---|---|
| CORS preflight fails | Check |
| "Access denied" after key rotation | Ensure new key is assigned to bucket with correct role |
| Secret key lost | Cannot recover — create new key and reassign |
| Browser upload fails silently | Check CORS config includes |
---Related Skills
关键规则
- file-storage — CLI setup and access key creation
- tigris-s3-migration — CORS and credential setup during migration
必须遵守: 为不同环境和不同用途创建独立密钥 | 为密钥分配特定存储桶的最小必要角色 | 定期轮换密钥(建议每季度一次) | 生产环境下CORS仅允许指定来源 | 使用短有效期的预签名URL
绝对禁止: 将密钥提交到git | 所有环境共用同一个密钥 | CORS配置来源搭配写入方法 | 公开分享预签名URL | 保留未使用的活跃密钥
"*"Official Documentation
已知问题
- Tigris: https://www.tigrisdata.com/docs/
| 问题 | 解决方案 |
|---|---|
| CORS预检请求失败 | 检查 |
| 密钥轮换后提示“访问被拒绝” | 确认新密钥已分配到对应存储桶且拥有正确角色 |
| 密钥丢失 | 无法恢复 — 创建新密钥并重新分配权限 |
| 浏览器上传无提示失败 | 检查CORS配置的 |
—
相关技能
—
- file-storage — CLI安装和访问密钥创建
- tigris-s3-migration — 迁移过程中的CORS和凭证配置
—
官方文档
—
- Tigris: https://www.tigrisdata.com/docs/