Reputation: 2867
I have app that generates presigned url (using java sdk generatePresignedUrl method). Everything works on one environment (@ EU_central_1 server), but the same app published on other environment (client's EU_West_1) generates links that don't work, info from S3 when i try to download object right after creating an URL:
<Error>
<Code>AccessDenied</Code>
<Message>Request has expired</Message>
<X-Amz-Expires>600</X-Amz-Expires>
<Expires>2016-05-26T09:32:44Z</Expires>
<ServerTime>2016-05-26T09:33:03Z</ServerTime>
As you can see, x-amz-expires was set to 600 seconds, but expires tag says object was expired immediately.
Is it a problem with GeneratePresignedUrlRequest.setExpiration that calculates incorrect expiration time ?
that's my code to set expiration time:
Date expiration = new Date();
expiration.setTime(expiration.getTime() + 1000 * 600);
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, key);
generatePresignedUrlRequest.setMethod(HttpMethod.GET);
generatePresignedUrlRequest.setExpiration(expiration);
URL url = s3client.generatePresignedUrl(generatePresignedUrlRequest);
Looks like both servers return the same time. that's the response from two different EC2 servers connected to two different S3 servers, from the same area. One has a expire set to 4, second to 4000 (to be able to download resource right after creating a link).
Response from server working correctly:
<Error>
<Code>AccessDenied</Code>
<Message>Request has expired</Message>
<X-Amz-Expires>4</X-Amz-Expires>
<Expires>2016-05-31T09:54:04Z</Expires>
<ServerTime>2016-05-31T11:00:17Z</ServerTime>
response from server with presigned URL problem:
<Error>
<Code>AccessDenied</Code>
<Message>Request has expired</Message>
<X-Amz-Expires>4000</X-Amz-Expires>
<Expires>2016-05-31T10:49:54Z</Expires>
<ServerTime>2016-05-31T11:00:07Z</ServerTime>
both links created in the same time (with a few seconds difference for page refresh)
Upvotes: 5
Views: 12439
Reputation: 151
try using this if you in javascript
S3.getSignedUrlPromise('getObject', {
Bucket: s3Bucket,
Key: files[0],
Expires: 60 * 60 * 24 * 7,
})
Upvotes: 0
Reputation: 1194
Please refer the below article to sync your time( between ec2 and s3) https://aws.amazon.com/blogs/aws/keeping-time-with-amazon-time-sync-service/
we need to use a service called chrony. its a versatile implementation on ntp and a bit more accurate and accomodate leap seconds.
Use below information to troubleshoot:
you can know the time in current linux machine using date
command.
X-Amz-Date
tells you when your url was signed in your ec2 or machine where the code is running.
In the response,
<Expires>2016-05-31T10:49:54Z</Expires>
<ServerTime>2016-05-31T11:00:07Z</ServerTime>
Expires tell when the signature expired based on the X-Amz-Expires and ServerTime tells the time on the s3 server when the request was received.
Upvotes: 1
Reputation: 178966
Signature V4 (unlike V2) does not rely on the signature generation code to do the time math to figure out the expiration time.
Generating a V4 signature (as you are doing) requires that you know what time it is now, and include that value as X-Amz-Date
. AWS then does the math on their side. "Hey, this guy says he signed it 11 minutes ago, and it's only good for 10 minutes... denied!"
Check the clock on the machine generating the signature.
Upvotes: 5