razor
razor

Reputation: 2867

S3 presigned download url immediately expired, why?

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

Answers (3)

vish anand
vish anand

Reputation: 151

try using this if you in javascript

S3.getSignedUrlPromise('getObject', {
            Bucket: s3Bucket,
            Key: files[0],
            Expires: 60 * 60 * 24 * 7,
        })

Upvotes: 0

Arvin_Sebastian
Arvin_Sebastian

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

Michael - sqlbot
Michael - sqlbot

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

Related Questions