AWS S3 PreSigned URL Permissions at the Creation Level & Usage Level - amazon-web-services

Is there a way to restrict the permissions of my Users so that, they should not be able to create/generate a presigned URL for the S3 objects that they have access to. ?? My users should not be able to generate a pre-signed URL even if they have access to the S3 objects.
Either restricting their ability of generating presigned URL or atleast detecting an action in real-time when its created is also fine with me.
It looks like there is no cloudtrail API call for generating presigned URL or also there is no cloudtrail API call whenever the generated presigned URL is used for accessing the S3 object.
So, I am stuck at this point and we as a platform team need to stop our App users from being able to generate presigned URLs and give them out to unauthorized users.

Related

AWS S3 Per Bucket Permission for non-AWS accounts

This question is in the same line of thought than Is it possible to give token access to link to amazon s3 storage?.
Basically, we are building an app where groups of users can save pictures, that should be visible only to their own group.
We are thinking of using either a folder per user group, or it could even be an independent S3 bucket per user group.
The rules are very simple:
Any member of Group A should be able to add a picture to the Group A folder (or bucket)
Any member of Group A should be able to read all pictures of the Group A folder (or bucket)
No member of Group A should not have access to any of the pictures
However, the solution used by the post mentioned above (temporary pre-signed URLs) is not usable, as we need the client to be able to write files on his bucket as well as read the files on his bucket, without having any access to any other bucket. The file write part is the difficulty here and the reason why we cannot use pre-signed URLs.
Additionally, the solution from various AWS security posts that we read (for example https://aws.amazon.com/blogs/security/writing-iam-policies-grant-access-to-user-specific-folders-in-an-amazon-s3-bucket/) do not apply because they show how to control accesses for IAM groups of for other AWS accounts. In our case, a group of users does not have an IAM account...
The only solutions that we see so far are either insecure or wasteful
Open buckets to everybody and rely on obfuscating the folder / bucket names (lots of security issues, including the ability to brute force and read / overwrite anybody's files)
Have a back-end that acts as a facade between the app and S3, validating the accesses. S3 has no public access, the bucket is only opened to an IAM role that the back-end has. However this is a big waste of bandwidth, since all the data would transit on the EC2 instance(s) of that back-end
Any better solution?
Is this kind of customized access doable with S3?
The correct way to achieve your goal is to use Amazon S3 pre-signed URLs, which are time-limited URLs that provides temporary access to a private object.
You can also Upload objects using presigned URLs - Amazon Simple Storage Service.
The flow is basically:
Users authenticate to your back-end app
When a user wants to access a private object, the back-end verifies that they are permitted to access the object (using your own business logic, such as the Groups you mention). If they are allowed to access the object, the back-end generates a pre-signed URL.
The pre-signed URL is returned to the user's browser, such as putting it in a <img src="..."> tag.
When the user's browser requests the object, S3 verifies the signature in the pre-signed URL. If it is valid and the time period has not expired, S3 provides the requested object. (Otherwise, it returns Access Denied.)
A similar process is used when users upload objects:
Users authenticate to your back-end app
They request the opportunity to upload a file
Your back-end app generates an S3 Pre-signed URL that is included in the HTML page for upload
Your back-end should track the object in a database so it knows who performed the upload and keeps track of who is permitted to access the object (eg particular users or groups)
Your back-end app is fully responsible for deciding whether particular users can upload/download objects. It then hands-off the actual upload/download process to S3 via the pre-signed URLs. This reduces load on your server because all uploads/downloads go direct to/from S3.

Restrict S3 objects URL only to logged in users on a website

My website has some files hosted on AWS S3 buckets, but I need to restrict access to the s3 objects URL to only logged in users of the website. Something similar to how google drive works. which means that anyone trying to access the urls to any of the files on our S3 bucket needs to be logged into the website before he or she would be able to.
Is this possible?
Thanks
If you want to restrict access to the S3 objects, don't make the objects public and don't use the public URLs shown on AWS S3 console.
S3 provides an option to generate pre-signed URLs to download S3 objects. So once your users log in to your website and when they request to download the S3 object, make a request to S3 to generate this pre-signed URL. Clicking on the pre-signed URL will download the object.
With pre-signed URLs, you can configure additional options like expiry time, so that these URLs are more secure.
You can find more info about pre-signed URLs and their implementation here.
If you happen to use AWS Cognito for log in/out functionality, you can assign IAM roles to logged in users.
This way when trying to access the s3 bucket, you can restrict access using IAM roles.
AWS Amplify would be a good fit for this use-case.

How to make sure a S3 presigned GetObject URL can only be accessed from an authorized device?

I want to provide a presigned s3 url for authenticated users to download files. I have a JWT based authentication on my backend and the URL can be generated on my backend based on the token. So if a user is authenticated on a device, they can click on a button and it opens a new tab pointing at the presigned url. My question is, how to prevent the user to copy the url on to an unauthenticated device and access the file from there? I referred to AWS S3 authenticated user access using presigned URLs? this, but it doesn't solve my problem.
Generally no, that is not possible, a pre-signed URL is valid from any browser and any device. You cannot prevent a user from copying and sharing the link.
The only thing you could do is reduce the duration for which the presigned url is valid, if you open the link in a new tab and set the duration of the presigned url only be e.g. 5 seconds you massively reduce the chance or the effect of the user being able to share the link in time.

is there a way to limit access to s3 presigned url

I have a use case of allowing users to access remote file present in s3. Currently I am sending the pre-signed url in an email and allowing access. But I have a use case that is not met with this solution.
That being, in case the email containing the pre-signed url is forwarded to someone unintended, the forward recipient should not be able to access the file. Is there a way of authenticating an s3 presigned url by means of id/password. I am also open to a different solution using other AWS services as well to meet the use case.
Pre-signed URLs aren't particularly good for emails.
The intention with a pre-signed URL is that a user would authenticate to an application, then request access to some private content. The application would verify that they are permitted access, then provide a pre-signed URL to grant time-limited access to the content. Such access would normally be for up to 5-10 minutes.
As demonstrated by your scenario, there is an issue if somebody forwards a pre-signed URL to somebody else. This is normally not a problem because access time is limited. However, if a pre-signed URL is generated that has access for hours or days, it becomes more of a security issue.
Solution: Provide a link to your application. Users should authenticate, then be provided with a short-duration (eg 5-minute) pre-signed URL. This lowers the chance that other people can use the link.
By default you can't limit who can use the pre-sign url. The entire purpose of pre-signed S3 urls is to enable access to your object to anyone who has them for a limited time:
Anyone who receives the presigned URL can then access the object.
If this does not suit you, you have few choices:
don't use pre-signed urls, but instead create an IAM user which just the permissions to download the object. This will require login to the AWS by your recipients.
use password protected 7zip or rar files that contain your objects. So instead of downloading objects directly, you provide pre-signed urls to password-protected archives.
use encryption and share encrypted files. You clients will need to decrypt them.
and many others
But ultimately they will be as save as your users' passwords, encryption keys or other types of protection you will implement.

Create temporary credentials to upload file to S3 bucket

I need to validate client and then generate temporary credentials (valid for few seconds) using which client can upload a file on my S3 bucket. I cannot create a user for the client. First I validate the client using OAuth and if the client is valid, I need to enable it to upload the file to S3. I know about presigned URL way, but am wondering is there another way.
using which client can upload a file on my S3 bucket.
..
know about presigned URL way, but am wondering is there another way
As already answered, I see two ways. The presigned url or assumed IAM role (e. g. though cognito or own/custom identity broker)
There is a significant difference.
While using the presign url, it allows the client to upload/update a very specific object defined by the url in S3. I like this approach because of its simplicity, more control over expiration and I imho more secure (less work around managing permissions)
When using the assumed credentials, you may give the user more privileges (e. g. upload any object with specific prefix, tag the object, ,..). However you may have more work to manage the permission and control the expiration (default lifetime of the assumed role credentials is 15min and can be prolonged to 12h).
First I validate the client using OAuth
Still you may create a presigned url using the assumed (temporary) identity
You could use Amazon Cognito with OAuth. This will assume an IAM role and generate temporary credentials for you.