Automatic renewal of Oracle Cloud Load Balancer SSL Certs with Certbot & Let's Encrypt

Automatic renewal of Oracle Cloud Load Balancer SSL Certs with Certbot & Let's Encrypt

I recently had trouble finding a solution to issue public SSL certs for an OCI Load Balancer with automatic renewal. I was hoping the OCI native Certificates resource would be the answer, but these are untrusted self-signed certs only.

So naturally, I turned to Certbot to see if it could provide an answer, and as it so happens the deploy-hook function combined with Oracle’s oci-cli tool makes for a straightforward and effective solution.


Prerequisites

Install Packages:

  • python3
  • python3-venv
  • libaugeas0

Create Python VENV:

/usr/bin/python3 -m venv /opt/certbot/
/opt/certbot/bin/pip install --upgrade pip

Install Certbot:

/opt/certbot/bin/pip install certbot

Install OCI-CLI:

According to Oracles Documentation at the time of writing, though best to follow the most recent official installation guide.

bash -c "$(curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh)"

The installation script will walk you through the creation of your configuration file. You will then want to add your API Keys to your selected User in the OCI console:

Identity > Users > User Details > API Keys

Create OCI Load Balancer and Listener:

If you’re following this guide, I will assume you already have a Load Balancer resource in OCI. You should create a HTTPS Listener with a Backend Set before proceeding.


The Scripts:

This below command will issue an LE cert for example.com with the SAN www.example.com using the DNS method, which requires being able to create a TXT record under the authoritative zone for example.com.

Complete and save this script as renew-certs.sh:

#!/bin/bash

certbot certonly \
-d example.com,www.example.com \
--cert-name example.com \
--manual \
--preferred-challenges dns \
--force-renew \
--deploy-hook ./deploy-hook.sh

By using this method, we will not be required to respond to HTTP challenge requests on the local Certbot host, which can become complex when sitting behind a Load Balancer.

(If the DNS method is not an option for you, this guide does a good job at walking through the steps involved in creating the neccessary Listener, Backend Set and Path Route Set)

Certbot will then call a deploy-hook script, which is executed only on successful renewal of certs. The deploy-hook is passed the environment variables $RENEWED_DOMAINS (the certificate CN) and $RENEWED_LINEAGE (the path to the directory containing all cert keys)

Complete and save this script as deploy-hook.sh:

#!/bin/bash

oci lb certificate create \
--config-file ./config \
--load-balancer-id <ocid> \
--wait-for-state SUCCEEDED \
--certificate-name "$RENEWED_DOMAINS-"`date +"%Y-%m-%d"` \
--ca-certificate-file "$RENEWED_LINEAGE/fullchain.pem" \
--private-key-file "$RENEWED_LINEAGE/privkey.pem" \
--public-certificate-file "$RENEWED_LINEAGE/cert.pem"

oci lb listener update --force \
--config-file ./config \
--load-balancer-id <ocid> \
--wait-for-state SUCCEEDED \
--listener-name "HTTPS" \
--default-backend-set-name <backend_set> \
--port 443 --protocol HTTPS \
--ssl-certificate-name "$RENEWED_DOMAINS-"`date +"%Y-%m-%d"` \
--hostname-names \[\"$RENEWED_DOMAINS\"\] 

The two steps in this script are:

  1. Upload the newly generated cert to the Load Balancer resource

  2. Apply the newly generated cert to the Load Balancer Listener


Done! Running renew-certs.sh will take care of cert renewal, as well as pushing the new certs out to your OCI Load Balancer. This script can be executed by a cronjob every 30 days, or at whatever frequency you wish to renew.

Hope this helped, feel free to send any questions my way if you have run into trouble.