How to Use AWS Certificate Manager with API Gateway

Updated: As of Mar 9, 2017, now you can!

If you’re reading this, you’re probably trying to figure out how to set up a custom domain name with AWS API Gateway. If you log into the AWS Console, you get some fancy HTML text input fields asking you for the:

  • Domain name
  • Certificate name
  • Certificate body
  • Certificate private key
  • Certificate chain

(╯°□°)╯︵ ┻━┻

Why does this form exist when AWS already has a tool called Certificate Manager? AWS Certificate Manager allows you to provision SSL/TLS certificates for free, but those certificates only work with Elastic Load Balancers (ELBs) and CloudFront distributions.

Note: Certificate Manager support for API Gateway is on the AWS Roadmap, but until then, keep flipping tables.

The Problem

Certificate Manager is the simplest way to get SSL/TLS certificates, but it’s so easy to use that I’ve become reliant on it for all my CA needs. I started looking for ways to export certificates from Certificate Manager, but unfortunately, that’s not an option. The AWS documentation actually lists a bunch of third-party certificate authorities, but most of them charge for a certificate.

I could put an ELB or a CloudFront distribution in front of it, but the reason that I’m using API Gateway in the first place is because I’m using AWS Lambda to build a “serverless” application. It kind of defeats the purpose of deploying stateless microservices on AWS Lambda if you end up running nginx or a load balancer in front of it.

The Solution

Use Lets Encrypt!

I’ve used Certbot with nginx on Linux, but since AWS Lambda is “serverless”, I can’t SSH into a server to install anything. Fortunately, there are a number of third-party ACME clients. I chose to use the google/acme client.

The google/acme project’s README was sufficient to get everything set up, but I’ll walk through the steps.

Install the ACME client

If you have Go installed, you can run go get -u github.com/google/acme to install it.

Otherwise, download the latest release for your operating system.

Create an account with LetsEncrypt

mkdir -p ~/.config/acme
openssl genrsa -out ~/.config/acme/account.key 4096
acme reg mailto:your@email.com

mailto:your@email.com is the ACME contact argument, which is necessary in case the CA needs to notify you.

Agree to the ACME CA Terms of Service

Check the status of your account with acme whoami and run acme update -accept to accept.

Generate your private key using OpenSSL

openssl genrsa -out your.custom.domain.key 2048

The output will look something like this:

Generating RSA private key, 2048 bit long modulus
..............................................+++
...+++

This will create a 2048 bit private key inside a file called your.custom.domain.key

Request the certificate

acme cert -k your.custom.domain.key -dns=true your.custom.domain

Note: change your.custom.domain to your domain name.

The DNS flag will use a DNS TXT record to prove that you own the domain (instead of using the .well-known method). You should see output that looks like this:

Add a TXT record for _acme-challenge.your.custom.domain with the value "PlcpEqnjIzhMlDsUKHFhUZx" and press enter after it has propagated.

Don’t press enter.

Update your DNS records

Login to Route53 or other DNS provider and add the requested DNS record. Once it has propagated, press enter.

You should see something like cert url: https://acme-v01.api.letsencrypt.org/, but that doesn’t matter because there will be a file called your.custom.domain.crt in your current working directory.

Add the Custom Domain into API Gateway

Let’s go back to 1995 and fill in the Custom Domain Names form.

  • Domain name: enter your your.custom.domain
  • Certificate name: name this something easy to remember, like your custom domain name
  • Certificate body: copy/paste the first certificate from your.custom.domain.crt
  • Certificate private key: copy/paste from your.custom.domain.key
  • Certificate chain: copy/paste the second certificate from your.custom.domain.crt

Note: It’s fine to copy the parts that say -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----.

Click the Save button and you should see AWS create the CloudFront distribution for your custom domain.