Custom DNS for AWS Private API Gateway
Tags: aws, typescript, devops, serverless
Published: 2022-11-26 07:42:09

## How to enable custom names for your internal APIs, with CDK example

[This post first appeared on Medium](https://medium.com/aws-in-plain-english/custom-dns-for-private-api-gateway-5940cb4889a8)

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 APIs 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 is 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. It adds a little cost to the scenario, but if you have users and applications out of your control accessing the API's it's probably essential. You can use host and path-based routing on the ALB to access many APIs, and even use the same ALB to access web apps on EC2/ECS/Fargate in smaller environments or test accounts.

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

### API Gateway

I'm not going into detail about how to create and configure APIs 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 adding a Custom Domain Name and mapping it to your internal APIs.

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


![Create a domain name for your internal API](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f634klastu8kqwoua6ox.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a1k3hq1t6vjksuc92qlz.png)

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

And that's it for the API configuration. You can still access the APIs using the unfriendly endpoint URLs, but accessing it directly using the custom name won't work yet.

### Application Load Balancer

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wzwbgmwj1c6gzzen3isb.png)

Next, we need a Target Group

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


![Get the API Endpoint addresses](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/otp9538zwz9adf1921ov.png)

Then create a new Target Group:


![New Target Group](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1of65w9alniay03l1wtt.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/euivs1em2ndsa10cnbd0.png)

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


![Add IP targets](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ygjx184a679xzxk3prap.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wtdrvqaxfjax6mk82l5w.png)

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


![Adding a New Rule](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2b0wbdqndrxw21hpb1c3.png)

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`

### CDK Example

In my environments, I'm deploying the ALB's and configuration using AWS CDK. I've [created a demo](https://github.com/markilott/aws-cdk-internal-private-api-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](https://github.com/markilott/aws-cdk-internal-private-api-demo) for more detail. You will need VPN/DX or a bastion/jumpbox to access the internal load balancer for testing.

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 work around it, which is pretty easy using CDK. If you are interested in the generic CloudFormation version let me know.

---

**About the Author**

*Mark is a 20+yr IT industry veteran, with technical expertise and entrepreneurial experience in a range of fields. For many years now his passion has been building on AWS, and he holds certifications including Solution Architect Professional and the Advanced Networking Specialty. He wants you to know that he is an infrastructure and architecture expert who writes code, not a professional software developer — just in case you spot something odd.*

*Mark has spent the last few years in the banking industry, were he is currently building and leading a team focused on using AWS serverless technologies to reduce costs and speed up the time to market for new services and products.*

You can also find Mark on:
GitHub - https://github.com/markilott
LinkedIn - https://www.linkedin.com/in/markilott/
Medium - https://markilott.medium.com/