为什么在尝试读取不存在的 s3 密钥时会收到不同的错误

Tes*_*uji 6 python amazon-s3 amazon-web-services boto3 aws-lambda

我有两个环境。一个,我从桌面运行,另一个我从 aws lambda 运行。这两个都是python。我机器上的代码是:

import boto3
s3 = boto3.resource('s3')
bucket = 'my-bucket'
obj = s3.Object(bucket,'test.txt')
try:
    text = obj.get()['Body'].read().decode()
    print("file exists"))
except s3.meta.client.exceptions.NoSuchKey:
    print("key does not exist")

Run Code Online (Sandbox Code Playgroud)

当我运行它时,一切正常,如预期的那样。

当我在 lambda 上运行它时,我得到

调用 GetObject 操作时发生错误 (AccessDenied):拒绝访问

我的 lambda 权限是正确的,所以不可能,因为当文件存在时一切正常。我每次运行都会删除文件,因此它与我运行测试代码的顺序无关。为了调试,我这样做了:

except Exception as e:
    print(e)
Run Code Online (Sandbox Code Playgroud)

在我的 lambda 代码和本地代码中,查看实际错误是什么。在我的本地机器上,错误是:

调用 GetObject 操作时发生错误 (NoSuchKey):指定的键不存在。

当我在我的 lambda 上运行它时,它是

调用 GetObject 操作时发生错误 (AccessDenied):拒绝访问

为什么我会收到不同的错误消息,如果没有懒惰的“除所有异常”解决方案,我该如何解决这个问题?谢谢

这是我的 lambda 的 CFT

                {
                  "Effect": "Allow",
                  "Action": [
                    "s3:PutObject",
                    "s3:GetObject",
                    "s3:ListBucket",
                  ],
                  "Resource": {
                    "Fn::Sub": "arn:aws:s3:::my-bucket/*"
                  }

                }
Run Code Online (Sandbox Code Playgroud)

rda*_*das 9

来自:https : //forums.aws.amazon.com/thread.jspa?threadID=56531

正如您发现的那样,当请求不存在的密钥并且不允许请求者列出存储桶的内容时,Amazon S3 将返回 AccessDenied 错误。根据 Amazon S3 的定义,不允许列出存储桶的内容意味着不允许发现特定键是否存在。返回 NoSuchKey 会泄漏有关所请求密钥不存在的信息。相反,Amazon S3 返回 AccessDenied。AccessDenied 不会说明所请求的密钥是否存在,因此不会泄露任何信息。

您可能缺少s3:listBucket在 lambda 中列出存储桶 ( )内容的权限。

参考:https : //docs.aws.amazon.com/AmazonS3/latest/dev/using-with-s3-actions.html#using-with-s3-actions-related-to-buckets

  • 好吧,那没有用。我将 ListBucket 添加到我的 cft,更新了堆栈,通过 aws 控制台验证了我的 lambda 中存在权限,但仍然收到“调用 GetObject 操作时发生错误(AccessDenied):拒绝访问” (2认同)
  • 那没有用。我什至将其更改为 s3:* 以便能够涵盖所有选项,但我仍然被拒绝访问。 (2认同)
  • 也为我工作,但有一个问题:“s3:ListBucket”的资源必须是存储桶本身“arn:aws:s3:::BucketName”,与“GetObject”和“PutObject”的资源不同,是(在我的例子中)存储桶 `"arn:aws:s3:::BucketName/*"` 的所有对象 (2认同)