Sign in

Custom DNS for Private API Gateway

Enable custom names for your internal API’s, with CDK Example

AWS API Gateway Private is the ideal way to front our internal applications and services, but there’s one frustrating limitation — you cannot assign a custom domain name to a private API like you do with one that is public facing.

This leads to internal API’s with less than friendly names like:

https://abcdefsxthl.execute-api.ap-southeast-1.amazonaws.com/v1

Or if you need the name to resolve for remote users (VPN or on-prem over Direct Connect), then it would look like this:

https://abcdefsxthl-vpce-aaaaff0d0673c9999.execute-api.ap-southeast-1.amazonaws.com/v1

Either way, it’s a pain to remember! What’s worse if it’s redeployed for any reason the name will change — ok for services part of your CI/CD pipeline that know about the update, but not so good for users or applications out of the loop.

The solution for now is to put an Application Load Balancer (ALB) in front of the API and access it using the hostname of the ALB instead. Adds a little cost to the scenario, but in some cases it will be worth it. You can use host and path based routing on the ALB to access many API’s, and even use the same ALB to access web apps on EC2/ECS/Fargate in smaller environments or test accounts.

Accessing API’s via ALB

There’s a few tricks to it though, so here’s what you need to do (with a CDK example at the end)…

I’m not going into detail of how to create and configure API’s here, just how to access them using an internal ALB and custom domain name.

You will need a working API or two, and the internal API VPC Endpoints to access it.

The key trick with API Gateway itself is to add a Custom Domain Name and mapping it to your internal APIs.

This is not intuitive, because Custom domains can not be created with a Private endpoint type:

Create a domain name for your internal API

That’s ok — using the Regional endpoint type will work. You will also need a matching certificate from ACM.

Next, map the Custom domain to your internal API stages as you would an external API:

Add mappings for your internal API stages

Note the path(s) you use here will be needed later in the ALB Rules.

And that’s it. You can still access the APIs using the unfriendly endpoint URL’s, but accessing it directly using the custom name won’t work yet.

Next we create and configure a load balancer. Again I’m not going into all the detail here, just the parts relevant to the API and custom domain.

First, create the ALB and attach it to the same subnets as your API VPC Endpoints.

Add a Listener for HTTPS and attach your certificate. The default action should be a Fixed Response with a 400 or 500 error.

HTTPS Listener with default action and ACM certificate

Next we need a Target Group

First, get the IP Addresses of the API VPC Endpoint:

Get the API Endpoint addresses

Then create a new Target Group:

New Target Group

We need to configure the Health Check Settings. API Gateway will send a 403 response to health checks so we have to include that:

Health check settings

Add the IP Addresses of the VPC Endpoint and add to pending:

Add IP targets

Go back to the Load Balancer, and to Listeners. We need to edit the HTTPS Listener to add the new targets:

Listeners — note I have also added a HTTP Listener to redirect to HTTPS — optional but recommended

Edit the Listener and Add a New Rule with Path based routing:

Adding a New Rule

Note I have added the paths mapped above for both of my test API’s here — we can forward to multiple API’s using the same ALB and Rule. The leading slash is required.

Save the Rule and we are done.

You can now access the API’s using the hostname of the ALB, for example:

https://api-priv.mydomain.com/test-api1

will be forwarded to the API with a domain path mapping of api-priv.mydomain.com => test-api1

In my environments I’m deploying the ALB’s and configuration using AWS CDK. I’ve created a demo to show how to create an Application Load Balancer and internal private API Gateways with a custom domain name.

The demo is self-contained and will deploy into the AWS default VPC by default. Check out the Readme for more detail. All you will need to test is VPN access to your VPC — I’ll add another article on that soon.

Aside from the tricks above, the other issue automating this with CloudFormation and CDK is that there is no export for the IP addresses attached to the VPC Endpoints. I use a CloudFormation custom resource to workaround it, and it turns out that’s pretty easy using CDK. If you are interested in the generic CloudFormation version let me know.

Learning and sharing cloud and AWS technologies

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store