amazon-web-servicesnetwork-programmingaws-api-gatewayamazon-route53amazon-vpc

Public Route53 CNAME Record to Private API Gateway


Background

I have a Private API Gateway attached to a VPC Endpoint which I am NOT using private DNS for. Therefore the url of the form https://${aws_api_gateway_rest_api.this.id}-${aws_vpc_endpoint.this.id}.execute-api.${var.region}.amazonaws.com/${var.stage}/${var.path} is publicly resolvable per Invoke Private API via VPC Endpoint with Route 53 Alias. This is an endpoint used by other internal clients at my org who are coming from within our private, multi-cloud network.

I can successfully invoke this URL no problem from my private network with the following: curl -v -X POST https://${aws_api_gateway_rest_api.this.id}-${aws_vpc_endpoint.this.id}.execute-api.${var.region}.amazonaws.com/${var.stage}/${var.path}.

The Necessary Design

This URL will change whenever the api gateway id or vpc endpoint id changes. I need a static url I can provide to internal clients that will never change.

Attempted Solution

I create a route53 CNAME record named endpoint.sub.domain.com in a public hosted zone called sub.domain.com and pointed it at ${aws_api_gateway_rest_api.this.id}-${aws_vpc_endpoint.this.id}.execute-api.${var.region}.amazonaws.com to serve as a static "proxy" to always point to the underlying publicly resolvable DNS record for the Private API Gateway.

What happened

I went to curl this just like the previous one and received: curl -v -X POST https://endoint.sub.domain.com/<stage>/<path> but had TLS issues:

Server certificate:
*  subject: CN=*.execute-api.us-east-1.amazonaws.com
*  start date: Sep 19 00:00:00 2022 GMT
*  expire date: Sep 16 23:59:59 2023 GMT
*  subjectAltName does not match endpoint.sub.domain.com
* SSL: no alternative certificate subject name matches target host name 'endpoint.sub.domain.com'
* Closing connection 0
* TLSv1.2 (OUT), TLS alert, close notify (256):
curl: (60) SSL: no alternative certificate subject name matches target host name 'airport-mock-endpoint.npd.nortonalto.com'
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Tried the same with --insecure just to see:
curl --insecure -v -X POST https://endoint.sub.domain.com/<stage>/<path>
And received {"message”:”Forbidden”}.

Tried the same, this time specifying the api gateway id:
curl --insecure -v -X POST https://endoint.sub.domain.com/<stage>/<path> -H "x-apigw-api-id:5xxxxxxf"
And received:
{"message":"Missing Authentication Token"}

Tried the same, this time specifying the target of the CNAME record (the original url) as the Host:
curl --insecure -v -X POST https://endoint.sub.domain.com/<stage>/<path> -H "Host: {api-gateway-id}-{vpc-endpoint-id}.execute-api.us-east-2.amazonaws.com"
And received:
Success!

The Problem

Clients must be able to call this API without passing in the Host header AND with the same secure TLS that the original endpoint provides. How can this be accomplished?


Possible solutions

1. Have a server 302 redirect requests

2. Configure something involving Cloud Front?

3. Some Route 53 / API Gateway DNS configuration?

4. Enable private DNS in my VPC


Solution

  • November 2024 UPDATE

    This is now possible out of the box. See: https://aws.amazon.com/about-aws/whats-new/2024/11/amazon-api-gateway-custom-domain-name-private-rest-apis/

    Original answer

    Api gateway will serve your "static" domain certificate only via feature called "custom domains" which is not supported for private api gateways. See first blue note box in this aws documentation: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html

    The only available solution I'm aware of is described here in aws github https://github.com/aws-samples/serverless-samples/tree/main/apigw-private-custom-domain-name

    This solution works around this limitation by creating network load balancer in front of your private api gateway which can be configured to use your "static" domain certificate.