Lambda / 预签名 url 访问被拒绝

Lambda / Pre-signed url access denied

我编写了一个 lambda 函数,它 return 为 S3 存储桶中的文档预签名 url。

代码真的很简单:

            const url = s3.getSignedUrl('getObject', {
                Bucket: BUCKET_NAME,
                Key: myFile.Key,
                Expires: 20
            })

            const response = {
                statusCode: 200,
                headers: {
                    "Access-Control-Allow-Origin": "*"
                },
                body: JSON.stringify({
                    "url": url
                }),
            };

有趣的是,当我像这样在本地(使用无服务器框架)调用此函数时:

sls invoke local -f getEconomyFile -d '{ "queryStringParameters": { "key": "myfile.pdf" } }'

有效!我有一个 url 给我文件。

但是当我部署到 AWS Lambda 时,函数 return a URL 总是在文件上显示 "access denied" :

<Error>
    <Code>AccessDenied</Code>
    <Message>Access Denied</Message>
    <RequestId>93778EA364B3506B</RequestId>
    <HostId>
        yqnPC0SeIVE3/Pl7/d+xHDJ78=
    </HostId>
</Error>

为什么它在本地工作而不是部署?

谢谢!

这是预签名 URL 不起作用时要检查的事项列表:

  1. Lambda 函数的 IAM 策略需要能够访问相关的 S3 对象(通过 arn:aws:s3:::BUCKET-NAME/*)。如果它没有访问权限,它将能够创建一个预签名的 URL(纯本地计算**),但 URL 实际上不允许您访问该对象(因为支持预签名 URL 的凭据无权访问)。
  2. 检查 URL 是否已过期。
  3. 检查用于签署 URL 的凭据是否已过期。这是使用临时凭据预签名 URL 时的常见问题,其中凭据在预签名 URL 到期之前到期。
  4. 检查客户端是否同步。
  5. 检查 URL 是否在传输过程中损坏或以某种方式编码。

** 您可以看出这是一个本地计算,并且不涉及通过预签名对象(例如 s3://notmybucket/fred)对 AWS 的任何调用。这将起作用并生成一个预签名的 URL,但它实际上不能用于检索该对象。