We are storing files uploaded by users of our app to Amazon S3.
In order to keep these files private & secure, we are:
having the client generate a UUID for the filename (so that the URL of the file is difficult to guess). See: What is the probability of guessing (matching) a Guid?
going to protect the data by using client-side encryption.
Do these two measures provide sufficient security, or should we also use Amazon Cognito to ensure that the user getting the object is one of the users who has access to it?
Using obscure filenames is not a good security method.
If you wish to allow users to upload/download data to/from Amazon S3 in a secure manner, you should use Pre-Signed URLs.
The process is:
Users authenticate to your web/mobile application
Users interact with your application and indicate they wish to upload/download a file
Your application generates a pre-signed URL that includes an authorization to access Amazon S3, with restrictions such as bucket, path and file size
Users upload/download the file using the pre-signed URL
This way, your application controls the security and there is no potential for accidental workaround, overwriting, access, etc.
See: Uploading Objects Using Pre-Signed URLs
Related
I have a bunch of 3D models on my web app and they are accessible to public to see but I don't want anyone to download them. I use Amazon S3. Is there any way to achieve this?
In the default web app - as already commented - if the client can "see" the resource, it is already on the client's side.
There are two aspects of the question. You want to prevent accessing the models from the public (unauthenticated) client or even the authenticated.
To prevent unauthorised access to S3 resources used for web apps, the common option is using the pre-signed S3 url. The application generates temporary resource link only for authorized users.
If you want to prevent access to resources even authorized users, to you can render the view on the server side e.g. see AWS AppStream
I have a MEAN stack app built where the user can upload images. Currently, I'm storing the URLs of the images in mongodb, and the images themselves in the filesystem in a specified folder. I've read that it's better to store these images somewhere like AWS or firebase for scalability, so I decided to go with AWS.
I created a bucket and can upload images fine via multer.
How can I allow users to only retrieve their images when they are logged into my app? The authentication in the frontend and backend is already finished, but I can't figure out how to use this with accessing the s3 bucket and only getting the user specific images.
I could make the bucket public and easily build the URLs, but that means everyone (regardless if they are logged into my app or not) can access them, which is not what I want.
If you can authenticate your users as Amazon Cognito users then during a login they will assume a role.
If that role has a policy attached for S3 you can use the ${cognito-identity.amazonaws.com:sub} variable. By structuring your S3 bucket to use key paths containing this variable in it you can develop a policy that will only grant access to keys with the prefix of that user id.
Take a look here for an example S3 policy.
I have a bunch of images on my S3 which is linked with Cloudfront.
Now I have a web server and I only want users to view the image through my website so I can't just give out links to the image. How do I set that?
It appears that your requirement is:
Content stored in Amazon S3
Content served via Amazon CloudFront
Content should be private, but have a way to let specific people view it
This can be accomplished by using Pre-Signed URLs. These are special URLs that only work for a limited period of time.
When your application determines that the user is entitled to view an image, it can generate a Pre-Signed URL that grants access for a limited period of time. Simply use this URL in an <IMG> tag as you would normally.
See:
Amazon S3 pre-signed URLs
Amazon CloudFront pre-signed URLs
Since your content in Amazon S3 will be private (so users cannot bypass CloudFront and access it directly), you will also need to grant CloudFront permission to access the content from S3. See: Using an Origin Access Identity to Restrict Access to Your Amazon S3 Content
Another option, instead of creating a pre-signed URL each time, is to use Signed Cookies. However, this doesn't give fine-grained control for access to individual objects -- it's more for granting access to multiple objects, such as a subscription area.
I am building an app that needs to upload files to S3. Initially, I had my secret key in the web.config file. Since they key has access to my entire account, I am realizing that instead I should rely on the IAM services to just generate a user for accessing a bucket.
However, this doesn't solve the problem of storing the key in plain text. How can I manage it otherwise?
Actually IAM permissions to S3 do solve your problem because the user that you'll create will be only allowed to access this specific bucket - it can't do any harm to your account and you don't have to store the access/secret keys on the machine.
Further, you can restrict access to a bucket to a specific IP.
We have a Java product which may put and get data from Amazon S3. We already successfully implemented a class responsible of that by using the Amazon SDK for Java.
But, as far as I know, to interact with Amazon S3 through the library, you have to instantiate an AmazonS3Clientobject by providing an access key and a secret key.
Even if this technique can be relatively safe by using Amazon IAM and restrict access of the keys to the specific bucket of S3 you want to pull and put data, it is still a security hole in a sense that someone could decompile your application to extract the keys and use them to access your bucket's data.
Is there a safer way to do that ? Can we avoid to embed the AWS credentials in the application ? Can we make a REST call to our server to sign the requests (and keep the keys secret) ?
Take a look at the Amazon Secure Token Service (JavaDoc) as well as the Token Vending Machine to see if these help to resolve your issue.