Hi
I have a use case where each of my users in the app can upload their own images for other users in the app to see. Currently, Amplify Storage allows you to create S3 bucket to store images but without the cloudfront part. Is there a way to do that currently? Or is this something that I have to do manually.
It would be nice if the cloudfront used in Amplify hosting can be shared with Amplify Storage. So you end up with one cloudfront and 2 S3 buckets.
Any suggestions about what is the easiest way to do that as Amplify cli stands right now.
Thanks
Agreed, the S3 image downloads are too slow for an app, cloudfront would be a major enhancement
From looking through the source code, this really isn't feasible without a rewrite. I'm haven't determined whether you can create a Cloudfront distribution and use the existing S3 bucket by altering some permissions, but the current Storage implementation relies on the s3 aws-sdk object which doesn't support cloudfront.
@kaustavghosh06 if cloudfront is added manually with a Storage bucket as the origin and the Storage module is modified to retrieve files from the cloudfront url, will Amplify's Auth module still inject the correct credentials into requests? Will Storages' permission system still work behind cloudfront?
+1 for this.
I want to reduce the cost of reads/writes to S3 and so I would like to do this via cloudfront. Is this possible using amplify?
It is somehow possible, but it depends on the usecase. You can make a cloudfront distribution for your S3 bucket and use the cloudfront link to show media files in your app. To restrict access use the origin access with the cloudfront distribution. This only prevents public acces, you still have to refine authorization in your app. You also still have to upload the files with AWS using the s3 Put. Which unfortunatly is slow. For me it would make sense to be able to use the cloudfront link with Put.
Ist that not simple as creating a new S3 + cloudfront ready bucket and then using a lambda function to move/copy images to it? Or am I missing something?
Here are some helpful CloudFormation teamplates:
https://aws.amazon.com/de/blogs/networking-and-content-delivery/amazon-s3-amazon-cloudfront-a-match-made-in-the-cloud/
Has anyone found a proper setup to do this? I'm facing issues serving stored content through s3 with lower latency
Has anyone found a proper setup to do this? I'm facing issues serving stored content through s3 with lower latency
So i ended up doing the following -
Creating a cloud front distribution with restricted access as pointed in(https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html) that points to the S3 bucket created by the amplify add storage.
Created a REST api with API access to only Authenticated users using amplify add api
Added a Lambda function with express js server option during API creation
In the get method of my api i added code that would take a url of the cloud front and signs it using aws-sdk https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CloudFront/Signer.html#getSignedUrl-property
In my app im calling the Rest API with the cloud front URL as query parameter. Something like https://mycloudfront-distribution-url/folder/file
The Rest API will take the query parameter URL and return the Signed URL. Im then taking the signed URL and using that in my code
Above may not be the best approach but thats how i could achieve lower latency without compromising security
My workaround:
amplify add storage
Content (Images, audio, video, etc.)
myImageStorage
my-image-storage
Both
Auth and guest users
create/update, read, delete
Press _space
_ to selectread
Press _space
_ to selectadmin
Press _space
_ to selectcreate/update, read, delete
Press _space
_ to selectNo
amplify push
https://console.aws.amazon.com/cloudfront/home?region=eu-west-2#create-distribution
my-image-storage...
/public
Yes
Create a New Identity
Yes, Update Bucket Policy
Lets say I upload an image file in the S3 bucket with the key public/my-image-123.jpg
, this image will be available through the url https://xxx.cloudfront.net/my-image-123.jpg
@neilime Your solution would let only cloudfront with the specified OAI have access to your bucket which means anybody with the cloudfront URL can access contents of your bucket
my use case is that I wanted to accelerate the read access to the protected (only a certain user can write; anyone can read) files.
I have managed to have the write part work, which is basically the Amplify storage approach, but I am not sure how to make the read part work.
tagging related discussion from @syang - https://github.com/aws-amplify/amplify-js/discussions/6228 it doesnt seem like we have a better process than @neilime's one right now
+1
My workaround:
Run
amplify add storage
- ? Please select from one of the below mentioned services:
Content (Images, audio, video, etc.)
- ? Please provide a friendly name for your resource that will be used to label this category in the project:
myImageStorage
- ? Please provide bucket name:
my-image-storage
- ? Restrict access by?:
Both
- ? Who should have access:
Auth and guest users
- ? What kind of access do you want for Authenticated users?
create/update, read, delete
Press _space
_ to select- ? What kind of access do you want for Guest users?
read
Press _space
_ to select- ? Select groups:
admin
Press _space
_ to select- ? What kind of access do you want for Admin users?
create/update, read, delete
Press _space
_ to select- ? Do you want to add a Lambda Trigger for your S3 Bucket?
No
Run
amplify push
Create cloudfront distribution
https://console.aws.amazon.com/cloudfront/home?region=eu-west-2#create-distribution
Select a delivery method for your content > Web > Get started
- Origin Domain Name:
my-image-storage...
- Origin Path:
/public
- Default Cache Behavior Settings > Viewer Protocol Policy > Redirect HTTP to HTTPS
- Restrict Bucket:
Yes
- Origin Access Identity:
Create a New Identity
- Grant Read Permissions on Bucket:
Yes, Update Bucket Policy
And then what?
Do you still use Storage.get() to get the object?
Do you use aws-sdk - AWS.Cloudfront to fetch it? if so - how do you sign the url?
@tombaumg I have edited my comment in order to explain how to get the image through cloudfront CDN
@tombaumg I have edited my comment in order to explain how to get the image through CloudFront CDN
First of all thanks for the quick reply.
But my S3 resources are protected and can be fetched only with signed urls. Storage.get() is wrapping this logic to me but for example if i want to use aws-sdk S3 service, ill need to use - getSignedUrl to get an authorised url and then fetched the resource.
When it comes to CloudFront, i guess it's blocking me because this one: "https://xxx.cloudfront.net/my-image-123.jpg" is not a signed url, and there's no such thing as the Storage.get() which wrapping the authorising part. (I also can't just view the image from the s3 console because of the same reason).
What do you think?
You don't need an signed url to access the content of cloudfront, but you have to configure your bucket policy in order to allow cloudfront to access the content of this bucket as I've explain in my comment.
@neilime That worked for me. I didn't follow the steps exactly and spent a few hours digging through some issues with the bucket not set to restricted. It worked perfect and I've made sure to add the appropriate "reactions" to your post. Thank you so much!
Up
I would like to see as a cli command, while we waiting I'm using the custom CloudFormation stack for that, here is an example, https://docs.amplify.aws/cli/usage/customcf#secondary-nav
You need to add the custom resource with your cloudfront template inside the backend folder and the dependency of your S3 in the backend-config.json file and that's it, you have automated the creation of the cloudfront within amplify. 馃樃
+1
Most helpful comment
My workaround:
Run
amplify add storage
Content (Images, audio, video, etc.)
myImageStorage
my-image-storage
Both
Auth and guest users
create/update, read, delete
Press _space
_ to selectread
Press _space
_ to selectadmin
Press _space
_ to selectcreate/update, read, delete
Press _space
_ to selectNo
Run
amplify push
Create cloudfront distribution
https://console.aws.amazon.com/cloudfront/home?region=eu-west-2#create-distribution
Select a delivery method for your content > Web > Get started
my-image-storage...
/public
Yes
Create a New Identity
Yes, Update Bucket Policy
Get image cdn url
Lets say I upload an image file in the S3 bucket with the key
public/my-image-123.jpg
, this image will be available through the urlhttps://xxx.cloudfront.net/my-image-123.jpg