我有一个非常典型的用例,其中我在AWS账户中拥有授予我的角色(1234567890-不受我控制),以从其S3存储桶(“ remote_bucket”)读取数据。我可以从远程存储桶中读取数据很好,但是我再也无法将其转储到我自己的存储桶中,因为假设另一个AWS账户中的角色“隐藏”了我自己账户中的资源。最后一行因错误而失败。该如何解决?
import boto3
# Create IAM client and local session
sts = boto3.client('sts')
local_sess = boto3.Session()
s3_local = local_sess.resource('s3')
role_to_assume_arn='arn:aws:iam::1234567890:role/s3_role'
role_session_name='test'
# Assume role in another account to access their S3 bucket
response = sts.assume_role(
RoleArn = role_to_assume_arn,
RoleSessionName = 'test',
ExternalId = 'ABCDEFG12345'
)
creds=response['Credentials']
# open session in another account:
assumed_sess = boto3.Session(
aws_access_key_id=creds['AccessKeyId'],
aws_secret_access_key=creds['SecretAccessKey'],
aws_session_token=creds['SessionToken'],
)
remote_bucket = 'remote_bucket'
s3_assumed = assumed_sess.resource('s3')
bk_assumed = s3_assumed.Bucket(remote_bucket)
for o in bk_assumed.objects.filter(Prefix="prefix/"):
print(o.key)
in_object = s3_assumed.Object(remote_bucket, o.key)
content = in_object.get()['Body'].read()
s3_local.Object('my_account_bucket', o.key).put(Body=content)
错误:
botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
答案 0 :(得分:0)
( TL; DR 请参见结尾,以了解一种比使用角色更容易配置权限的方法!)
在存储桶之间移动数据的最简单方法是使用copy_object()
命令。此命令将发送到目标存储桶,并从源存储桶“拉”信息。
当涉及多个AWS账户时,这会变得稍微复杂一些,因为同一组凭据需要对源存储桶具有GetObject
权限,而对目标存储桶则具有{em> {em} PutObject
您的情况似乎是:
GetObject
权限PutObject
权限重要的是,还应向角色分配写入目标存储区的权限。
为测试这种情况,我执行了以下操作:
Bucket-A
(源存储桶)中创建了Account-A
,并上传了一些测试文件Bucket-B
(目标存储桶)中创建了Account-B
Role-A
中创建了Account-A
,并指定Account-B
可以使用它。Role-A
:{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:List*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::bucket-a",
"arn:aws:s3:::bucket-a/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:Put*"
],
"Resource": [
"arn:aws:s3:::bucket-b/*"
]
}
]
}
请注意,该角色也已被授予写入Bucket-B
的权限。在您的特定情况下可能不会出现这种情况,但是有必要否则Account-A
将不允许角色调用Bucket-B
!
要澄清:在使用跨帐户权限时,两个帐户都需要授予权限。在这种情况下,Account-A
授予Role-A
写入Bucket-B
的权限,但是Account-B
也必须允许写入(请参见下面的存储桶策略)。
User-B
中创建了Account-B
,并授予在AssumeRole
中Role-A
上调用Account-A
的权限:{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AssumeRoleA",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::111111111111:role/role-a"
}
]
}
Bucket-B
上创建了一个桶策略,允许Role-A
将文件放入桶中。这很重要,因为Account-A
无法访问Account-B
中的资源,但是此存储桶策略将允许Role-A
使用存储桶。 {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::bucket-b/*",
"Principal": {
"AWS": [
"arn:aws:iam::111111111111:role/role-a"
]
}
}
]
}
Role-A
:[role-a]
role_arn = arn:aws:iam::906972072995:role/role-a
source_profile = user-b
Bucket-A
:aws s3 ls s3://bucket-a --profile role-a
Bucket-A
复制到Bucket-B
:aws s3 cp s3://bucket-a/foo.txt s3://stack-bucket-b/ --profile role-a
这成功完成了。
摘要
以上过程看似相当复杂,但可以很容易地在源和目标之间进行划分:
Role-A
,可以从Bucket-A
读取,并且还具有写入Bucket-B
的权限Bucket-B
上的存储桶策略允许Role-A
对其进行写入如果Account-A
不愿意提供既可以从Bucket-A
读取又可以写入Bucket-B
的角色权限,那么还有另一种选择: >
Account-A
询问向Bucket-A
添加存储桶策略,以允许User-B
到GetObject
User-B
可以使用普通(User-B
)权限从Bucket-A
读取内容,而无需使用AssumeRole