I have created an SSL certificate with ACM. I would like to use this certificate to serve both my static content from an S3 bucket and my lambdas. At this time, I want to avoid using CloudFront and proxy both S3 and Lambda with API Gateway so that everything is served from a single SSL domain (no CORS issues).
Ideally, I will call:
https://my.customdomain.com/ (lambda redirects to /web/index.html)
https://my.customdomain.com/api/* (lambdas)
https://my.customdomain.com/web/* (static content - s3)
Is the above architecture reasonable/possible?
Yes, the architecture is possible.
API Gateway has this objective. To serve as a Gateway for backend services that are not exposed to your customer. One of the options to integrate with API Gateway is with Amazon S3.
Basically you will foward the object key to S3 and request this object using S3 API Calls (executed by API Gateway). You'll just need to give API Gateway the correct permissions to make this call with the proper credentials.
You can find the information needed to make this work here.
Related
I am hosting a static website in AWS cloudfront with S3 Bucket Origin. I want to send from the frontend an API request to the AWS service API Gateway, to activate a lambda function and send an email using the service SES.
I want to use the Serverless framework to build it.
I want to restrict the access for the API Gateway to be only accessed from Cloudfront, so I wonder how can I add a restriction in the API gateway to be only accessed by: https://mywebsite.
I have created a list of possible services where I think this rule can be added:
At the rule in the YML file in Serverless framework
adding this rule in the API gateway once is created
Using AWS WAF
add an API Key in the Cloudfront distribution to the send in the header
Using a lambda function as a custom validator
If there is more than one that is possible which one would be the best or simple way?
I need to secure my s3 bucket objects. In my web application I'm using aws-sdk to upload media to s3 bucket and get an http link back to access that object. This http link is public by default and I want to make it secure so that only authorized users can access the media. aws s3 allows to make the object private but it wont let anyone with the link access the object.
This link will be accessed from a mobile app where I dont want to use aws-sdk, Instead I want to execute some logic on aws side whenever someone tries to access the http link for the object.
What I would like to happen is, before the user gets access to s3 object, Some authorizer code would execute (like a jwt token authorizer) and depending on it user would be granted/denied access.
I'm currently looking into Amazon API Gateways, I believe they can be accessed as an http link and AWS Lambda could be used to secure them(where i would execute my jwt authorizer). Then these apis would have access to s3 internally.
If someone could point me in the right direction, If this is at all possible.
If I could use the same jwt token issued from my web-application to send along the request to Amazon API Gateway, that would be great.
I would make the bucket private, and place a CloudFront distribution in front of it. Using an Origin access identity to allow only CloudFront to directly access the S3 bucket.
Then to provide security I would use either CloudFront signed cookies, or Lambda#Edge with a custom JWT token validation.
The easiest solution to expose private objects in an S3 bucket is to create a pre-signed URL. Pre-signed URLs use the permissions from the service (which pre-signs the URL) to determine access and have only a limited duration in which they can be used. They can also be used to upload an object directly to S3 instead of having to proxy the upload through a lambda function.
For a download functionality and a smooth user experience, you can - for example - have a lambda function that generates a pre-signed URL and returns it as an HTTP 302 response, which should instruct the browser to automatically download the file from the new URL.
(Edit)
Following on what I've stated in the comments on this answer, if you're proxying the upload/download of the objects through services such as API Gateway or Lambda, you will be severely limited in the size of files that you are able to upload to S3. The payload size limit on an API Gateway is 10 MB and for requests to lambda your payload is capped at 6MB for synchronous invocations. If you want to upload something larger than 10 MB, you will need to use direct upload to S3 for which pre-signed URLs are the safest solution.
I know I am bit late here, but I wanted to give my opinion in case someone has the same problems.
Your mobile app should communicate with a server app (backend app) for authentication and authorization. let's say you are deploying your server app on AWS VPC. Now, it's simple to manage the files access by creating a policy which allow just your server app (IP, or VPC) to access the bucket. the authorization part will be managed on your application.
I'm working on the application that will receive files from users and then upload to Amazon S3. The application is accessed using API Gateway. The service API Gateway has limits for payload size for both WebSocket and REST APIs. Is there any way to access my service from the Internet through API Gateway?
API gateway is not intended to be data transfer gateway, but lightweight API definition layer.
The most suitable approach is to generate temporary pre-signed upload URL and redirect (30X) requests there. API Gateway should define an endpoint, calling lambda function which generates pre-signed S3 URL and redirect post request there (after user's authentication of course).
Please refer an example of app with API Gateway and pre-signed S3 URLs to upload files
API documentation for generating pre-signed S3 URLs in Python, AWS CLI and even Go-lang
Recently I have been working with AWS API gateway where I created an API and protected it with API key and Cognito (OAuth).
One day I found that my API has been accessed 10K times which failed because of attacker didn't had the access to it.
My question is : Does Amazon charge for such api calls which are unauthorized? If they charge then how to protect it. As I understand even if I put WAF in front it my API url will still be exposed ....
Any help is appreciated...
If you protect your endpoint with the following authorization types: AWS_IAM, CUSTOM, and COGNITO_USER_POOLS, API Gateway will not be charged for failed requests. Please reference the Pricing Documentation. Also reference Secure AWS API Gateway with Lambda Integration
What you are describing is a type of DDoS attack.
This is what you need to do to protect your API Gateway Endpoint from DDoS attack.
1) Create your API
2) Setup CloudFront distribution to your API
3) Front your CloudFront distribution with AWS WAF.
4) Create ACL rule and set requester limit to what you deem appropriate.
5) Test.
You still need to use AWS_IAM or Cognito to do the authorization part.
Here is the document that details the steps:
https://aws.amazon.com/blogs/compute/protecting-your-api-using-amazon-api-gateway-and-aws-waf-part-i/
Let say I need an API Gateway that is going to run Lambdas and I want to make the best globally distributed performing infrastructure. Also, I will use Cognito for authentication, Dynamodb, and S3 for user data and frontend statics.
My app is located at myapp.com
First the user get the static front end from the nearest location:
user ===> edge location at CloudFront <--- S3 at any region (with static front end)
After that we need to comunicate with API Gateway.
user ===> API Gateway ---> Lambda ---> S3 || Cognito || Dynamodb
API Gateway can be located in several regions, and even though is distributed with CloudFront, each endpoint is pointing to a Lambda located at a given region: Let say I deploy an API at eu-west-1. If a request is sent from USA, even if my API is on CloudFront, the Lambda it runs is located at eu-west-1, so latency will be high anyway.
To avoid that, I need to deploy another API at us-east-1 and all my Lambdas too. That API will be pointing to those Lambdas
If I deploy one API for every single region, I would need one endpoint for each one of them, and the frontend should decide which one to request. But how could we know which one is the nearest location?
The ideal scenario is a single global endpoint at api.myapp.com, which is going to go to the nearest API Gateway which runs the Lambdas located in that region too. Can I configure that using Route 53 latency routing with multiple A records pointing to each api gateway?
If this is not right way to do this, can you point me in the right direction?
AWS recently announced support for regional API endpoints using which you can achieve this.
Below is an AWS Blog which explains how to achieve this:
Building a Multi-region Serverless Application with Amazon API Gateway and AWS Lambda
Excerpt from the blog:
The default API endpoint type in API Gateway is the edge-optimized API
endpoint, which enables clients to access an API through an Amazon
CloudFront distribution. This typically improves connection time for
geographically diverse clients. By default, a custom domain name is
globally unique and the edge-optimized API endpoint would invoke a
Lambda function in a single region in the case of Lambda integration.
You can’t use this type of endpoint with a Route 53 active-active
setup and fail-over.
The new regional API endpoint in API Gateway moves the API endpoint
into the region and the custom domain name is unique per region. This
makes it possible to run a full copy of an API in each region and then
use Route 53 to use an active-active setup and failover.
Unfortunately, this is not currently possible. The primarily blocker here is CloudFront.
MikeD#AWS provides the info on their forums:
When you create a custom domain name it creates an associated CloudFront distribution for the domain name and CloudFront enforces global uniqueness on the domain name.
If a CloudFront distribution with the domain name already exists, then the CreateCloudFrontDistribution will fail and API Gateway will return an error without saving the domain name or allowing you to define it's associated API(s).
Thus, there is currently (Jun 29, 2016) no way to get API Gateway in multiple regions to handle the same domain name.
AWS has no update on providing the needful since confirming existence of an open feature request on July 4, 2016. AWS Form thread for updates
Checkout Lambda#Edge
Q: What is Lambda#Edge? Lambda#Edge allows you to run code across AWS
locations globally without provisioning or managing servers,
responding to end users at the lowest network latency. You just upload
your Node.js code to AWS Lambda and configure your function to be
triggered in response to Amazon CloudFront requests (i.e., when a
viewer request lands, when a request is forwarded to or received back
from the origin, and right before responding back to the end user).
The code is then ready to execute across AWS locations globally when a
request for content is received, and scales with the volume of
CloudFront requests globally. Learn more in our documentation.
Usecase, minimizing latency for globally distributed users
Q: When should I use Lambda#Edge? Lambda#Edge is optimized for latency
sensitive use cases where your end viewers are distributed globally.
Ideally, all the information you need to make a decision is available
at the CloudFront edge, within the function and the request. This
means that use cases where you are looking to make decisions on how to
serve content based on user characteristics (e.g., location, client
device, etc) can now be executed and served right from the edge in
Node.js-6.10 without having to be routed back to a centralized server.