1

当我想使用 boto3 访问我的 S3 存储桶时,我只需这样做:

import boto3

s3_client = boto3.client('s3')

response = s3_client.list_objects_v2(
    Bucket='[bucket name]',
    Prefix='[prefix]'
)

但是,如果我需要访问另一个服务器中的另一个 S3 存储桶(不是我的,而是来自客户端)Server = bucket/prefix.s3.amazonaws.com)怎么办?

见cyberduck配置

此解决方案似乎不起作用:

import boto3

s3_client = boto3.client('s3', aws_access_key_id='[other access key]',
    aws_secret_access_key='[other secret key]')

response = s3_client.list_objects_v2(
    Bucket='[bucket name]',
    Prefix='[prefix]'
)

我可以使用 Cyber​​duck 毫无问题地访问 S3(指定服务器、访问密钥 ID 和密钥 ID),但是在脚本上我得到access denied.

我尝试指定添加到 boto3.client 的任何其他区域region_name='[region]',但除了拒绝访问之外,有时我遇到的另一个错误是An error occurred (InvalidAccessKeyId) when calling the ListObjectsV2 operation: The AWS Access Key Id you provided does not exist in our records.这没有多大意义,因为它与 Cyber​​duck 和 bash 脚本中使用的相同,格式如下:

SOURCE_FOLDER=s3://bucket/prefix
SEC_KEY=[other secret key]
ACC_KEY=[other access key]

同样使用 Postman,我没有任何问题,使用https://s3.amazonaws.com/bucket/?prefix=path和使用 AWS 签名作为授权类型。

4

2 回答 2

1

s3 服务中没有服务器这样的概念,bucket 是按区域存储的,但可以全局访问,因为它们共享一个唯一的全局命名空间。

编辑:您可以使用路径样式(https://s3.amazonaws.com/[bucket]/[prefix]/file)或虚拟托管样式(https://[bucket].s3 .amazonaws.com/[前缀]/文件

注意:在以下所有示例中,凭据都是通过环境变量设置的。

因此,您可以通过全局访问您的前缀:

globally = boto3.client('s3').list_objects_v2(
    Bucket='<my-bucket>', 
    Prefix='<my-folder>'
)

内部boto3设置endpoint_urls3.amazonaws.com

您还可以通过指定区域来访问您的前缀(如果您知道的话):

by_region = boto3.client('s3', region_name='eu-central-1').list_objects_v2(
    Bucket='<my-bucket>', 
    Prefix='<my-folder>'
)

内部boto3设置endpoint_urls3.<region_name>.amazonaws.com

最后,您可以通过指定存储桶端点来访问您的文件夹:

by_endpoint = boto3.client(
    's3', endpoint_url='https://<my-bucket>.s3.amazonaws.com'
).list_objects_v2(Bucket='<my-bucket>', Prefix='<my-folder>')

endpoint_url也可以是https://<my-bucket>.s3.<region_name>.amazonaws.com,结果是一样的。

这可以通过运行来验证:

assert globally['Contents'] == by_region['Contents'] == by_endpoint['Contents']

您不能在endpoint_url唯一的存储桶中设置前缀。由于Bucket参数是必需的,因此endpoint_url对我来说指定似乎没有必要。

全局访问存储桶是可行的,但您可能会在特定区域遇到一些问题,请参阅关于 boto3 问题的评论

编辑:由于 AWS计划弃用路径样式 URL,因此使用 boto3 始终使用虚拟托管样式设置端点。如果指定了区域,则端点最终是https://<my-bucket>.s3.<region_name>.amazonaws.com. 否则 boto3 使用全局端点启动 ``https://.s3.amazonaws.combut add the configured default region to the request, in case of a mismatch, the s3 service will return a 400 error with the a message like 授权标头格式错误;区域“us-east-1”是错误的;期待'eu-central-1'`。然后,无论如何都会强制客户端使用虚拟托管样式的区域端点重试请求。因此,您每次都将支付(性能方面的)往返费用。

因此,恕我直言,最好的解决方案是始终使用存储桶区域实例化客户端。

于 2019-07-25T10:38:18.837 回答
0

这些可能是两种可能的解决方案。

1)允许跨账户访问另一个账户中的 S3 存储桶。在这种情况下,您不必为另一个存储桶创建单独的 S3 客户端。参考:https ://aws.amazon.com/premiumsupport/knowledge-center/cross-account-access-s3/

2)为另一个存储桶创建一个单独的 S3 客户端。在这种情况下,您无需在创建 S3 客户端时指定endpoint_url,假设用于 IAM 用户的访问密钥已经可以访问它。代码参考:

s3_client = boto3.client('s3', aws_access_key_id='[other access key]', aws_secret_access_key='[other secret key]')
于 2019-07-25T11:33:09.327 回答