@From Zero to Hero — Run parse-server on google cloud platform part 3— Automatically obtain lets encrypt certificate for google container engine deployment

This blog is part 3 of a series of From Zero to Hero blogs on how to run parse-server on GCP container engine

In part 2 you learned how to deploy and run your parse-server Node.js backend and MongoDB on Google Container Engine.

In this part you will learn how to automatically obtain a secure certificate for your parse-server instance via lets encrypt api and connect a custom domain (or sub-domain) to your parse-server API endpoint.

Perquisites

Security

The most important thing that you need to make sure before running your service in production is that it will be secured. I will not cover all the security aspect in this series but it’s important to know that parse-server provide you a very good and stable security mechanism like: authentication (via oAuth), ACL (access control lists), API and Master keys, User sessions and more. One of the things that you need to take care on your own is to add the SSL/TLS layer on top of your HTTP layer. In other words you need to run your API in https mode only!

In part 2 you deployed your parse-server instance to google container engine and then executed some test requests in front of it. If you noticed the URL that you used there was: http://<host_ip_address>:<port>/parse/<Class_Name> this is was good enough for dev/test purposed but it’s definitely not recommended in production. The aim of this part is to show you how you can run the same requests but this time with https instead of http and with domain name instead of host_ip_address. So instead of http://<host_ip_address>:<port>/parse/<Class_Name> you will use https://myCustomDomain/parse/<class_name> as your API endpoint.

Lets Encrypt and SSL/TLS Certificates (Theoretical)

SSL/TLS

SSL stands for Secure Socket Layer, TLS stands for Transport Layer Security the aim of this protocol is to provide encrypted link between your server and your apps. SSL/TLS is industry standard and use by most of the website/apps in order to protect their customers. If you want to learn more about SSL/TLS i suggest you to google it or maybe to watch youtube videos which explain it but the most important thing that you need to know is that when you run any service in production please make sure that it is running with SSL.

Lets Encrypt

Lets encrypt is a great service which provides you free SSL/TLS certificates for your website or app. The most beautiful and powerful feature of lets encrypt is the ability to automatically obtain an SSL certificate for your service via lets encrypt API’s. The reason that this automation process is so important is due to the certificate lifetime. Each certificate that is obtained via lets encrypt is valid for 3 months, so instead of running a manual renewal process few days before the expiration date, you can automate it and write some scheduler that will obtain a new certificate for your services and that’s where kube-lego comes into the picture.

In addition, let’s encrypt saves you money (about 150–250$ per year in case you already purchased one from one of the providers) and time (because you can automate the process). This is really amazing that this service comes for FREE.

kube-lego and Custom Domains (Theoretical)

kube-lego

kube-lego is an open source project which allows you to automatically obtain SSL/TLS certificate for your Kubernetes resources.

How does it work (taken for kube-lego github page):

kube-lego github page

Sounds complicated right? don’t panic… think about it like a service which runs every X period of time and automatically obtain the certificate for you. You will not even need to change the default configurations.

Custom Domain

Custom domain is mandatory in order to use kube-lego and lets encrypt. The reason is that when you generate an SSL certificate you must provide the domain on which you want to generate the certificate for (e.g. api.myDomain.com).


kube-lego (Practical)

Deploy kube-lego to container engine

The first thing that you need to do is to create a namespace for you kube-lego resources. Creating a new namespace is very simply and can be done by executing the following command:

kubectl create namespace kube-lego

In order to check that your namespace has been created please navigate to your Kubernetes instance by opening the browser and navigate to http://localhost:8001/ui, on the left side menu click on Namespaces and check that kube-lego namespace is listed there.

Next, go to visual studio code, double click on parse-server-service.yml file and change the type value from LoadBalancer to NodePort or simply copy and replace the content of this file with this one:

the reason for this change use is because the load balancer will be handled by Kubernetes Ingress resource which is a collection of rules that allow inbound connections to reach your container engine cluster services. In your case your ingress yml file will define 2 rules: one for SSL and another one for the load balancer.

Next, go to visual studio code, right click on container-engine folder and create a kube-lego-configmap.yml file. This config file will be parsed by the kube-lego service in runtime.

Copy and paste the content from the following gist into this file:

Change <YOUR_EMAIL_ADDRESS> to a valid email address that you have access to. The lego.url key is pointing to lets encrypt staging api. If you running your service in production you need to modify this URL and use lets encrypt production API. The URL of the production API is: https://acme-v01.api.letsencrypt.org/directory

