Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS Java SDK 2.0 create a presigned URL for a S3 object

Tags:

I know with version 1.x of the SDK it's as simple as per the docs

java.util.Date expiration = new java.util.Date();
long msec = expiration.getTime();
msec += 1000 * 60 * 60; // Add 1 hour.
expiration.setTime(msec);

GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objectKey);
generatePresignedUrlRequest.setMethod(HttpMethod.PUT); 
generatePresignedUrlRequest.setExpiration(expiration);

URL s = s3client.generatePresignedUrl(generatePresignedUrlRequest); 

However looking at the 2.0 docs but I can't find anything close to the GeneratePresignedUrlRequest.

Hopefully there is another simple pattern for this?

like image 646
Chris Turner Avatar asked Jan 29 '18 02:01

Chris Turner


People also ask

How do I create a URL for Amazon S3?

To generate a presigned URL using the AWS Management ConsoleSign in to the AWS Management Console and open the Amazon S3 console at https://console.aws.amazon.com/s3/ . In the Buckets list, choose the name of the bucket that contains the object that you want a presigned URL for.

What is Presigned URL in AWS S3?

A presigned URL is a URL that you can provide to your users to grant temporary access to a specific S3 object. Using the URL, a user can either READ the object or WRITE an Object (or update an existing object). The URL contains specific parameters which are set by your application.

When should I use Presigned URL S3?

Pre-signed URLs are used to provide short-term access to a private object in your S3 bucket. They work by appending an AWS Access Key, expiration time, and Sigv4 signature as query parameters to the S3 object. There are two common use cases when you may want to use them: Simple, occasional sharing of private files.

How do I mask my Amazon S3 URL?

There are two parts to masking your S3 url, the first is creating and naming a bucket in S3 to match the subdomain, the second is creating the subdomain and pointing it to the S3 bucket url. Update 5 January 2021: On November 11th, 2020 Amazon announced the release of the new S3 Console.


2 Answers

This is now supported for S3's GetObject. See here.

  // Create an S3Presigner using the default region and credentials.
      // This is usually done at application startup, because creating a presigner can be expensive.
      S3Presigner presigner = S3Presigner.create();

      // Create a GetObjectRequest to be pre-signed
      GetObjectRequest getObjectRequest =
              GetObjectRequest.builder()
                              .bucket("my-bucket")
                              .key("my-key")
                              .build();

      // Create a GetObjectPresignRequest to specify the signature duration
      GetObjectPresignRequest getObjectPresignRequest =
          GetObjectPresignRequest.builder()
                                 .signatureDuration(Duration.ofMinutes(10))
                                 .getObjectRequest(getObjectRequest)
                                 .build();

      // Generate the presigned request
      PresignedGetObjectRequest presignedGetObjectRequest =
          presigner.presignGetObject(getObjectPresignRequest);

      // Log the presigned URL, for example.
      System.out.println("Presigned URL: " + presignedGetObjectRequest.url());

      // It is recommended to close the S3Presigner when it is done being used, because some credential
      // providers (e.g. if your AWS profile is configured to assume an STS role) require system resources
      // that need to be freed. If you are using one S3Presigner per application (as recommended), this
      // usually is not needed.
      presigner.close();

This is also now supported for S3's PutObject. Example here.

S3Presigner presigner = S3Presigner.create();
PresignedPutObjectRequest presignedRequest =
    presigner.presignPutObject(r -> r.signatureDuration(Duration.ofMinutes(5))
                                        .putObjectRequest(por -> por.bucket(testBucket).key(objectKey)));

System.out.println("Pre-signed URL to upload a file to: " + 
                   presignedRequest.url());
System.out.println("Which HTTP method needs to be used when uploading a file: " + 
                   presignedRequest.httpRequest().method());
System.out.println("Which headers need to be sent with the upload: " + 
                   presignedRequest.signedHeaders())

Here's an example of uploading to S3 using a PresignedPutObjectRequest:

PresignedPutObjectRequest presignedRequest = ...;
SdkHttpClient httpClient = ApacheHttpClient.builder().build();

ContentStreamProvider contentToUpload = () -> new StringInputStream("Hello, World!");
HttpExecuteRequest uploadRequest = HttpExecuteRequest.builder()
                                                     .request(presignedRequest.httpRequest())
                                                     .contentStreamProvider(contentToUpload)
                                                     .build();

HttpExecuteResponse response = httpClient.prepareRequest(uploadRequest).call();
Validate.isTrue(response.httpResponse().isSuccessful());
like image 116
Andreas Frische Avatar answered Sep 16 '22 18:09

Andreas Frische


As mentioned by @Anurudhha in the comment, it is not yet supported in SDK 2.0. Here is the link to the official backlog

https://github.com/aws/aws-sdk-java-v2/projects/1

Here is a workaround from the feature request, which can help you as of now

https://gist.github.com/aaronanderson/f9e2806cc5e2c18fab4d7e60c589d160

like image 39
Juned Ahsan Avatar answered Sep 17 '22 18:09

Juned Ahsan