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.

Related Article