Back to Lab home

Add SSL Certificates to your static website without redeploying on App Engine

By Pascal Aubort — Feb 8, 2017 in How To
 

Update 1 - 22 Sep 2017

On September 15, 2017, Google announced the introduction of managed SSL Certificates on Google App Engine. Head to the post to get started.

A few months ago, Google announced their plan to make the web more secure. That means the next version of Chrome (56) will display more obviously whether a site is using a secure HTTPS connection in the address bar like below.

That also means it is now time to make your site and your visitors secure using HTTPS. When we started building our site, it was clear that we needed an “easy” way to make it secure and at the lowest cost possible. After looking at the many commercial options out there, we discovered Let’s Encrypt, an open and free Certificate Authority. Our site is hosted on Google App Engine (go runtime) and it turned out that Let’s Encrypt certificates are supported by GAE.

In this article I will describe how to make the certificate creation and renewal as easy as possible with a custom handler. There are plenty of articles out there, in particular this one which describes very well all the steps to create the SSL Certificates and add them to App Engine.

Because Lets’ Encrypt are only valid for 90 days, after which they have to be renewed, I decided that I would write a custom handler in Go to deal with the /.well-known/acme-challenge without having to deploy our site multiple times everytime the certificates have to be renewed.

In order to achieve this, I am using the App Engine Memcache to store the challenge temporarily and a custom Go handler to retrieve the values from the memcache.

Basically, when creating your certificate, for the naked domain and each sub-domain, you will be prompted a URL and a challenge, similar to this.

Make sure your web server displays the following content at
http://domain.com/.well-known/acme-challenge/k_F9xhVZjCmavFRePY0qRnPQTP2Wog_K6szbPWUS1sQ before continuing:

k_F9xhVZjCmavFRePY0qRnPQTP2Wog_K6szbPWUS1sQ.UfRTCl-YJkBwds1kza7iK2_IDQMjzIsYKmsPTMeqAgQ

The Go Handler

In your main.go file, add the following custom handler. This handler will get the part after /acme-challenge/, search for it in the memcache and return the corresponding challenge.

func LetsEncryptHandler(w http.ResponseWriter, r *http.Request) {

  ctx := appengine.NewContext(r)

  key := strings.Split(r.URL.Path, "/")[3]
	ctx.Infof("%s", key)

  w.Header().Set("Content-Type", "text/plain; charset=utf-8")

  if item, err := memcache.Get(ctx, key); err == memcache.ErrCacheMiss {
  	ctx.Infof("item not in the cache")
  } else if err != nil {
  	ctx.Errorf("error getting item: %v", err)
  } else {
  	ctx.Infof("the challenge is %q", item.Value)
  	challenge := string(item.Value)
  	w.Write([]byte(challenge))
  }
}

Now, in the main.go file, add the following line to the init() function.

func init() {
  
  ...
	http.HandleFunc("/.well-known/", LetsEncryptHandler)
  ...
}

Make sure to add the following handler in the app.yaml too:

- url: /.well-known/.*
  script: _go_app

- url: /.*
  script: _go_app
  secure: always

Getting the Challenge in Memcache

Once you have done that and deployed your app, you can start creating your certificate and adding the challenges and keys to App Engine’s Memcache.

First go to your App Engine Console, in the Memcache section. Then press the “New Key” button to get the the new key screen.

Now create a new key using Go String as the Key type and String as Key value. You can now copy the key and challenge from your terminal, similar to what is displayed in this example. The Key field being the part after the /acme-challenge/ in the URL.

Once you have done so, press the Create value button and you are set. In order to verify that this is working as intended, copy and paste the acme-challenge URL (http://domain.com/.well-known/acme-challenge/k_F9xhVZjCmavFRePY0qRnPQTP2Wog_K6szbPWUS1sQ) in your browser and verify that the challenge is being printed out.

You can now repeat the above steps for all your keys and challenges for all your subdomains and continute the certificate creation and verification.