S3 签名 URL 在参数通过之前就过期了

Eri*_*ann 3 amazon-s3 amazon-web-services aws-lambda serverless-framework

我正在尝试为 S3 存储桶对象生成签名 URL,最大过期时间为 604800 秒或 7 天。然而,经过测试,我发现链接在 24 小时内就会过期。经过一番挖掘,我发现这篇文章声称只有当 aws-sdk 获得 IAM 用户授权并且 s3 库使用 AWS Signature v4 时,7 天到期才可用。

我肯定使用 v4:exports.getS3 = () => new AWS.S3({region : 'us-east-1', signatureVersion: 'v4'})

此外,据我所知,在使用 sdk 时,在没有任何其他操作的情况下,通过无服务器部署的 lambda 应该默认为我的 IAM 用户凭证:const AWS = require('aws-sdk')

这是上述文章:https://aws.amazon.com/premiumsupport/knowledge-center/presigned-url-s3-bucket-expiration/

我还定义了委托给我的用户的 IAM 角色以启用对 s3 的访问iamRoleStatements: - Effect: Allow Action: - dynamodb:* Resource: "*" - Effect: Allow Action: - ssm:* Resource: "*" - Effect: Allow Action: - s3:* Resource: "*"

我已经证实这并不像传递错误的参数那么愚蠢exports.getSignedURL = (key,bucket,method,expiration) =>{ console.log(`GETTING SIGNED URL WITH EXPIRATION ${expiration}`) return new Promise((resolve, reject) => { exports.getS3().getSignedUrl(method,{ Bucket: bucket, Key : key, Expires : expiration },(err,url)=>err?reject(err):resolve(url)) }); }

有人遇到过这个问题或者有任何想法可能导致我的问题吗?我缺少一些配置吗?

jar*_*mod 7

serverless据我所知,部署的 Lambda 函数不会默认使用您的 IAM 用户凭证。它们使用您在 serverless.yml 中提供的 IAM 角色/策略,以及由以下命令自动生成的基本 CloudWatch Logs 权限serverless

问题在于您的 Lambda 函数正在使用来自 STS 的临时凭证(通过假定的 IAM 角色)来生成预签名 URL。当临时会话令牌过期时,URL 将过期(如果您明确指示较早的超时,则更早)。

如果您使用 IAM 用户凭证,而不是通过 IAM 角色使用临时凭证,则可以将过期时间延长至 7 天(使用签名 v4)或纪元结束(使用可能已弃用的签名 v2)。因此,您需要为 Lambda 函数提供 IAM 用户凭证(可能通过环境变量或 AWS Parameter Store 或 AWS Secrets Manager)。

有关更多信息,请参阅为什么我的 Amazon S3 存储桶的预签名 URL 在我指定的过期时间之前过期?

此外,这里还有一些小的编码问题:

  • 所有 AWS 方法都有一个 .promise() 选项来返回 Promise,因此无需使用回调,也无需手动创建 Promise 对象
  • 虽然该getSignedUrl方法提供了异步选项,但操作本身是同步的,因此您应该简单地运行const url = s3.getSignedUrl(...)