1

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"
],

enter image description here

Here's what is passed in browser enter image description here

UPDATE: Implementation attempt from comment enter image description here enter image description here 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==

2 Answers2

2

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

  1. 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.

  2. Associate this function to the viewer request event.

  3. 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.

  4. 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.

jellycsc
  • 10,904
  • 2
  • 15
  • 32
  • 1
    Thanks a lot for explanation really detailed I saw this extra functions but faced some issues configuring it now will try one time added like to your comment so thanks a lot again – Yuriy Gavriluk Jun 08 '22 at 19:37
  • @YuriyGavriluk Absolutely, let me know if you encounter any issues. – jellycsc Jun 08 '22 at 19:44
  • added bounty to you as I think in general you explaining what I need. I just enctounter this issue maybe something not related or I am doing something wrong when assigning function I start receiveing 502 and dont see any function invocations if I simply remove function from viewer requests things just start work so if you have any idea what is wrong I would really appreciate this – Yuriy Gavriluk Jun 10 '22 at 06:55
  • @YuriyGavriluk This is probably not related to the CloudFront Function. Does [this](https://stackoverflow.com/a/23599450/10692493) post help? – jellycsc Jun 10 '22 at 12:34
  • not really different error code I have 503 and 502 in the post, I have alternative dns name attached to CF as it would not work without function. so if only I add this function error appears. I will research. Anyway your help is really appreciated thanks – Yuriy Gavriluk Jun 10 '22 at 16:54
0

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: enter image description here

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.

Mattia Galati
  • 2,415
  • 16
  • 22
  • 1
    Thanks for a reply just to check you can get user entered dns in backend code ? what I try to accomblish is many alternative domain names assigned to one CF and in backend add logic something like this if (clientdns = 'firstdns.com') { } else { } and I will try your solution anyway – Yuriy Gavriluk Jun 07 '22 at 14:30
  • I don't see a specific procedure to register multiple domain names, but theorically speaking, there should be no limit in that sense. Also, AWS lets you reate a wildcard domain name (https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html) and if your purpose is serving a multi-tenant service, you could give it a try – Mattia Galati Jun 08 '22 at 06:19
  • Yes multitenant as the question is how to get user selected dns name in browser in the very backend code At the moment from what I can see on backend you still can get only name of gateway custom or aws provided – Yuriy Gavriluk Jun 08 '22 at 10:52