【问题标题】:listing all objects in an S3 bucket using boto3使用 boto3 列出 S3 存储桶中的所有对象
【发布时间】:2021-03-05 10:33:15
【问题描述】:

我有一个 s3 存储桶,其中包含我想从我的 lambda 访问的一堆文件(由同一帐户创建的 lambda 和 s3 存储桶):

def list_all():
  s3 = boto3.client('s3')
  bucket = 'my-bucket'
  resp = s3.list_objects(Bucket=bucket, MaxKeys=10)
  print("s3.list_objects returns", resp)

这会产生如下错误:

{
  "errorMessage": "An error occurred (AccessDenied) when calling the 
                   ListObjects operation: Access Denied",
  "errorType": "ClientError",
  "stackTrace": [
  [
    "/var/task/lambda_function.py",
    41,
    "lambda_handler",
    "list_all()"
  ], ...

我的存储桶设置在 aws 上显示如下:

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

我有两个问题:

1) 我应该将我的操作字段设置为什么,以便我可以使用 boto3 从我的 lambda 中列出任何文件夹中的所有文件?

2) 我应该将我的主体设置为什么,以便只有我的 aws 帐户(例如,当我运行我的 lambda 时)才能访问存储桶?

【问题讨论】:

  • 使用 S3 存储桶策略是向您的 S3 存储桶授予 Lambda 权限的错误方法。相反,创建等效的 IAM 角色,然后配置 Lambda 函数以使用该角色。
  • 我创建了 iam 角色并将 LF 配置为使用该角色。如何关闭对存储桶的公共访问?
  • 删除桶策略。

标签: amazon-web-services amazon-s3 aws-lambda boto3


【解决方案1】:

您的 lambda 失败的原因是要使用 listObjects,您的 lambda 函数需要具有 IAM 权限 s3:ListBucket,该权限适用于单个存储桶(不需要对象通配符) (docs).

即你应该set your lambda's IAM policy到:

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

【讨论】:

  • OP 的策略有一个 Principal,因为它是 S3 存储桶策略,而不是 IAM 策略。切换到 IAM 策略提供您提供的策略是需要的。
  • 为现场干杯——没有注意到这是存储桶策略。
  • 如果我没有 Principal 会报错,ListBucket 也会报错(“policy has invalid action”)
  • 嗨-检查我的编辑,正如@jarmod 注意到的那样,您需要编辑 lambda 的角色(在 lambda 控制台上按“键”图标查看和更改政策)。
【解决方案2】:
def list_s3_by_prefix(bucket, key_prefix, filter_func=None):
    next_token = ''
    all_keys = []
    while True:
        if next_token:
            res = s3.list_objects_v2(
                Bucket=bucket,
                ContinuationToken=next_token,
                Prefix=key_prefix)
        else:
            res = s3.list_objects_v2(
                Bucket=bucket,
                Prefix=key_prefix)

        if 'Contents' not in res:
            break

        if res['IsTruncated']:
            next_token = res['NextContinuationToken']
        else:
            next_token = ''

        if filter_func:
            keys = ["s3://{}/{}".format(bucket, item['Key']) for item in res['Contents'] if filter_func(item['Key'])]
        else:
            keys = ["s3://{}/{}".format(bucket, item['Key']) for item in res['Contents']]

        all_keys.extend(keys)

        if not next_token:
            break
    print("find {} files in {}".format(len(all_keys), key_prefix))

【讨论】:

    猜你喜欢
    • 2018-08-28
    • 2021-05-09
    • 2015-10-23
    • 2021-11-25
    • 2018-03-29
    • 2012-04-12
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多