如何使用boto3在两个不同账户的S3存储桶之间复制文件

11

我正在尝试使用boto3从供应商的S3存储桶将文件复制到我的S3存储桶。我使用sts服务来扮演角色以访问供应商的s3存储桶。我能够连接到供应商存储桶并获取存储桶列表。但是,当复制到我的存储桶时,我遇到了CopyObject操作:拒绝访问错误。以下是我的脚本:

session = boto3.session.Session(profile_name="s3_transfer")
sts_client = session.client("sts", verify=False)
assumed_role_object = sts_client.assume_role(
    RoleArn="arn:aws:iam::<accountid>:role/assumedrole",
    RoleSessionName="transfer_session",
    ExternalId="<ID>",
    DurationSeconds=18000,
)

creds = assumed_role_object["Credentials"]
src_s3 = boto3.client(
    "s3",
    aws_access_key_id=creds["AccessKeyId"],
    aws_secret_access_key=creds["SecretAccessKey"],
    aws_session_token=creds["SessionToken"],
    verify=False,
)
paginator =src_s3.get_paginator("list_objects_v2")
# testing with just 2 items.
# TODO: Remove MaxItems once script works.
pages = paginator.paginate(
    Bucket="ven_bucket", Prefix="client", PaginationConfig={"MaxItems": 2, "PageSize": 1000}
)
dest_s3 = session.client("s3", verify=False)
for page in pages:
    for obj in page["Contents"]:
        src_key = obj["Key"]
        des_key = dest_prefix + src_key[len(src_prefix) :]
        src = {"Bucket": "ven_bucket", "Key": src_key}
        print(src)
        print(des_key)
        dest_s3.copy(src, "my-bucket", des_key, SourceClient=src_s3)

错误发生在 dest_s3.copy... 这一行。我有以下 AWS 用户策略,允许将文件复制到我的存储桶。

{
    "Version": "2012-10-17",
   "Statement": [
    {
        "Sid": "VisualEditor1",
        "Effect": "Allow",
        "Action": [
            "s3:*"
        ],
        "Resource": [
            "arn:aws:s3:::my-bucket/*",
            "arn:aws:s3:::my-bucket/"
        ]
    }
    ]
}

在运行上述脚本时,出现以下错误:
botocore.exceptions.ClientError: 调用CopyObject操作时发生错误(Access Denied):访问被拒绝。

您用于调用复制操作的凭据需要能够访问源存储桶中的对象和目标存储桶中的对象。 - jarmod
如果您用于复制的凭据具有访问源对象的权限,那么为什么要使用临时STS凭据来列出源对象(使用src_s3)? - jarmod
被接受的答案对你有用吗?请问你能发布更新后的代码吗? - saadi
@saadi 我所做的是我有两个S3客户端,一个连接到源帐户,另一个连接到目标帐户。然后,我使用源客户端从源中下载文件,然后使用目标客户端将其上传到目标。 - Satish
重复的 https://stackoverflow.com/q/52318171/96588? - l0b0
显示剩余5条评论
1个回答

19
CopyObject()命令可用于在不必上传/下载的情况下在存储桶之间复制对象。基本上,两个S3存储桶相互通信并传输数据。
该命令还可用于在不同区域和不同AWS帐户中的存储桶之间进行复制。
如果您希望在属于不同AWS帐户的存储桶之间复制,则需要使用具有以下内容的单个凭据集
  • 源存储桶的GetObject权限
  • 目标存储桶的PutObject权限
此外,请注意,CopyObject()命令发送到目标帐户。目标存储桶会有效地从源存储桶拉取对象
根据您的描述,您的代码假定从其他帐户获取角色以获得源存储桶的读取权限。不幸的是,这对于CopyObject()命令来说是不够的,因为该命令必须发送到目标存储桶。(是的,从文档中很难看出这一点。这就是为什么明确指定源存储桶而不是目标存储桶的原因。)因此,针对你的情况,如果想要复制这些对象,你需要使用一组来自目标账户 Account-B 的凭证(同时也需要具有从源桶 Bucket-A 读取权限的凭证)。这将需要供应商修改与 Bucket-A 关联的 Bucket 策略。
如果他们不想这样做,那么你唯一的选择就是使用假定角色下载这些对象,然后使用你自己 Account-B 的凭证将文件单独上传到你自己的桶中。

你有相同的代码片段吗? - codingbruh
@codingbruh 这个问题中的代码是可以正常工作的。需要的是通过存储桶策略授予凭据访问该存储桶的权限。有关详细信息,请参阅跨账户 S3 存储桶权限 - John Rotenstein
@codingbruh 这个问题中的代码将正常工作。所需的是通过存储桶策略授予凭据访问存储桶的权限。有关详细信息,请参阅跨账户S3存储桶权限 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接