Lambda /预先签名的URL访问被拒绝

use*_*545 2 amazon-web-services aws-lambda serverless-framework

我编写了一个lambda函数,它返回S3 Buckets中文档的预签名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
                }),
            };
Run Code Online (Sandbox Code Playgroud)

有趣的是当我在本地调用此函数(使用无服务器框架)时,如下所示:

sls invoke local -f getEconomyFile -d '{ "queryStringParameters": { "key": "myfile.pdf" } }'
Run Code Online (Sandbox Code Playgroud)

它的工作原理!我有一个网址给我文件.

但是当我部署到AWS Lambda时,该函数返回一个URL,该URL总是在文件上显示"access denied":

<Error>
    <Code>AccessDenied</Code>
    <Message>Access Denied</Message>
    <RequestId>93778EA364B3506B</RequestId>
    <HostId>
        yqnPC0SeIVE3/Pl7/d+xHDJ78=
    </HostId>
</Error>
Run Code Online (Sandbox Code Playgroud)

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

谢谢 !

jar*_*mod 10

以下是预签名网址不起作用时要检查的事项列表:

  1. Lambda函数的IAM策略需要访问有问题的S3对象(通过arn:aws:s3 ::: BUCKET-NAME/*).如果它没有访问权限,它将能够创建一个预先签名的URL(纯粹的本地计算**),但该URL实际上不允许您访问该对象(因为支持预签名URL的凭据可以没有访问权限).
  2. 检查URL是否已过期.
  3. 检查客户端是否已经过时间同步.

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

  • @anonymouscoward 我猜你是想写 arn:aws:s3::::BUCKET-NAME/* (带有尾随斜线星号)而不是 arn:aws:s3:::BUCKET-NAME* (带有尾随星号) . (4认同)
  • 未来的 Google 员工:注意那个星号!我花了相当长的时间调试我认为是客户端上传端的问题...结果是,IAM 用户对 `arn:aws:s3:::BUCKET-NAME` 具有“所有 S3 操作”,看起来是正确的。为什么不?将其更改为“arn:aws:s3:::BUCKET-NAME*”解决了该问题。 (2认同)