I'm currently testing out how to setup CloudFront with Regional Api Gateway that includes a Custom Domain but have run into a bit of snag.
I would like to be able to use: https://mySuperDomain.com/rest/get_stuff
Setup:
Api Gateway
I have a regional Api Gateway that points to a Lambda function.
The Gateway includes a Cognito Authorizer
The Integration Request is a Lambda Proxy
The base Resource is "/" with Methods: GET & OPTIONS
The stage is "dev"
Custom Domain name and ACM are set to "mySuperDomain.com"
Configuration is also Regional
Directly calling the url works as expected: https://XXXXXXXX.execute-api.REGION.amazonaws.com/dev
Route53
A record is an alias that points to the CloudFront Distribution
Base domain also contains NS, SOA, and MX
CloudFront
Origins:
Alternate Domain Names: www.mySuperDomain.com & mySuperDomain.com
Origin and Domain Path: XXXXXXXX.execute-api.REGION.amazonaws.com/dev
HTTPS only
Behaviors:
/rest/*
Origin group is set to the Origin
HTTPS only
This is where things get confusing.
When including no headers, I get a "Missing Authentication Token" error. This signals to me that I'm hitting the correct endpoint but the Authentication Token is not making it through CloudFront.
However, when I whitelist what I describe as the kitchen sink: "Authorization, Host, Origin, Referer, Accept-Datetime", I get 403 Forbidden when calling: https://mySuperDomain.com/rest/get_stuff.
What am I missing in order to access the specified custom domain URL? Thanks ahead of time.
Related
I tried to create a HTTP API through API Gateway.
This API generated a URL e.g. https://{api-id}.execute-api.{region}.amazonaws.com/
This endpoint works as intended.
After this; I created a custom domain name and under "Api Mappings", I added this newly created API, set the stage the $default and left Path (Optional) as blank. This generated another endpoint (which is supposed to be added as an A record in Route53). When I try to hit this new endpoint; I get {"message":"Not Found"}. This "connection" between the custom domain endpoint and the working api gateway endpoint doesn't seem to work. Any pointers on how to fix this?
Other Information:
I own the custom domain
Adding a custom domain required uploading a SSL certificate (I had a valid one and I uploaded it - verified and all good)
The API is a basic HTTP API which refers to a Cloudfront URL. This endpoint is fully functional and working as expected.
Endpoint Type: Regional
No multiple "Stages" for API/Routes - only a $default one
I have the following AWS architecture:
Dns Name -> Cloud front
Cloud front -> API gateway
API gateway -> Lambda function
Problem can not identify Dns Name inside Lambda function
The only thing that I can get from request headers is dns name of API gateway
Are there any Cloud front configuration that allows to pass user entered dns name through all the layers till backend code?
in headers I receive host field but it contains dns of api gateway and not cloud front or public dns name
"Host": [
"9b8vc8vvhl.execute-api.us-east-1.amazonaws.com"
],
Here's what is passed in browser
UPDATE:
Implementation attempt from comment
gives
503 ERROR
The request could not be satisfied.
The Lambda function associated with the CloudFront distribution is invalid or doesn't have the required permissions. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
Generated by cloudfront (CloudFront)
Request ID: n03zM0u93vrvdcwQi-hgyhONbv3b10x3ETq-A4Ru7-fC-RUlskjJxQ==
The reason why you get 9b8vc8vvhl.execute-api.us-east-1.amazonaws.com as Host in your lambda function is because, by default, CloudFront rewrites the Host in the origin request.
From HTTP request headers and CloudFront behavior documentation:
Header
Behavior if you don't configure CloudFront to cache based on header values
Host
CloudFront sets the value to the domain name of the origin that is associated with the requested object.
Host in the request header that your browser sends to CloudFront: yuriy-test-cars2.pp.ca (CloudFront uses this value to route your request to the distribution owned by you)
Host in the request header of the origin request that CloudFront sends to API Gateway: 9b8vc8vvhl.execute-api.us-east-1.amazonaws.com (This is the origin domain that you configured in your distribution. CloudFront sets it as the value of the Host header in the origin request. This is consistent with what the documentation says.)
Issue
You can't simply passthrough the Host header to the origin in CloudFront since the API Gateway service uses this value to route your request to the API that you created.
Solution
Create a CloudFront Function to make a copy of the Host header.
function handler(event) {
var request = event.request;
request.headers['cf-host'] = request.headers.host;
return request;
}
Here, I save the value to a custom header named Cf-Host.
Associate this function to the viewer request event.
Create an Origin request policy and include the Cf-Host header in the policy. This makes sure that the Cf-Host header is included in the origin request.
You will be able to access the Cf-Host header in your lambda function. The value of the Cf-Host header is the alternative dns name that you are looking for.
Don't know if my solutions is suitable for you, but I have a similar architecture, except the step Cloud Front > API Gateway.
My DNS is a direct CNAME to API Gateway DNS which result in the original header once the request is logged:
My APIGateway also has a "Custom domain name" ties to it, this way AWS create the proper ssl certificate for the my public domain.
Also the API Gateway endpoint could be edge-optimized (https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-endpoint-types.html) to be server phisiclaly near the user.
If you don't need any caching feature, maybe you could give a try.
I have a REST API serving behind API Gateway.
I have a Route53-hosted zone: myAWSHostedDomain.myCompanyDomain.com
I have also created a certificate in ACM: myApp.myAWSHostedDomain.myCompanyDomain.com
The certificate has an additional domain:
myApp.myCompanyDomain.com
The cert has been issued without any problem, both domains were validated.
In the company non-AWS-hosted zone myCompanyDomain.com, I have a CNAME pointing myApp to myApp.myAWSHostedDomain.myCompanyDomain.com. It resolves OK.
I have configured a Custom Domain for that API Gateway using that certificate. The name that shows is myApp.myAWSHostedDomain.myCompanyDomain.com. Which is fine because it's the main domain for that cert.
The problem I have is that all the requests made to myApp.myCompanyDomain.com fail with a 403 Forbidden error, while those same requests on the myApp.myAWSHostedDomain.myCompanyDomain.com work just fine. The app code has nothing to do with it, a request for a favicon.ico behaves the same way.
The API Gateway endpoint is configured as a Regional one.
Could it be that API Gateway's custom domain only takes the main domain from the certificate and doesn't work with the additional ones? Is there a way to fix this?
So, the problem is that the request fails with a 403 forbidden error, because API Gateway is unable to set the correct Host header, which is required for the request to succeed.
If I do:
curl https://myApp.myCompanyDomain.com/favicon.ico -H "Host:myApp.myAWSHostedDomain.myCompanyDomain.com"
Then, it works.
Hence, the options here are the following:
Create a DNS record in Route53 for myApp.myCompanyDomain.com.
While calling the API, add a Host header to the request, with the value set as the value for the DNS record.
Create a new API Gateway where the main custom domain corresponds with the one in the API Gateway: myApp.myCompanyDomain.com work instead of myApp.myAWSHostedDomain.myCompanyDomain.com work.
I've deployed an SPA to S3 Static Hosting. We're using CloudFront in front of it which would be accessed at www.example.com
However - we want to be able to trigger a lambda function at www.example.com/email as a POST request. I've configured and setup API Gateway and tested both the Lambda function itself, and API Gateway and I am able to send out an email using CURL/Postman.
When trying to use API Gateway through CloudFront I am getting
{
"message": "Missing Authentication Token"
}
I've configured a CloudFront origin with API Gateway. It's stage with the Origin Domain Name being the API Gateway URL, and the Origin Path being the stage (default).
Under behaviours my pattern is /email*, with HTTP to HTTPS and allowed HTTP methods is GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE.
I've also whitelisted Authorization under Whitelist Headers but I am not doing any Authorization in my application as of now.
I have also enabled CORS in API Gateway.
I'm trying to build a serverless app with AWS. My API is working fine, but my custom domain is not. I'm receiving a 403 forbidden answer. This is how it's configured my custom domain:
And then I'm using the Target URL provided by this Custom Domain in Route 53 as CNAME. How can I fix this?
The CNAME should point to the CloudFront endpoint (*.cloudfront.net) rather than the API Gateway endpoint (*.execute-api.[region].amazonaws.com).
The CloudFront endpoint can be found by going to API Gateway -> Custom Domain Names. A CloudFront domain should be listed under "Target Domain Name".