S3 PutObject正常但List/Delete操作失败问题排查
核心问题1:ListBucket的资源配置错误
s3:ListBucket是针对S3桶本身的操作,而非桶内对象路径的操作,所以它对应的资源必须是桶的完整ARN:arn:aws:s3:::<bucket_name>,而不是你配置的arn:aws:s3:::<bucket_name>/<path>/。
你当前的Policy把ListBucket的资源限定在了路径级别,AWS会判定你没有对桶执行ListBucket的权限,这就是调用ListObjects时提示AccessDenied的直接原因。
核心问题2:Delete操作的双重权限要求
你用bucket.objects.filter(Prefix=path_in_bucket).delete()时,boto3的执行逻辑是:
- 第一步:调用ListObjectsV2(对应
s3:ListBucket权限)获取符合Prefix的所有对象 - 第二步:对每个对象调用DeleteObject(对应
s3:DeleteObject权限)
除了ListBucket的资源配置错误外,你的DeleteObject资源也有问题:当前配置的arn:aws:s3:::<bucket_name>/<path>/只能匹配到路径本身(S3里路径是一个特殊的空对象),而桶内真实的对象是arn:aws:s3:::<bucket_name>/<path>/*格式的,所以需要把DeleteObject的资源改成带/*的路径,才能覆盖到路径下的所有对象。
修正后的Policy示例
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:DeleteObject", "s3:GetObject" ], "Resource": "arn:aws:s3:::<bucket_name>/<path>/*" }, { "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::<bucket_name>", "Condition": { "StringLike": { "s3:prefix": "<path>/*" } } } ] }
这里给ListBucket加上了s3:prefix条件,确保只能列出指定路径下的对象,而非整个桶的内容,兼顾权限最小化原则。
额外说明
PutObject能正常工作,是因为你上传的对象路径正好匹配了arn:aws:s3:::<bucket_name>/<path>/*(可能是Kotlin代码变量替换时自动补了/*),资源匹配正确所以操作成功。
内容的提问来源于stack exchange,提问作者leoOrion

