0

I am using generatePresignedUrl method of AmazonS3Client class to get a pre-signed URL. However when the method is called in the same session as that of the upload of the file. it returns url of the form :

https://mp-dev.downloads.XYZ.com.s3.ap-south-1.amazonaws.com/certificate/404/17_04_2017/XYZ/ITHLUaXYPnMmHEUbK9L21KBneJQy7oJ1jw.zip?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20170417T090656Z&X-Amz-SignedHeaders=host&X-Amz-Expires=900&X-Amz-Credential=ASDFSFFGODQ%2F20170417%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Signature=9b2e112608c46cbeb16ff577b6e1321f889efsdfdsc850212251b231cb909d1942

But when I rerun my API and call the same method with the same params I get url of the form :

https://mp-dev.downloads.XYZ.com.s3.amazonaws.com/certificate/404/17_04_2017/XYZ/ITHLUaXYPnMmHEUbK9L21KBneJQy7oJ1jw.zip?AWSAccessKeyId=AKIAJFAFDTTISR4UHODQ&Expires=1492421420&Signature=CZuY1acATGUEEpoXN8aEQFXLX18%3D

First Url works fine but the second url results in :

The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.

I have tried to change configuration to use signature version 4 as per the following discussion :

The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256

But doesn't work. Ask me if any additional info is required.

Endpoint to generate url :

@SkipAuthentication
  @GET
  @Path("/xyz")
  public String download(@QueryParam("cer") String objectKey) {
    return testService.test(objectKey).toString();
  }

Test method of service :

public URL test(String objectKey) {
    return awsDownloadService.generateDownloadUrl(objectKey, awsServer.getDownloadsBucketName());
  }

The generateDownloadUrl method is as follows :

  public URL generateDownloadUrl(String keyName, String bucketName) {
    LOG.info("generateDownloadUrl - {} {} {} {}>",accessKeyId, secretAccessKey, keyName, bucketName);
    BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKeyId, secretAccessKey);
    AmazonS3Client s3Client = new AmazonS3Client(awsCreds);

    Date expiration = new Date();
    long msec = expiration.getTime();
    msec += 1000 * 60 * 15; // 15 minutes.
    expiration.setTime(msec);
    GeneratePresignedUrlRequest generatePresignedUrlRequest = 
                  new GeneratePresignedUrlRequest(bucketName, keyName);
    generatePresignedUrlRequest.setMethod(HttpMethod.GET); // Default.
    generatePresignedUrlRequest.setExpiration(expiration);
    URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
    LOG.info("GeneratePreAuthenticatedUrl - url generated is <{}>",url);
    return url;
  }

When I upload the file using upload method and then call the end point to generate url it works fine but when I restart the api and call the end point to generate url, different url is returned as described earlier in the question.

Solution and new query:

I have solved the problem. Apparently ,AmazonS3Client is deprecated. Making client this way works consistently :

AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(awsCreds));
    builder.setRegion(Regions.AP_SOUTH_1.getName());
    AmazonS3 s3client = builder.build();

Still, the behavior AmazonS3Client exhibited earlier is kind of odd. Can anybody provide explanation of the earlier behavior?

Community
  • 1
  • 1
sudheer singh
  • 684
  • 1
  • 6
  • 20
  • 1
    Did you specify the same region for both connections? Signature v4 is forced in the newer regions. – John Rotenstein Apr 17 '17 at 21:58
  • I didn't specify region for any of the connections.As I said there is a method which take credentials, bucket name and key and calls generatePresignedUrl but the result differs for same params. – sudheer singh Apr 18 '17 at 04:35
  • Interesting! Can you supply some minimal code to reproduce the situation? If so, please insert it into your Question. – John Rotenstein Apr 18 '17 at 05:09
  • I have provided the code. – sudheer singh Apr 18 '17 at 05:21
  • Where is the code that produces the different URLs vs the code that produces the same URLs? Also, please only show enough code to reproduce the situation -- there is no need to provide the code that uploads files, since this is irrelevant to generating the pre-signed URL. – John Rotenstein Apr 18 '17 at 05:24
  • Calling same endpoint(/xyz) results in different urls. The working url is obtained when the end point is called in same session as the one which the file is uploaded in. Restarting the API and calling the same endpoint with same object key results in url of second kind(as provided in the question). – sudheer singh Apr 18 '17 at 05:42

1 Answers1

0

Apparently the AmazonS3Client class is deprecated in the latest SDKs. Creating client in the following manner solves the problem as it also takes region into account and hence attaches proper signature versions :

BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKeyId, secretAccessKey);
    AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(awsCreds));
    builder.setRegion(regionName);
    AmazonS3 s3client = builder.build();
sudheer singh
  • 684
  • 1
  • 6
  • 20