I have deployed my docker image for a web UI to GKE (Google Kontainer Engine), and this website is using tokens for authentication. When using JWT tokens for authentication, you should always encrypt your site using HTTPS. This has always been a trivial task, and while it is very easy to set up your SSL on GKE, it was not straight-forward since I didn’t find any instructions for this.
I have a pod in my cluster that is running my Angular UI. It is not terribly important that this Angular. The quick history:
- Created pod using a yaml deployment
- Created a NodePort (the type of service with internal IP and port 80 and 443 exposed)
- Created an Ingress (external IP that points to the internal IP)
- I own my own domain name which we will pretend is ‘mydomain.com‘, so I went to my domain registrar and created an ‘A’ record to point ‘admin.mydomain.com‘ to the public IP of my Ingress
After that everything was working well on port 80 and I was able to test the site a little bit using http://admin.mydomain.com. Now the issue is that I don’t want anyone else using this URL without having SSL on the site because I need to encrypt the JWT token for their protection.
Assumptions about your current status:
Let’s review some assumptions about the state of your GKE application before we go any futher. If haven’t got the following items in place, then you’ll need to do all that before you worry about SSL.
- You have an account a Google Cloud Platform
- You have created a cluster.
- You have created a NodePort service (internal ip with port 80 and 443 open)
- You have deployed your application as a pod (Workspace in GKE terminology)
- Your NodePort points to your pod (/deployment/workspace) (this terminology is confusing!)
- You created an Ingress (public IP) and it points to your NodePort
- You have setup an A record to point your domain to your Ingress IP.
- You can load your website using your domain name (ex: http://www.abc.com)
- If you are up to speed feel free to continue on…
Create a self-signed SSL (or skip to next part if you have an SSL cert):
I’m going to use a self-signed SSL certificate because this is still in testing mode and I don’t mind the warning pages. And because it is free.
*I’m on a Mac so may vary a bit for windows or other OS.
At a comand prompt:
//Get into my Temp folder cd Temp //Create a cert (it does need to be rsa 2048 in this case because GKE supports that). openssl req -newkey rsa:2048 -nodes -sha512 -x509 -days 3650 -nodes -out cert-admin-mydomain.pem -keyout private-admin-mydomain.pem
This is going to create a certificate that is valid for 10 years and put it in the current directory (which is Temp because we just navigated into Temp).
You will now get prompted for some information for the certificate after you enter that command.
** The one vital part is ‘Common Name’. It must match exactly the subdomain you are trying to use
Country Name (2 letter code) : US State or Province Name (full name) :NC Locality Name (eg, city) :PG Organization Name (eg, company) :Tarheel Solutions, LLC Organizational Unit Name (eg, section) :DEV Common Name (eg, fully qualified host name) :admin.mydomain.com Email Address :email@example.com
** Again make sure you set Common Name to match the subdomain you need to protect.
You will now see the 2 new files in your Temp folder:
Now login to your Google Cloud Platform console.
- Navigate to ‘Network Services / Load balancing’ in the side menu.
- There will be a list of load balancers (mine have terrible cryptic names, but I only have one that says (HTTP(S)) so I select that one. Select the one that matches your Ingress (it will say HTTP(S)).
- On the next page, you get all the details about your load balancer/ Ingress, and the table will have a row for HTTP, but nothing for HTTPS. (we’ll fix that now)
- Click ‘Edit’ at the top of the screen.
- On the ‘Edit Http(s) load balancer’ page, click ‘Frontend configuration’ to edit the ‘Frontend configuration’.
- Click the button for ‘Add Frontend IP and Port’
- You can leave ‘Name’ blank.
- Select ‘HTTPS’ for protocol.
- Leave IP Version as IPv4.
- Set IP address to the IP address you are using for HTTP (yes you want it to be the same IP you use for port 80).
- Set the port to 443.
- Click ‘Create a certificate’ (this option only shows after you choose port 443).
- Enter your certificate and private key values from the PEM files you generated. You can open them as text files to copy the text out of them and paste them here. Note the files were named with ‘cert’ and ‘private’ prefixes so you can easily get the right one in the correct location now.
- Submit your certificate text values and your SSL certificate is installed.
- Click the ‘Done’ button.
Assuming you have your NodePort setup to accept 443 traffic and your pod is accepting 443 traffic, your site should now work. It did take a minute or 2 and I ended up closing my browser and reopening it. You can expect warning and messages about the site not being safe from your browser. This is because it is self-signed, however since we know we just put SSL on it, we are ok with that. Obviously you would not use a self-signed cert on a production website because your visitors would not feel comfort with all these warnings.
It seems so simple now that it is done. I blew most of a Saturday doing this 20 different wrong ways before figuring out this was my solution. I hope save you some time on your website.