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}
.
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.
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.
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!
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/
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.