[Ed note: in an amazing turn of events, this library was released mere hours before AWS basically made it obsolete.]
This is a CloudFormation custom resource for API Gateway custom domains. It runs Certbot on Lambda to create certificates, and automatically creates Route53 DNS records to respond to Let's Encrypt domain ownership challenges.
It's basically a prollyfill for the conspicuously missing AWS::ApiGateway::DomainName
resource type, which will likely land if/when AWS Certificate Manager supports API Gateway.
If you need to renew your certificates or would like to just use Route53 to create Let's Encrypt certificates, check out certbot-route53.sh.
- Fast: Certificates are installed and enabled in minutes
- Free: Certificates cost nothing (but you can donate)
- Easy: Certificates need only 14 lines in a CloudFormation template
- Safe: Certificates never touch your email or machine
Before you get started, you'll need to:
- create a Route53 public hosted zone for the domain, and
- point the domain at your zone's nameservers.
Since Let's Encrypt needs to be able to contact Route53, your DNS settings must be in effect already.
-
First, make sure you have a
AWS::Route53::HostedZone
in theResources
section of your template:MyHostedZone: Type: AWS::Route53::HostedZone Properties: Name: jedschmidt.com
-
Then, add an API Gateway Custom Domain stack to your template:
ApiGatewayCustomDomain: Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://s3.amazonaws.com/api-gateway-custom-domain/stack.template Parameters: LetsEncryptAccountEmail: me@jedschmidt.com LetsEncryptAgreeTOS: Yes LetsEncryptManualPublicIpLoggingOk: Yes
You'll need to specify three things:
LetsEncryptAccountEmail
: The email address associated with your Let's Encrypt accountLetsEncryptAgreeTOS
: That you agree to the Let's Encrypt Terms of Service. This must beYes
.LetsEncryptManualPublicIpLoggingOk
: That you're okay with Let's Encrypt logging the IP address of the Lambda used to runcertbot
. This must beYes
.
This stack has only one output:
ServiceToken
. This can be accessed using!GetAtt {your-logical-stack-name}.Outputs.ServiceToken
. -
Finally, add a custom domain to your template:
MyDomain: Type: Custom::ApiGatewayCustomDomain Properties: ServiceToken: !GetAtt ApiGatewayCustomDomain.Outputs.ServiceToken HostedZoneId: !Ref MyHostedZone Subdomain: www
You'll need to specify two things:
Service Token
: The Service token output by your API Gateway Custom Domain stackHostedZoneId
: A reference to the existingAWS::Route53::HostedZone
resource for which you're creating a certificate.
You can also optionally specify:
Subdomain
: The subdomain prefix for which you're creating a certificate, such aswww
. This is concatenated with theName
of the hosted zone, to create the full domain name. If this is omitted, the bare apex domain is used.
This resource returns the results of the createDomainName function.
At this point, you've done all you need to create/update/deploy your stack and get your certificate installed into API Gateway, but to user the domain you'll need to add an alias DNS record that resolves your domain to the CloudFront distribution created with your custom domain name, and then map the domain to a stage of your rest API:
MyDNSRecord:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneId: !Ref MyHostedZone
RecordSets:
- Type: A
Name: !GetAtt MyDomain.domainName
AliasTarget:
HostedZoneId: Z2FDTNDATAQYW2 # (hardcoded for all CloudFormation templates)
DNSName: !GetAtt MyDomain.distributionDomainName
MyPathMapping:
Type: AWS::ApiGateway::BasePathMapping
Properties:
DomainName: !GetAtt MyDomain.domainName
RestApiId: !Ref MyRestAPI
Stage: prod
See the included example for a simple website redirect app configured entirely with CloudFormation.
When a custom domain name is first created in your stack, CloudFormation calls a node.js function in a Lambda-backed custom resource, which in turn launches Certbot in a Python subprocess. Certbot then contacts Let's Encrypt to get a challenge string, which is placed in a TXT record on Route53. Once the record is live, Certbot tells Let's Encrypt to verify it, and once it's verified, Let's Encrypt sends the certificate back to Certbot and then to API Gateway, where it's used to create a custom domain.
- Let's Encrypt for taking the tedium and cost out of making web sites more secure.
- Michael Hart overall really, but in particular for the amazing docker-lambda, without which this project would not be possible.
- Eric Hammond, for his helpful explorations of CloudFormation and Lambda.