DEV Community

Cover image for Custom DNS for AWS Private API Gateway
Mark Ilott
Mark Ilott

Posted on • Originally published at Medium

Custom DNS for AWS Private API Gateway

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

This post first appeared on Medium

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

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

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

CDK Example

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

Top comments (0)