I've got a prototype RESTful service I'd like to promote to something a bit more durable for minimal cost, which breaks down to the following steps:
- Define on-demand compute resource
- Enable HTTP requests to urls like example.com/*
- Restrict access
- Custom domain
I'm using Cloud9, which provisions an EC2 instance. I've been running services on different ports of this instance, but this is tedious and relatively unrealistic. I'd like these services to be available for arbitrary requests, but I don't need to them running all the time. AWS' Lambda seems appropriate.
Creating a new function via the Lambda console is straightforward. Well-done, AWS 👍
Routing HTTP requests to a Lambda function requires the API Gateway abstraction.
Routing requests with wildcard paths requires the API Gateway's Lambda Proxy configuration.
The end result is accessible via HTTP at a URL like: https://jmf9mr2fge.execute-api.us-west-1.amazonaws.com/prod/a/b/c.
Since I'm paying by usage, and the only customer, I only want this function invoked by my requests. API Key security seems appropriate at this stage.
Setting up API Key security on a proxy endpoint is accomplished by drilling into the "Method Request" configuration of the "Method Execution" overview.
Custom domains are configured through the API Gateway. The commands below use fn.example.com as an example domain.
API Gateway requires domains use HTTPS. ("To set up a custom domain name as your API's host name, you…must provide an SSL/TLS certificate for the custom domain name." - docs).
Install Go on Amazon Linux (Cloud9's EC2):
sudo yum install golang
go get -u github.com/google/acme
~/go/bin/acme reg -gen -accept email@example.com
Generate cert (2048 bit, per blog post mentioned above, although it seems more options are now supported):
openssl genrsa -out cert.key 2048
Generate domain ownership token:
~/go/bin/acme cert -k cert.key -dns=true fn.example.com
Follow acme's instructions to create a TXT record. Google's Public DNS tool makes to easy to assert record propagation.
Once cert creation is complete, import it into AWS' Certificate Manager service. (Note at the time of this writing, only N. Virginia was supported, so import there and then reference them in whatever region we're using for API Gateway.)
Acme generates a single cert file, but it contains two certs. Copy the first into ACM's "Certificate body" field and the second into the "Certificate chain". Copy the key into the "Certificate private key" field.
Associate the cert with the API and stage (so we don't have to pass it in the path) in the API Gateway custom domain configuration. The output of this process is a cloudfront "Target Domain Name", eg d1eputjh2acqt4.cloudfront.net.
Create a record (CNAME for subdomains, A for apex domains) in your domain registrar mapping the custom domain to the cloudfront domain name.
At long last, we should be able to load https://fn.example.com/a/b/c in a browser.