After adding your email address in lego.email you are ready to deploy this file to Kubernetes. In order to deploy this file please execute the following command in your terminal:

kubectl apply -f container-engine/kube-lego-configmap.yml

Next, go to visual studio code, right click on the container-engine folder and create a kube-lego-deployment.yml file. Copy and paste the following into this file:

This file will create the kube-lego daemon service in your Kubernetes cluster. The kube-lego daemon is the service which responsible to automate all the process for you. As soon as the kube-lego daemon is running it will:

  • Create a user account (via your email address) with Lets Encrypt
  • Auto create a service resource in Kubernetes (the service name is: kube-lego-gce)
  • Look for Kubernetes Ingress resource that have the following annotation:
metadata:
annotations:
kubernetes.io/tls-acme: "true"

every ingress resource that has this annotation will be monitored and handled by kube-lego daemon.

Deploy parse-server ingress to container engine

Go to visual studio code, right click on container-engine folder and create a parse-server-ingress.yml file. Copy and paste the following code into this file:

This file will create the Ingress resource in your cluster. It will create LoadBalancer, secret that will host the key for your lets encrypt certificate and other relevant resources that will allows you to run your parse-server with SSL. The only part that is watched by kube-lego daemon is the spec.tls list there you need to define your API endpoint URL and use your custom domain.

Change <YOUR_CUSTOM_DOMAIN> to your own custom domain. I suggest you to create a sub domain (e.g. api.myCustomDomain.com) because in kube-lego you can generate multiple certificate for various services with the same daemon, the only thing that you need is to add it to your ingress hosts and then point then to the relevant services.

The line kubernetes.io/ingress.class: “gce” which located under the annotations section indicates that our ingress will use GCE load balancer to load balance the traffic for the services in your cluster. This line is relevant only when you running your cluster on google container engine. Instead of using GCE load balancer you can change this line to nginx, deploy an inginx service to your cluster and use it instead for load balancing between services in your cluster. Since we use GCP in this series i decided to go with GCE load balancer and not handle and maintain one on my own. If you insist to maintain your own nginx controller from various reasons (e.g. you don’t want to pay for the GCE load balancer resource) you can read how it can be done in kube-lego github page.

Execute the following command in terminal in order to deploy your ingress resource to your cluster:

kubectl create -f container-engine/parse-server-ingress.yml

The next thing that you need to do is to connect your load balancer IP address with you custom domain. Your load balancer IP address will be available in about 1–2 minutes after deploying the ingress resource. In order to know which IP address allocated for you do the following:

  • Open your browser and go to your cluster admin UI at: http://localhost:8001/ui
  • On the left menu click on Ingress
  • The IP address should be located under the Endpoints column

Troubleshooting: if from some reason you don’t see the IP address after 1–5 minutes go to your GCP console → Networking → Load balancing and check if the load balancer has been created.

Now, that you have the IP address it’s time to connect it to your own custom domain. Like i mentioned earlier, kube-lego require a domain to obtain certificate for so the next thing that you will do is to connect your own custom domain to your ingress load balancer URL.

Custom Domain (Practical)

Connect your custom domain

Go through the following steps in order to connect your custom domain to your load balancer IP address:

  • Login to your domain provider (in my case its godaddy.com)
  • Go to your domain manager
  • Select your domain from the list
  • Go to DNS manager
  • Create a new sub domain and connect it to your load balancer IP address by creating a new A record. The host name should be api (which is your sub domain name) and it should points to your load balancer IP address
  • Click on Save and make sure that your new sub domain is listed

The only thing that left you to do now it to wait (about 5–10 mins) and let the magic happen. During this time kube-lego daemon will run, creaea a new lets encrypt account if needed, access lets encrypt api’s and obtain a new certificate and finally attach this certificate to your parse-server service via Kubernetes secret resource.

Test your API (Practical)

Go through the following steps in order to check that your API works with SSL/TLS

  • Open your browser
  • Navigate to https://api.<YOUR_CUSTOM_DOMAIN>/parse
  • Make sure that your certificate is valid and your API is secure via the browser secure flag
  • Finally, open POSTMAN and execute a GET request to get all the tasks that have been created in part 2 of the series but this time use the https with your custom domain endpoint and make sure you get the same results

Part 3 — Summary

Now that your API is SSL secured it’s time to know how it can be consumed in a “real” app. In the next part (part 4) i will show you how you can create an iOS app that will consume your parse-server API’s. Moreover, i will explain how you can leverage parse-server advanced security mechanism (authentication, authorization and more) and create a well secured app for your clients.