Getting Let's Encrypt Certificate for a Google App Engine Hosted Website

Let's Encrypt is a completely free Certificate Authority (CA) who distributed free and trusted TLS server certificates for website owners around the world to use. The process of using their certificate on a Google App Engine (GAE) hosted site, however, was a little tricky and thus I will record the steps I have done in order to achieve this.

Obtain an ACME Client

First things first, Let's Encrypt does not have any web form for obtaining a certificate. In order to do so, you have to use so called an Automated Certificate Management Environment (ACME) client to talk with Let's Encrypt's server, which implements the ACME server side protocol. After you have proven the ownership of your domain, the server will automatically signs your private key and the whole process takes less than 5 min to complete.

In order to download the official ACME client made by the Let's Encrypt project, go to their GitHub and follow the instructions on there.

Once you have a working ACME client, next thing you will need to do is to run the ACME client in "Certificate Only" and "Manual Authentication Mode. " The reason for this being that Let's Encrypt was created as a "fool proof" one-liner solution that will ideally obtain and install a TLS certificate on your website automatically in a typical setup. Unfortunately, as GAE user, we do not have direct control over the server hosting our website and thus we would have to do those process by ourself.

Obtain the Certificate

Let's run the ACME client in the mode we have mentioned above:

[datong@localhost letsencrypt]$ ./letsencrypt-auto certonly --manual

Give few seconds for any output to come back since this command will do some auto-update work before invoking the actual ACME client program. If you are prompted to enter a sudo password, this is perfectly normal since Let's Encrypt's ACME client stores the generated private key in a location only accessible by root by default in order to protect it.

If you are running this in a Terminal window and everything goes smoothly, you will see an old school ncurses style text based GUI. The first thing it will ask you is the domain name(s) you would like to sign for in your requested certificate. If you provide multiple ones, the resulted certificate will be containing an extra "Subject Alternative Names (SAN)" field which allows it to work with multiple domain names. Since today we are only encrypting one website, I will just put one domain name www.cyfly.org inside the box.

After that, you will be presented to agree their terms and verify your ownership of the domain. Different from most of the public CAs out there, which uses Email Validation, Let's Encrypt used the HTTP File Validation method. In order to prove your ownership of the website, Let's Encrypt will instruct you to do something like the following:

Make sure your web server displays the following content at
http://www.cyfly.org/.well-known/acme-challenge/vjiHqi5E9FfiNjOe2yajth-eVzxS1oHfMCBwj6HVQoE before continuing:

vjiHqi5E9FfiNjOe2yajth-eVzxS1oHfMCBwj6HVQoE.2GhklWKkNkag5BcFx95RAhNTluIbbubTNSXlUR_dsNY

Configure GAE to Serve Our Token File

In order to let GAE serve this file over the specified URL by Let's Encrypt, we need to find a convenient location under your application directory that will be used to store the actual file. I created a sub-directory called well-known under static for this purpose.

Please note that you do not have to and can not create a directory starting with .. Doing so will make appcfg.py ignore this directory during the scanning peocess and the directory will never be uploaded to Google's Server! This is why I created a directory called well-known, omitting the leading dot.

To map the URL /.well-known to the directory we newly created, we simply add a new static file handler in our app.yaml file:

- url: /.well-known
  static_dir: application/static/well-known
  mime_type: text/plain
  secure: always

Remember to change the static_dir section to match your actual setup. Also mime_type and secure are not technically required but it allows you to check the content of the file using your browser easily and thus was added.

Next, we need to create the acme-challenge/vjiHqi5E9FfiNjOe2yajth-eVzxS1oHfMCBwj6HVQoE file under well-known as requested by the ACME client. Use whatever editor of your choice but remember this file contains only one line of content and do not put a newline character after the first line. The content of the file will be:

vjiHqi5E9FfiNjOe2yajth-eVzxS1oHfMCBwj6HVQoE.2GhklWKkNkag5BcFx95RAhNTluIbbubTNSXlUR_dsNY

as required by the client.

After that, update your GAE application and make sure http://www.cyfly.org/.well-known/acme-challenge/vjiHqi5E9FfiNjOe2yajth-eVzxS1oHfMCBwj6HVQoE is indeed accessible and contains the correct file format. After that let the ACME client to continue and if you did everything correctly, you will get a new certificate within couple of seconds.

Installing the Certificate

By default, the ACME client stores the certificate along with it's private key under /etc/letsencrypt/live/<your domain name>/. Navigate to that directory as root, fullchain.pem file contains the certificate along with any required intermediates for your certificate and should almost always be used. privkey.pem is your private key.

When uploading your certificate to Google, the certificate file will simply be fullchain.pem. For the private key, however, you will have to run a simple command to get rid of the extra OID indicating the type of key first before Google would accept it. Currently Google only accepts RSA private key for custom TLS and Let's Encrypt only signs certificates using RSA public key so should work out pretty well.

To convert:

[root@localhost www.cyfly.org]# openssl rsa -in privkey.pem -check

Simply copy the content from -----BEGIN RSA PRIVATE KEY----- to -----END RSA PRIVATE KEY----- and paste it into the Google form and it should work right away.

After that, enable your new certificate and make sure it works by checking your website using ssllabs.com. You can keep or remove the authentication file safely on your website since it is only used once by Let's Encrypt and does not contain any useful information regarding your website.