S3 Signed Url 在参数通过之前到期
S3 Signed Url's expiring before argument passed
我正在尝试为 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))
});
}
有没有人遇到过这个问题或者知道是什么导致了我的问题?我缺少某些配置吗?
据我所知,使用 serverless
部署的 Lambda 函数不会默认为您的 IAM 用户凭证。他们使用您在 serverless.yml 中提供的 IAM role/policy,以及由 serverless
自动生成的基本 CloudWatch Logs 权限
问题是您的 Lambda 函数正在使用来自 STS 的临时凭证(通过假定的 IAM 角色)来生成预签名 URL。 URL 将在临时会话令牌过期时过期(如果您明确指示更早的超时,则更早)。
如果您使用 IAM 用户凭证,而不是通过 IAM 角色的临时凭证,您可以将有效期延长至 7 天(签名 v4)或 (with the potentially deprecated 签名 v2)。因此,您需要为 Lambda 函数提供 IAM 用户凭证,可能是通过环境变量或 AWS Parameter Store 或 AWS Secrets Manager。
此外,这里还有一些小的编码问题:
- 所有 AWS 方法都有一个 .promise() 选项来 return 承诺,因此无需使用回调,也无需手动创建 Promise 对象
- 虽然
getSignedUrl
方法提供了异步选项,但操作本身是同步的,因此您应该 运行 const url = s3.getSignedUrl(...)
我正在尝试为 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))
});
}
有没有人遇到过这个问题或者知道是什么导致了我的问题?我缺少某些配置吗?
据我所知,使用 serverless
部署的 Lambda 函数不会默认为您的 IAM 用户凭证。他们使用您在 serverless.yml 中提供的 IAM role/policy,以及由 serverless
问题是您的 Lambda 函数正在使用来自 STS 的临时凭证(通过假定的 IAM 角色)来生成预签名 URL。 URL 将在临时会话令牌过期时过期(如果您明确指示更早的超时,则更早)。
如果您使用 IAM 用户凭证,而不是通过 IAM 角色的临时凭证,您可以将有效期延长至 7 天(签名 v4)或
此外,这里还有一些小的编码问题:
- 所有 AWS 方法都有一个 .promise() 选项来 return 承诺,因此无需使用回调,也无需手动创建 Promise 对象
- 虽然
getSignedUrl
方法提供了异步选项,但操作本身是同步的,因此您应该 运行const url = s3.getSignedUrl(...)