S3:对象身份、权限与版本机制
普通用途桶、IAM 与凭据链
范围与版本族
本系列研究 AWS Amazon S3 的 general purpose bucket,使用 Python 3.10+ 与 boto3>=1.40,<2 的 API 合同。不涵盖 S3 Express directory bucket、Outposts 或所有标称“S3 兼容”的产品;这些目标在端点、版本、条件请求和授权上可能不同。2026-10-17 核对官方中英文 API 和 SDK 文档,依赖范围是教学声明,没有安装、解析锁文件或宣称最新。所有示例未执行,本轮没有访问账号、调用 API、启动服务或模拟器。
前置是 HTTP、Python 文件流、环境变量与最小权限概念。推荐按本篇、机制、完整 CLI、维护、复习阅读。读者没有云资源时也能完成纸面推演,后文安装和运行命令仅供读者自行选择。
Bucket、Key 与 Region
S3 对象由 Bucket、Key 和可选 VersionId 定位。reports/a.json 是一个键,普通用途桶中的斜杠不代表 POSIX 目录,prefix 不是访问权限。复制并删除一个前缀不是原子重命名,分页列表也不是跨对象事务。业务记录最好保存 Bucket、Key、VersionId、大小和业务摘要,短期预签名 URL 是展示时生成的能力,不应充当永久对象身份。
S3 Region 参与端点选择和 SigV4 签名,桶名称正确并不意味着错误区域也能直接操作。客户端设 project 一类概念对 AWS 不适用;账号、身份策略、资源策略和区域是不同维度。示例只调用 AWS 原生端点,不开放自定义 endpoint_url 参数,避免读者把其他产品的保证当作 S3 原生合同。
凭据链与 IAM
S3 Boto3 凭据链可从显式参数、环境变量、角色或 Web Identity 提供器、共享配置以及运行环境角色等位置解析身份。示例不传 AK/SK,让 SDK 按自身链查找;陈旧环境密钥可能优先于读者期望的 profile,排错必须确认实际来源。临时凭据需要完整 session token;生产优先角色和可刷新提供器,不把长期用户密钥写进源码。官方 Boto3 credentials是顺序和提供器的依据。
S3 IAM 最小权限中,s3:ListBucket 绑定桶 ARN,可用 s3:prefix 条件限制列举;s3:GetObject、s3:PutObject 绑定对象 ARN。按版本读写和清理另审 s3:GetObjectVersion、s3:DeleteObjectVersion,版本清单需要 s3:ListBucketVersions。IAM 身份策略与桶策略的显式拒绝都要考虑;权限边界、组织策略及跨账号信任也可能限制访问。SSE-KMS 还需密钥策略与相应 KMS 动作,不能只授 S3 权限。
CLI 入口和计费
S3 CLI 在此指仓库 examples/s3/object_cli.py,不是 AWS CLI 的命令别名。list 使用 list_objects_v2 paginator,put 使用普通 PutObject,get 读取 StreamingBody,sign 本地生成预签名 URL,delete 必须明确版本。程序不创建桶、不更改 IAM,单次上传限制 1 MiB,但 list 页数、下载量和历史容量并无限制。
S3 成本包括请求、存储、外网传输、历史版本、未完成分片及冷存储取回。1 MiB 限制不是预算上限,签名链接也不提供免费读取。练习:只允许上传者为何不必给 DeleteObjectVersion?答案是上传能力与永久销毁历史内容应分离,清理由受控维护身份执行,不能为运行全部子命令而扩大生产应用权限。
官方来源
核对:S3 版本控制、PutObject API、Boto3 S3 API。这些文档描述 AWS 原生能力;兼容实现要另查自己的合同与版本。
VersionId、条件写、校验与分片提交
VersionId 与 delete marker
前置:对象身份。S3 VersionId 是不透明的版本标识,开启版本控制后同键新写产生新版本。普通 DELETE 不带 VersionId 时通常创建 delete marker,让当前 GET 表现为不存在;旧版本仍可读取、占容量。带 VersionId 的 DELETE 永久删除选定版本,带删除标记自身的 ID 删除则可能让旧内容重新成为当前可见版本。暂停版本时 null 版本行为需要单独分析,不能等同从未启用。官方版本控制解释版本保留边界。
Object Lock 是另一项保护,版本控制并不自动阻止永久删除。恢复时先取得完整版本清单,包括 DeleteMarkers 和 Versions,按明确 ID 读取内容、核对摘要,再决定复制旧版本为新版本或移除标记;普通 list_objects_v2 没有展示全部历史。CLI 的 delete 强制版本 ID,只做精确删除,绝不暗中“清空 key”。
IfMatch、IfNoneMatch 与竞争
S3 条件写中 IfNoneMatch='*' 表达只有目标当前不存在时才创建,冲突可返回 412;若当前版本是删除标记,其效果应按普通用途桶条件写合同理解,而不是检测所有历史版本均不存在。IfMatch 用 ETag 表达“仍与我观察到的内容标识相同才写入”,不等同按 VersionId 排序,也不是多对象事务。并发删除与条件写交错还可能出现 409 ConditionalRequestConflict。PutObject API给出两类条件及错误。
先 HEAD 再普通 PUT 不是原子检查;必须让服务端在写入请求中检查条件。412 应重新读取并评估业务冲突,409 应按 API 要求重新获取状态或重启相应上传,不能把所有响应统一无限重试。ETag 的并发用途不要求它是全文 MD5,但也不意味着它具备完整版本身份:若业务需要准确引用某一次写入,仍保存 VersionId。示例用 UUID key 加 IfNoneMatch,不提供覆盖命令。
校验算法与 ETag
S3 校验使用显式 ChecksumAlgorithm 和相应编码字段;本示例计算 SHA-256 后以 Base64 的原始摘要传 ChecksumSHA256,服务端可据此拒绝传输不一致。不能把十六进制摘要直接放入该字段。ETag 在分片或部分加密场景并不等于全文 MD5,故不能作为统一内容摘要。算法名也不能从 OSS CRC64 或 GCS CRC32C 推导出来。官方上传完整性是校验依据。
下载通过 ChecksumMode='ENABLED' 请求校验元数据,SDK 对适用响应的验证仍依赖具体版本和算法;范围读取或只读部分流不能作为全文证明。业务摘要另行保存并完整比较。SDK 校验验证传输,不证明业务收到的是正确报告,也不防止有权限者上传错误内容。
SigV4 与预签名 URL
S3 SigV4 绑定方法、区域、服务、资源和参与签名的字段。generate_presigned_url 在本地形成限时 GET 能力,包含 VersionId 才能固定某个历史版本;临时凭据先失效会缩短实际寿命。收到链接的人可在有效期内重放,链接不是一次性票据,也不保证对象存在。客户端改变已签头、路径编码或 Host 可能破坏签名,代理不能任意重写。
生成链接前先校验业务身份、对象归属和允许的有效期;不要在日志或分析系统收集完整 query。签名成功而远端403可能来自权限、显式拒绝、过期或 KMS,并不矛盾。示例固定 SigV4、五分钟 GET,签名不自动探测远端权限。Boto3 S3 文档提供方法入口。
Multipart Upload
S3 分片上传以 CreateMultipartUpload 获得 UploadId,逐段上传并记录 PartNumber 与 ETag,CompleteMultipartUpload 提交清单后才产生完整对象。未完成分片占空间,不会因为普通对象 list 为空而消失;应使用 AbortMultipartUpload 或生命周期清理。分片号、大小、校验算法与提交结果都需要检查点,不能把不同源文件的分片拼成同一上传。
普通 PUT 的重试与分片 Complete 的重试要按各自合同处理,条件冲突时可能需要重新初始化整个任务;收到响应前断线不能直接断定失败。CLI 限制小文件、不使用 transfer manager,不声称具备分片性能。练习:保留所有版本是否消除了上传冲突?答案:没有,它保存内容历史,业务仍必须判断哪个结果应成为已发布引用。
继续阅读
- 应用实践
- 知识专题