How to validate a file on S3 send by pre-signed URL? - amazon-web-services

I understand that a pre-signed URL is a way to send a file to S3. By doing that way, how can the object be validated? For example, I want to submit a JSON file to S3 and I want to make sure the file is in a correct format as input. I'd like to know if there is any way to make a response that the file is correctly saved and is valid by own validator function.

You could have an S3 event for create object that triggers a Lambda function. This could perform the validation checks you desire.
See: https://docs.aws.amazon.com/lambda/latest/dg/with-s3.html

The best way to do this is to generate the pre-signed URL with GET and PUT permissions for the same object. First, you would fire the PUT request to upload the file to S3 bucket. Next, you can do a GET call to check that the file has been uploaded.
As long as you are uploading a fresh new file, there is no chance of getting a false positive.
The above concept is based on the fact that the pre-signed URLs are restricted by time validating and not by the number of requests. This allows you to perform any number of PUT and GET call to the file as you want until the URL is valid.
Note: S3 is a trustworthy service - As long as you get a 200 status for your PUT request, you can rest assured that your file is there. The above method is just to crosscheck in case you wish to

Related

Could Amazon S3 Presigned URL be generated so a user can read a file but not download it?

We have a requirement to provide a user with temporary access to video files stored in Amazon S3. Users with a presigned URL should be able to play a video but not download it.
Is there any option to generate a presigned URL so users can play a video in a browser without the "Download" option?
There is no difference between 'reading' and 'downloading' the response to a URL.
You could choose to stream content, which means that the browser actively requests segments of the file rather than simply receiving the whole file. This avoids the ability to 'download' a file, but smart people can still obtain the entire contents by requesting all the segments. Not even Netflix can prevent this from happening.

Is it possible to generate a single presigned URL which can allow MULTIPLE unique objects to be uploaded?

I know based on the AWS docs here
https://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObject.html
that its possible to generate a URL which can can used to
upload a specific object to your bucket
and that
You can use the presigned URL multiple times, up to the expiration date and time.
It is also possible to generate a URL (perhaps a base s3 presigned URL) which would allow multiple different unique documents to be uploaded based on a single URL?
For example, lets imagine a client application would like to upload multiple unique/distinct documents to s3 using some type of presigned URL. I dont necessarily want to force them to get a batch of presigned URLs since that would require much more on the part of the client (they would have to request batch of presigned URLs, rather than a single URL)
Here is the flow for a single document upload.
What is the simplest known solution for allowing a client to use some type of presigned url to upload multiple documents?
It is also possible to generate a URL (perhaps a base s3 presigned URL) which would allow multiple different unique documents to be uploaded based on a single URL?
A presigned URL is limited to a single single object key. You can't, for example, presign a key of foo and then use it to upload foo/bar (because that's a different key).
That means that, if you want to provide the client with a single pre-signed URL, the client code will have to combine the files itself. For example, you require the client to upload a ZIP file, then trigger a Lambda that unpacks the files in that ZIP.
Another approach is to use the AWS SDK from the client, and use the Assume Role operation to generate temporary access credentials that are restricted to uploading files with a specified prefix using an inline session policy.
A third approach is to hide the URL requests. You don't say what your client application does, but assuming that you let the user select some number of files, you could simply loop over those files and retrieve a URL for each one without ever letting your user know that's happening.
It is possible to upload multiple files with a single pre-signed URL and properly configured 'Starts-with' policy. Please, refer to the following AWS documentation: Browser-Based Uploads Using POST

AWS S3 createPresignedPost vs getSignedUrl. Which one should I use for uploading various files from client side?

On S3 document, there is createPresignedPost and getSignedUrl.
On getSignedUrl:
Note: Not all operation parameters are supported when using pre-signed
URLs. Certain parameters, such as SSECustomerKey, ACL, Expires,
ContentLength, or Tagging must be provided as headers when sending a
request. If you are using pre-signed URLs to upload from a browser and
need to use these fields, see createPresignedPost().
Is createPresignedPost simply more customizable version of getSignedUrl?
Is it doing the same thing underneath?
If you want to restrict users from uploading files beyond certain size, you should be using createPresignedPost, and specify ContentLength
with getSignedUrl, there is no restricting object size and user can potentially upload a 5TB object (current object limit) to s3
Note that if you can specify ContentLength in params when calling getSignedUrl('putObject',params, callback)
you will be thrown
Presigning post data encountered an error { UnexpectedParameter: ContentLength is not supported in pre-signed URLs.
There is an issue on this subject

Only make S3 files accessible through ajax

I want to use S3 to store user uploaded excel files - obviously I only want that S3 file to be accessible by that user.
Right now my application accomplishes this by checking if the user is correct, then hitting the URL https://s3.amazonaws.com/datasets.mysite.com/1243 via AJAX. I can use CORS to allow this AJAX only from https://www.mysite.com.
However if you just type https://s3.amazonaws.com/datasets.mysite.com/1243 into the browser, you can get any file :P
How do I stop S3 from serving files directly, and only enable it to be served via ajax (where I already control access with CORS)?
It is not about AJAX or not, it is about permissions and authorization.
First, your buckets should be private unlike their current state which is world visible.
Then in order for your users to connect, you create a temporary download link which in AWS world called S3 Pre-signed Request.
You generate them in your back-end, here is a java sample
Enjoy,
R

How to restrict the size of the file being uploaded on to the AWS S3 service using presigned urls

I'm using an AWS S3 presigned url to upload picture from a client (mobile app).
I want to prevent the user to upload large files.
Is there a way to limit the file size of an uploaded file?
Thanks
Check out "content-length-range" in s3 policy.
http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html
The conditions in a POST policy is an array of objects, each of which is used to validate the contents of the uploaded object. You can use these conditions to restrict what is allowed in the request. Each form field that you specify in a form (except x-amz-signature, file, policy, and field names that have an x-ignore- prefix) must appear in the list of conditions.
content-length-range
The minimum and maximum allowable size for the uploaded content.
This condition supports content-length-range condition match type.
I have solved this problem perfectly! Though, the POST policy can work, but use presigned urls is more comfortable.
I use nodejs as backend. And use getSignedUrl to limit the size of upload file.
It just need modify three line of aws-sdk code. And I have tried, it can work very well.
I don't know why aws-sdk of nodejs don't support it. If there is some reason, please share to me.
first, open "node_modules/aws-sdk/lib/signers/v4.js", comment the following two line
second, open "node_modules/aws-sdk/lib/services/s3.js", comment the following one line
third, write the code to generate presigned url and upload file