S3Mock icon indicating copy to clipboard operation
S3Mock copied to clipboard

CORS issue when uploading file using presigned POST URL

Open fabiob opened this issue 1 year ago • 3 comments

Hi! I'm migrating some of our tests from Localstack to S3Mock (great work, btw!), but I've encountered an issue where one of our tests fails when uploading a file to S3Mock using a presigned POST URL.

The request includes the Access-Control-Allow-Methods: POST header, and this seems to cause the failure. I've tried reproducing the issue, and you can see the failing test case here: https://github.com/fabiob/S3Mock/commit/c7679fc8d8c84e3c7378f49f2d69741a6c71f7eb

What I've tried:

  • Allowing POST in controller annotations: Added @CrossOrigin(..., methods = {Request.POST, ...}) to the controllers: https://github.com/fabiob/S3Mock/commit/79057ce74010360a59ae787a82df2b34569b5668
  • Configuring CORS globally: Removed the @CrossOrigin annotations from the controllers and tried configuring CORS globally by overriding S3MockConfiguration.addCorsMappings: https://github.com/fabiob/S3Mock/commit/0c6d2c4a3e917368ffa35210d777769ae07032cb
  • Using CORS filter: Removed the @CrossOrigin annotations and added a CORS filter using FilterRegistrationBean to S3MockConfiguration: https://github.com/fabiob/S3Mock/commit/ebe7d5e363dec5a6fb469c315c883744a00a348d

None of these attempts seem to resolve the issue. The test still fails when performing the OPTIONS request.

Any insights or workarounds from others who may have experienced this issue would be greatly appreciated!

References I've used:

  • https://spring.io/blog/2015/06/08/cors-support-in-spring-framework#global-cors-configuration

fabiob avatar Oct 16 '24 09:10 fabiob

@fabiob which URL are you trying to POST to?

The controllers are annotated with @CrossOrigin(origins = "*", exposedHeaders = "*") which means that the HTTP methods allowed default to the HTTP method declared by the controller function. There are only a few S3 APIs that allow POST requests, most APIs use PUT to modify or create data.

The only APIs supported by S3Mock using POST are deleteObjects, createMultipartUpload and completeMultipartUpload.

The reason why your test fails is because the URL used points to a bucket (https://github.com/fabiob/S3Mock/commit/c7679fc8d8c84e3c7378f49f2d69741a6c71f7eb#diff-830d0afe6486c2b436b422fabcb308511dab2b2eef4c1edf698108716a4d7b0dR228), and there are no APIs that allow a POST on a bucket.

afranken avatar Oct 17 '24 22:10 afranken

if you change your test to use "PUT" instead, it succeeds, as there are two APIs (and controller functions) that allow a "PUT" on a bucket, for example putObjectLockConfiguration

afranken avatar Oct 17 '24 22:10 afranken

You write "upload file" - do you mean "putObject"? This API needs a "PUT", not a "POST" request: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html

afranken avatar Oct 17 '24 22:10 afranken

I'm running into this as well. I'm using boto's generate_presigned_post method, which specifically returns a URL to post to. For context, in a local env, I'm trying to get a presigned post URL from the S3Mock container and then post to it.

jedkass avatar Oct 30 '24 16:10 jedkass

@afranken Do you have any context on this by chance? Should POST be supported for presigned URLs?

jedkass avatar Nov 06 '24 21:11 jedkass

@jedkass didn't have time yet to look into this. As I said in an earlier comment, the S3 API supports POST requests only for a few resources, everywhere else, PUT is used. You can't just generate a presigned URL allowing POST and then make the POST request for an API that disallows that HTTP verb...

It would be good to have specific test cases that work against S3 directly and fail against S3Mock for APIs that allow POST.

afranken avatar Nov 07 '24 15:11 afranken

Just merged tests for GET, HEAD, DELETE and POST options requests. Success depends on the APIs being called.

As I wrote in previous comments, creating presigned URLs may work locally using the AWS SDK for arbitrary URLs, but the S3 API (and S3Mock) will refuse connection if the API called does not allow for the HTTP method used.

Please refer to the S3 API to learn about the HTTP methods used for API calls: https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html

afranken avatar Dec 16 '24 18:12 afranken

@afranken Do you have any context on this by chance? Should POST be supported for presigned URLs?

@jedkass good news: I released https://github.com/adobe/S3Mock/releases/tag/4.1.0 S3Mock now supports POST Object requests (with basic parameters).

See also #2200

afranken avatar May 01 '25 10:05 afranken