源存储桶和目标存储桶位于同一区域但不同的 AWS 账户。失败的复制代码:
import boto3
from datetime import datetime
assumed_role = boto3.client('sts').assume_role(
RoleArn='arn:aws:iam::DESTACCT:role/copy-role',
RoleSessionName='RoleSessionName' + datetime.now().strftime('%Y%M%d%H%m%s'))
args = {
'aws_access_key_id': assumed_role['Credentials']['AccessKeyId'],
'aws_secret_access_key': assumed_role['Credentials']['SecretAccessKey'],
'aws_session_token': assumed_role['Credentials']['SessionToken']}
session = boto3.Session(**args)
dest_bucket = session.resource('s3').Bucket('dest-bucket')
copy_source = {'Key': 'source-prefix/someobject', 'Bucket': 'source-bucket'}
dest_bucket.copy(CopySource=copy_source, Key='dest-prefix/someobject')
[...backtrace...]
botocore.exceptions.ClientError: An error occurred (403) when calling the HeadObject operation: Forbidden
copy-role
的权限:
{
"Action": "s3:Put*",
"Effect": "Allow",
"Resource": "arn:aws:s3:::dest-bucket/dest-prefix/*"
}
{
"Action": ["s3:List*","s3:Get*"],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::source-bucket/source-prefix/*",
"arn:aws:s3:::source-bucket/source-prefix"
]
}
source-bucket
在其存储桶策略中包含以下条款:
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::DESTACCT:role/copy-role"
},
"Action": "s3:List*",
"Resource": "arn:aws:s3:::source-bucket"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::DESTACCT:role/copy-role"
},
"Action": [
"s3:List*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::source-bucket/source-prefix/*",
"arn:aws:s3:::source-bucket/source-prefix"
]
}
我从 copy() 文档中注意到以下内容:
SourceClient(botocore 或 boto3 客户端)——用于源对象上可能发生的操作的客户端。例如,此客户端用于确定副本大小的 head_object。如果没有提供客户端,则使用当前客户端作为源对象的客户端。
但是,似乎没有必要,因为
copy-role
是允许的 s3:Get*
和 s3:List*
上的 source-bucket/source-prefix
。
我记录了所有 HTTP 流量,并确认失败的 HEAD 操作是针对源存储桶的:
HEAD /source-prefix/someobject HTTP/1.1
Host: source-bucket.s3.amazonaws.com
我怀疑问题出在源存储桶上的存储桶策略的这一部分:
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::DESTACCT:role/copy-role"
},
"Action": [
"s3:List*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::source-bucket/source-prefix/*",
"arn:aws:s3:::source-bucket/source-prefix"
]
}
它正在授予
ListBucket
权限,但 ListBucket
需要存储桶本身的权限,而不是存储桶内的前缀。
使用存储桶策略示例 - Amazon Simple Storage Service 中的示例,您可以将其更改为:
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::DESTACCT:role/copy-role"
},
"Action": "s3:s3:ListBucket",
"Resource": "arn:aws:s3:::source-bucket",
"Condition": {
"StringLike": {
"s3:prefix": ["source-prefix/*"]
}
}
}
您可能需要在 IAM 角色中执行类似的操作。