Reputation: 106
I am trying to generate a signed URL for S3 bucket objects with the maximum expiration of 604800 seconds or 7 days. However, after testing I discovered that the links expire in under 24hrs. Doing some digging I came across this article claiming that the 7 day expiration is only available if the aws-sdk is authorized with an IAM user and the s3 library is making use of AWS Signature v4.
I am definitely using v4: exports.getS3 = () => new AWS.S3({region : 'us-east-1', signatureVersion: 'v4'})
Additionally, as far as I can tell, the lambdas deployed via serverless should default to my IAM user credentials when making use of the sdk without any other manipulation: const AWS = require('aws-sdk')
Here is the aforementioned article : https://aws.amazon.com/premiumsupport/knowledge-center/presigned-url-s3-bucket-expiration/
I also defined the IAM role delegated to my user to enable access to s3 iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:*
Resource: "*"
- Effect: Allow
Action:
- ssm:*
Resource: "*"
- Effect: Allow
Action:
- s3:*
Resource: "*"
I've verified that it is not something as asinine as passing the wrong argument 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))
});
}
Has anybody encountered this issue or have any ideas what may be causing my problem? Is there some configuration I am missing?
Upvotes: 3
Views: 3571
Reputation: 78803
Lambda functions deployed with serverless
do not default to your IAM user credentials, as far as I know. They use the IAM role/policy that you supply in serverless.yml, plus basic CloudWatch Logs permissions which are auto-generated by serverless
The problem is that your Lambda function is using temporary credentials from STS (via an assumed IAM role) to generate the pre-signed URL. The URL will expire when the temporary session token expires (or earlier if you explicitly indicate an earlier timeout).
If you use IAM user credentials, rather than temporary credentials via an IAM role, you can extend the expiration to 7 days (with signature v4) or end of epoch (with the potentially deprecated signature v2). So, you need to supply your Lambda function with IAM user credentials, possibly through environment variables or AWS Parameter Store or AWS Secrets Manager.
For more, see Why is my presigned URL for an Amazon S3 bucket expiring before the expiration time that I specified?
Also, there are a couple of minor coding issues here:
getSignedUrl
method offers an asynchronous option, the operation itself is synchronous so you should simply run const url = s3.getSignedUrl(...)
Upvotes: 7