Let's Encrypt Google App Engine2 min read
Let’s Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit. Let’s Encrypt is a service provided by the Internet Security Research Group (ISRG)
This post won't go into details as to what Let's Encrypt is about. We should probably read the FAQ's if we want to learn more.
Until the Google App Engine Team fully automate the process of using Let's Encrypt on Google App Engine or even provide some sort of API to handle certs, we'll probably have to find ways of either automating the process just a little bit or stick to some other easier cert authority. You can track work on this in Issue 12535. There's a catch.
But come on who doesn't like free, open, "secure" stuff? I know I do.
So to get started, we'll follow the instructions here to install the Let's Encrypt Client
The Let's Encrypt Client is a fully-featured, extensible client for the Let's Encrypt CA (or any other CA that speaks the ACME protocol) that can automate the tasks of obtaining certificates and configuring webservers to use them.
Next is to obtain a certificate using the manual plugin like so:
$ sudo ./letsencrypt-auto -a manual certonly
We'll be prompted for a couple of things, like the domain names we're generating the cert(s) for, and getting our IP logged.
Last but not least, we'll be presented with a challenge, the most crucial part, where we'll be presented with something like this at the let's encrypt console:
Make sure our web server displays the following content at http://www.example.com/.well-known/acme-challenge/odebEMaSagM3xRblm_hmcPvnpCFdEsTBDrpaHyw6Q_I before continuing: odebEMaSagM3xRblm_hmcPvnpCFdEsTBDrpaHyw6Q_I.du6Wm_JOQBK08bH0MzKjuVzNbozezAthZBONRGcghDI ... ... Press ENTER to continue
This is fairly straightforward. We can choose to serve the challenge text and content from a special directory within our app and ensure they match correspondingly.
For example in our GAE project directory, we could do the following:
$ mkdir -p well-known/acme-challenge/ $ echo "odebEMaSagM3xRblm_hmcPvnpCFdEsTBDrpaHyw6Q_I.du6Wm_JOQBK08bH0MzKjuVzNbozezAthZBONRGcghDI" > well-known/acme-challenge/odebEMaSagM3xRblm_hmcPvnpCFdEsTBDrpaHyw6Q_I
And then the challenge can be handled in a number of ways, like for my flask GAE apps, I prefer to create a simple flask route to help with current and future challenges
from flask import Flask, send_from_directory app = Flask(__name__) @app.route('/.well-known/acme-challenge/<path:path>') def acme_challenge(path): return send_from_directory('well-known/acme-challenge', path, mimetype='text/plain')
This means the challenges will be stored in a directory structure similar to:
. ├── app.yaml ├── main.py └── well-known └── acme-challenge └── odebEMaSagM3xRblm_hmcPvnpCFdEsTBDrpaHyw6Q_I
If we happen to be using a different runtime, running a static site on GAE or we
just love using
yaml, we can as well handle this in our
handlers: - url: /.well-known/acme-challenge/(.*) mime_type: text/plain static_files: well-known/acme-challenge/\1 upload: well-known/acme-challenge/.*
Upload all changes to our live environment and test that we can reach the endpoint:
$ appcfg.py update .
Head back to our Let's Encrypt console, hit enter to verify the challenge and get the certs generated.
If successful, the certificates will then reside in
We'll then convert our
privkey.pem into an RSA private key for use in the
Google Cloud Developers Console:
$ opennssl rsa -in privkey.pem -out rsa.pem
fullchain.pem into the
Google Cloud Developers Console SSL Certificates Section:
$ xclip -sel clip < fullcain.pem
$ xclip -sel clip < rsa.pem
https and voilà!
Okay, not exactly done because if you took note from the very beginning I said that's there's a catch :D. You'll have to remember to repeat parts of this every 3 months to ensure you enjoy continue to enjoy this.
Let's star GAE Issue 12535. Maybe the more the interest, the faster this is worked on.