Allow S3 hosted App exclusive permission to upload files to public bucket - amazon-web-services

I have a static React App I have deployed using Cloudfront - hosted within an S3 Bucket. I would like the user to have the option to upload files in the future, through this app, to the bucket but I am a little confused on the permissions side.
I have created the Bucket with the CDK like so...
val siteBucket = Bucket(
this, "SiteBucket",
BucketProps.builder()
.bucketName(SITE_DOMAIN_NAME)
.websiteIndexDocument("index.html")
.publicReadAccess(true)
.removalPolicy(DESTROY)
.build()
)
I have additional config using the CDK to hook up the CloudFrontWebDistribution and to route the traffic to my domain.
My understanding of the above is that .publicReadAccess(true) allows my Bucket to be accessible to the wider internet - but that it doesn't grant any rights to upload to the bucket.
However, how do I use the CDK to grant permissions for only my static webapp to upload to the Bucket - but not for anyone else to upload?
(I've been reviewing this https://docs.aws.amazon.com/cdk/v2/guide/permissions.html but unsure of the best practise e.g. can my app have a role or permissions assigned to when the app itself is just the contents of a bucket. Do I need to create an Access Point? But again, how do I limit my app to have permissions - is this even possible with a static app or do I need a backend/Lambda to invoke first?)
Thanks!

For one, you don't need publicReadAccess. You can just grant access to the OAI.
https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-access-to-amazon-s3/
This is a pretty good starting point for the page though:
https://aws.amazon.com/blogs/storage/allowing-external-users-to-securely-and-directly-upload-files-to-amazon-s3/
Not sure you necessarily want to use the same bucket to upload to and host your site.

Related

AWS: Does my S3 bucket need a policy for files to be readable from my application?

I have a Laravel application that is hosted on AWS. I am using an S3 bucket to store files. I know that I have successfully connected to this bucket because when I upload files, they appear as I would expect inside the bucket's directories.
However, when I try to use the URL attached to the uploaded file to display it, I receive a 403 Forbidden error.
I have an IAM user set up named laravel which has the permission AmazonS3FullAccess applied to it, and I am using that key/secret.
I have the Object URL like so:
https://<BUCKET NAME>.s3.eu-west-1.amazonaws.com/<DIR>/<FILENAME>.webm
But if I try to access that either in my app (fed into an audio player) or just via the link directly, I get a 403. None of the tutorials I've followed to get this working involve Bucket Policies, but when I've googled the problems I'm having, Bucket Policy seems to come up.
Is there a single source of truth on how I am to do this? My AWS knowledge is very limited, but I am trying to get better!
When you request a URL of the form https://bucket.s3.amazonaws.com/dog/snoopy.png, that request is unauthenticated. Your S3 bucket policy does not allow unauthenticated access to the contents of the bucket so that request is denied with 403.
If you want your files to be downloadable by an unauthenticated/anonymous client then create an S3 bucket policy to allow that.
Alternatively, your server can create signed URLs and share those with the client.
Otherwise, your client's requests need to be authenticated, which means having correctly-permissioned credentials and using an AWS SDK.
Typically, back-end applications that you write that need access to data in S3 (or other AWS resources) would be given AWS credentials allowing the necessary access. If your back-end application runs in AWS then you would do that by launching the compute with an IAM role.
Typically, front-end applications would not have AWS credentials. Instead they would either authenticate to a back-end that then does work with AWS resources on their behalf. There are other options, however, such as AWS Amplify apps.

AngularJS app in AWS S3. What should be correct policies?

I need to quickly deploy a static angular app to AWS S3. Unfortunately, I am still new to id so I would like to ask your help on:
What should be the bucket policy?
What roles should I give a user group to access it?
Requirements:
App deployed in the S3 bucket is public
Bucket contents should only accessible by those part of a user group. The users of the group should only be able to upload and get files in the bucket. Nothing more nothing less.
Another user group as administrators of the bucket.
Thanks. Any help would be appreciated.
Have you read Hosting a static website using S3? That should answer your question about bucket policy.
IAM users will need the appropriate S3 permissions on the bucket. This is an example of a read-write policy; remove the s3:PutObject and s3:DeleteObject permissions for read-only access.
As luk2302 pointed out, if you want to publish the S3 URL as your website URL, then the bucket contents must be publicly readable. If you want to publish the app using a custom domain name and/or use HTTPS, you should consider adding a CloudFront distribution. Doing so would also allow you to keep the bucket contents private so only your IAM users have direct access to the bucket.

Should my bucket be public for my usecase and how should I avoid bad practice?

I'm new to AWS tools and although I have tried to search thoroughly for an answer I wasn't able to fixate on a solution.
My usecase is this:
I have a bucket where I need to store images, upload them via my server however I need to display them on my website.
Should my bucket be public?
If not, what should I do to allow everyone to read those images but not be able to mass upload on it from origins who are not my server?
If you want the images to be publicly accessible for your website, then the objects need to be public.
This can be done by creating a Bucket Policy that makes the whole bucket, or part of the bucket, publicly accessible.
Alternatively, when uploading the images, you can use ACL='public-read', which makes the individual objects public even if the bucket isn't public. This way, you can have more fine-grained control over what content in the bucket is public.
Both of these options require you to turn off portions of S3 Block Public Access to allow the Bucket Policy or ACLs.
When your server uploads to S3, it should be using Amazon S3 API calls using a set of AWS credentials (Access Key, Secret Key) from an IAM User. Grant the IAM User permission to put objects in the bucket. This way, that software can upload to the bucket totally independently to whether the bucket is public. (Never make a bucket publicly writable/uploadable, otherwise people can store anything in there without your control.)
upload them via my server however I need to display them on my website.
In that case only your server can upload the images. So if you are hosting your web app on EC2 or ECS, then you use instance role and task role to provide S3 write access.
Should my bucket be public?
It does not have to. Often CloudFront is used to host images or files from S3 using OAI. This way your bucket remains fully private.

S3 PUT bucket access to all users though mobile application

I’m an upcoming aws developer and I am trying to understand the best practices. I have a mobile application and all the users will upload photos of their recipes through the app. I am trying to find a way to give limited access to my s3 bucket to my app for users to upload the images. Is there a way to do that with hard coding credentials on my app? So the bucket is private and all objects are private but my app needs to be put in the bucket. I don't know which to pick like AWS Cognito or S3 pre-signed URLs for the app to get limited access. Also, the solution should scale multi-region i.e on an Active-Active deployment it should be routed to the Closest Bucket t the user.
Thank you

How to access objects in S3 bucket, without making the object's folder public

I have provided AmazonS3FullAccess policy for both the IAM user and group. Also the buket that I am trying to access says "Objects can be public". I have explicitly made the folder inside the bucket public. Despite all this I am getting access denied error when I tried to access it through its url. Any idea on this?
Objects in Amazon S3 are private by default. This means that objects are not accessible by anonymous users.
You have granted permission for your IAM User to be able to access S3. Therefore, you have access to the objects but you must identify yourself to S3 so that it can verify your identity.
You should be able to access S3 content:
Via the Amazon S3 management console
Using the AWS CLI (eg aws s3 ls s3://bucketname)
Via authenticated requests in a web browser
I suspect that you have been accessing your bucket via an unauthenticated request (eg bucketname.s3.amazonaws.com/foo.txt. Unfortunately, this does not tell Amazon S3 who you are, so it will deny the request.
To access content with this type of URL, you can generate an Amazon S3 pre-signed URLs, which appends some authentication information to the URL to prove your identity. An easy way to generate the URL is with the AWS CLI:
aws s3 presign s3://bucketname/foo.txt
It will return a URL that looks like this:
https://bucketname.s3.amazonaws.com/foo.txt?AWSAccessKeyId=AKIAxxx&Signature=xxx&Expires=1608175109
The URL will be valid for one hour by default, up to 7 days.
There are two ways I will recommend.
go to s3 dashboard, and download the object you need, one by one manually, the bucket can be kept private at the same time.
build a gateway/a small service, to handle authentication for you, set a policy and give the permission to the service container/lambda to visit the private bucket, and restrict only specific users to download the objects.
References
download from aws s3
aws policy, permission and roles