From 40173db9adb6efd2c0ec3aeb835f6a798cc355be Mon Sep 17 00:00:00 2001 From: Wade Barnes Date: Wed, 28 Jan 2026 07:29:32 -0800 Subject: [PATCH 01/10] Add support for managed ingresses (tlsSecrets) - Initial pass at ingress query. Signed-off-by: Wade Barnes --- docker/entrypoint.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 8a927c1..d23a84a 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -160,6 +160,14 @@ EOF # Get a mapping of all managed routes and their hosts routeMap=$(oc get route -l certbot-managed=true -o=jsonpath='{range .items[*]}{.metadata.name}={.spec.host}{"\n"}{end}') + +# Get a mapping of tls secrets and their hosts from all managed ingresses. +# Example: +# oc -n 4a9599-dev get ingress -l certbot-managed=true -o=jsonpath='{range .items[*]}{range .spec.tls[*]}{.secretName}={.hosts}{"\n"}{end}' +# Result: +# mediator-credo-tls=["mediator-dev.digitaltrust.gov.bc.ca"] + + # Declare and populate a hash table to use as a dictionary for mapping the routes to their hosts. # - The host name will also be used as the certificate name in the case individual certificates are being requested. declare -A managedRoutes @@ -233,7 +241,7 @@ rm -f ${CERTBOT_WORK_DIR}/deployed # Get certificate(s), either combined or individual if [ "${CERTBOT_CERT_PER_HOST}" == "true" ]; then - echo "Manage individual certificates for each unique host." + echo "Manage individual certificates for each unique host." for certbot_host in $( Date: Wed, 22 Apr 2026 14:28:32 -0700 Subject: [PATCH 02/10] Add support for managed ingresses (tlsSecrets) - Initial pass at script updates to iterate over ingresses and patch their related secrets. Signed-off-by: Wade Barnes --- docker/entrypoint.sh | 79 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index d23a84a..ad5a923 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -166,6 +166,7 @@ routeMap=$(oc get route -l certbot-managed=true -o=jsonpath='{range .items[*]}{. # oc -n 4a9599-dev get ingress -l certbot-managed=true -o=jsonpath='{range .items[*]}{range .spec.tls[*]}{.secretName}={.hosts}{"\n"}{end}' # Result: # mediator-credo-tls=["mediator-dev.digitaltrust.gov.bc.ca"] +ingressTlsMap=$(oc get ingress -l certbot-managed=true -o=jsonpath='{range .items[*]}{range .spec.tls[*]}{.secretName}={range .hosts[*]}{.}{" "}{end}{"\n"}{end}{end}') # Declare and populate a hash table to use as a dictionary for mapping the routes to their hosts. @@ -182,10 +183,37 @@ for item in ${routeMap}; do fi done +# Declare and populate a hash table for mapping ingress TLS secrets to their hosts. +# - The TLS secret name will be used as the certificate name for ingress-managed certificates. +declare -A managedIngressSecrets +while IFS='=' read -r key value; do + if [ -z "${key}" ] || [ -z "${value}" ]; then + continue + fi + + # Normalize and de-duplicate hosts for a given secret. + ingressHosts=$(echo "${value}" | tr ' ' '\n' | sed '/^$/d' | sort -fu | paste -sd ',' -) + if [ -z "${ingressHosts}" ]; then + continue + fi + + if [ -n "${managedIngressSecrets[${key}]}" ]; then + mergedHosts=$(printf "%s\n%s\n" "${managedIngressSecrets[${key}]}" "${ingressHosts}" | tr ',' '\n' | sed '/^$/d' | sort -fu | paste -sd ',' -) + managedIngressSecrets[${key}]="${mergedHosts}" + else + managedIngressSecrets[${key}]="${ingressHosts}" + fi +done <<< "${ingressTlsMap}" + # Generate a list of sorted and unique managed domains (hosts), and a list of sorted and unique routes -echo "${managedRoutes[@]}" | tr " " "\n" | sort -fu > /tmp/certbot-hosts.txt +allHosts=$(printf "%s\n" "${managedRoutes[@]}" "${managedIngressSecrets[@]}" | tr ',' '\n' | sed '/^$/d' | sort -fu) +echo "${allHosts}" > /tmp/certbot-hosts.txt cat /tmp/certbot-hosts.txt | paste -sd "," - > /tmp/certbot-hosts.csv echo "${!managedRoutes[@]}" | tr " " "\n" | sort -fu > /tmp/certbot-routes.txt +echo "${!managedIngressSecrets[@]}" | tr " " "\n" | sort -fu > /tmp/certbot-ingress-secrets.txt + +# Track which certificate should be used for each ingress TLS secret. +declare -A ingressSecretCertificates echo 'CERTBOT_DEBUG =' ${CERTBOT_DEBUG} # Dump contents of files to help troubleshoot in case of problems @@ -200,6 +228,11 @@ if [ "${CERTBOT_DEBUG}" == "true" ]; then echo " ${route}: ${managedRoutes[${route}]}" done + echo '*********** resulting mapping of ingress tls secrets to hosts:' + for secret in "${!managedIngressSecrets[@]}"; do + echo " ${secret}: ${managedIngressSecrets[${secret}]}" + done + echo '*********** contents of /tmp/certbot-hosts.csv:' cat /tmp/certbot-hosts.csv @@ -209,6 +242,9 @@ if [ "${CERTBOT_DEBUG}" == "true" ]; then echo '*********** contents of /tmp/certbot-routes.txt:' cat /tmp/certbot-routes.txt + echo '*********** contents of /tmp/certbot-ingress-secrets.txt:' + cat /tmp/certbot-ingress-secrets.txt + echo '*********** contents of /tmp/certbot-route.yaml:' cat /tmp/certbot-route.yaml @@ -245,6 +281,12 @@ if [ "${CERTBOT_CERT_PER_HOST}" == "true" ]; then for certbot_host in $( /dev/null 2>&1; then + oc patch "secret/${secret}" -p '{"type":"kubernetes.io/tls","stringData":{"tls.crt":"'"${TLS_CRT}"'","tls.key":"'"${TLS_KEY}"'"}}' + else + echo "secret/${secret} does not exist, creating it as type kubernetes.io/tls ..." + oc create secret tls "${secret}" --cert="${CERTBOT_CONFIG_DIR}/live/${certificateName}/fullchain.pem" --key="${CERTBOT_CONFIG_DIR}/live/${certificateName}/privkey.pem" + fi + fi +done + if [ "${CERTBOT_DEBUG}" == "true" ]; then echo '*********** final mapping of routes to hosts (certificate names):' @@ -287,6 +359,11 @@ if [ "${CERTBOT_DEBUG}" == "true" ]; then echo " ${route}: ${managedRoutes[${route}]}" done + echo '*********** final mapping of ingress tls secrets to certificate names:' + for secret in "${!ingressSecretCertificates[@]}"; do + echo " ${secret}: ${ingressSecretCertificates[${secret}]}" + done + echo "*********** list of all files/folder under ${CERTBOT_CONFIG_DIR}:" find ${CERTBOT_CONFIG_DIR} From f6e5b0fb6cf9531e673593c5ca2a0a1e8060ed26 Mon Sep 17 00:00:00 2001 From: Wade Barnes Date: Wed, 22 Apr 2026 14:38:52 -0700 Subject: [PATCH 03/10] Update the permissions for the certbot service account - Update permissions as required to support operations on ingresses and secrets. Signed-off-by: Wade Barnes --- charts/certbot/templates/role.yaml | 17 +++++++++++++++++ openshift/certbot.dc.yaml | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/charts/certbot/templates/role.yaml b/charts/certbot/templates/role.yaml index 3215765..002c15f 100644 --- a/charts/certbot/templates/role.yaml +++ b/charts/certbot/templates/role.yaml @@ -53,3 +53,20 @@ rules: - update - patch - delete + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - list + - get + - apiGroups: + - "" + resources: + - secrets + verbs: + - list + - get + - create + - update + - patch diff --git a/openshift/certbot.dc.yaml b/openshift/certbot.dc.yaml index 84ca040..84f1622 100644 --- a/openshift/certbot.dc.yaml +++ b/openshift/certbot.dc.yaml @@ -67,6 +67,23 @@ objects: - update - patch - delete + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - list + - get + - apiGroups: + - "" + resources: + - secrets + verbs: + - list + - get + - create + - update + - patch - apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding From d3f1accbb417ecf444dabfdf4329e4dee4e92671 Mon Sep 17 00:00:00 2001 From: Wade Barnes Date: Wed, 22 Apr 2026 15:01:18 -0700 Subject: [PATCH 04/10] Update packages - Base image - certbot - oc cli Signed-off-by: Wade Barnes --- docker/Dockerfile | 13 +++++-------- openshift/certbot.bc.yaml | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 141c13a..9cec4c4 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,5 +1,5 @@ # cat Dockerfile | oc new-build -D - --name=certbot -FROM docker.io/python:3.10-alpine +FROM docker.io/python:3.12-alpine ENV PYTHONUNBUFFERED=1 ARG APP_ROOT=/usr/local/bin WORKDIR ${APP_ROOT} @@ -9,12 +9,9 @@ RUN apk add --no-cache bash gcompat py3-setuptools \ && rm -rf /var/cache/apk/* # Install Certbot -# Downgrade to Acme 1.32.0 to support Certbot 1.26.0 -# ToDo: Upgrade to latest -RUN apk add --no-cache --virtual certbot-build gcc libc-dev libffi-dev \ - && pip install --no-cache-dir --upgrade pip wheel \ - && pip install --no-cache-dir 'certbot==1.26.0' \ - && pip install --no-cache-dir 'acme==1.32.0' \ +RUN apk add --no-cache --virtual certbot-build gcc libc-dev libffi-dev openssl-dev \ + && pip install --no-cache-dir --upgrade pip setuptools wheel \ + && pip install --no-cache-dir 'certbot>=3,<4' \ && certbot --version \ && certbot --help paths \ && apk del certbot-build \ @@ -22,7 +19,7 @@ RUN apk add --no-cache --virtual certbot-build gcc libc-dev libffi-dev \ # Install Openshift CLI RUN apk add --no-cache --virtual oc-build curl tar \ - && curl -sfL https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable-4.10/openshift-client-linux.tar.gz | tar -zxvf - -C ${APP_ROOT} \ + && curl -sfL https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable-4.18/openshift-client-linux.tar.gz | tar -zxvf - -C ${APP_ROOT} \ && apk del oc-build \ && rm -rf /var/cache/apk/* diff --git a/openshift/certbot.bc.yaml b/openshift/certbot.bc.yaml index 9a83c5e..7a92d86 100644 --- a/openshift/certbot.bc.yaml +++ b/openshift/certbot.bc.yaml @@ -41,7 +41,7 @@ objects: dockerStrategy: from: kind: DockerImage - name: docker.io/python:3.10-alpine + name: docker.io/python:3.12-alpine type: Docker triggers: - type: ConfigChange From b9b035d40200e911daf494a54f3ad87f82ceead1 Mon Sep 17 00:00:00 2001 From: Wade Barnes Date: Wed, 22 Apr 2026 15:01:40 -0700 Subject: [PATCH 05/10] Update documentation Signed-off-by: Wade Barnes --- README.md | 7 +++---- charts/certbot/README.md | 4 +++- docker/README.md | 34 ++++++++++++++++++++++------------ 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 45b14be..01c24e9 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,8 @@ # Certbot [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) [![Lifecycle:Dormant](https://img.shields.io/badge/Lifecycle-Dormant-ff7f2a)](https://github.com/bcgov/repomountie/blob/master/doc/lifecycle-badges.md) -Automatically update TLS Certificates on OpenShift Routes +Automatically update TLS certificates on OpenShift Routes and Ingresses -_Update (August 2023) - Entrust Certificate Services has discontinued ACMEv1 protocol. Current users of BCDevOps Certbot will be unable to renew their certificates at this time if they are using OCIO Identity Management Services' Entrust Certificate Services._ - -_Update (November 2023) - At this time, the underlying EFF Certbot project and Entrust Certificate Services both support the newer ACMEv2 protocol. However, BCDevOps Certbot currently only supports the older, deprecated, ACMEv1 protocol, and OCIO IMS has not enabled ACMEv2 protocol support at this time. Please consider contacting OCIO Identity Management Services to express your need for ACMEv2 and Certbot support._ +The container image now uses a current Python and Certbot runtime with ACME v2-compatible defaults. Support for a specific certificate authority still depends on that provider's ACME implementation and any approval process required by your organization. To learn more about the **Common Services** available visit the [Common Services Showcase](https://bcgov.github.io/common-service-showcase/) page. @@ -24,6 +22,7 @@ SECURITY.md - Security Policy and Reporting ## Documentation * [Docker Readme](docker/README.md) +* [Helm Chart Readme](charts/certbot/README.md) * [Security Reporting](SECURITY.md) ## Getting Help or Reporting an Issue diff --git a/charts/certbot/README.md b/charts/certbot/README.md index e2cd8e8..267b44e 100644 --- a/charts/certbot/README.md +++ b/charts/certbot/README.md @@ -66,7 +66,7 @@ You can use the `--set` or `--values` option to change the default configuration You can find an exhaustive list of the configurable settings in `values.yaml`. -## Helm-managed routes with Certbot +## Helm-managed routes and ingresses with Certbot If you are using Helm to deploy your application, you likely create the routes via helm as well. Certbot will inject the `tls` settings in your route after Helm creates it, so you need to ensure that Helm does not overwrite the changes that Certbot made next time it updates your route (unless you change the host and actually need to issue a new certificate). The example below uses Helm's `lookup` function to retrieve the certificates and key from the route before recreating the template. @@ -108,6 +108,8 @@ spec: wildcardPolicy: None ``` +For Kubernetes `Ingress` resources, Certbot updates the TLS `Secret` referenced by each managed `spec.tls[*].secretName` entry rather than modifying the `Ingress` object itself. If you manage those secrets with Helm, ensure your chart preserves the secret contents or excludes those TLS secrets from regular reconciliation so Helm does not overwrite certificates issued by Certbot. + ## Artifactory Usage If you want to use Artifactory's local caching to download the docker image, you can set `artifactoryProxy.enabled: true` and provide the name of your `ArtifactoryServiceAccount` with `artifactoryProxy.artifactoryServiceAccount`. The chart will then add your artifactory pull secret to the job's `imagePullSecrets`. diff --git a/docker/README.md b/docker/README.md index 01d559e..c1f2f6a 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,10 +1,8 @@ # Certbot [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) [![Lifecycle:Stable](https://img.shields.io/badge/Lifecycle-Stable-97ca00)](https://github.com/bcgov/repomountie/blob/master/doc/lifecycle-badges.md) -Automatically update TLS Certificates on OpenShift Routes +Automatically update TLS certificates on OpenShift Routes and Ingresses -_Update (August 2023) - Entrust Certificate Services has discontinued ACMEv1 protocol. Current users of BCDevOps Certbot will be unable to renew their certificates at this time if they are using OCIO Identity Management Services' Entrust Certificate Services._ - -_Update (November 2023) - At this time, the underlying EFF Certbot project and Entrust Certificate Services both support the newer ACMEv2 protocol. However, BCDevOps Certbot currently only supports the older, deprecated, ACMEv1 protocol, and OCIO IMS has not enabled ACMEv2 protocol support at this time. Please consider contacting OCIO Identity Management Services to express your need for ACMEv2 and Certbot support._ +This container now uses a current Python and Certbot runtime with ACME v2-compatible defaults. Compatibility with a specific certificate authority still depends on that provider's ACME implementation and any approval process required by your organization. To learn more about the **Common Services** available visit the [Common Services Showcase](https://bcgov.github.io/common-service-showcase/) page. @@ -29,15 +27,25 @@ To learn more about the **Common Services** available visit the [Common Services - Can utilize or other ACME compliant Certificate Authority for issuing certificates - Leverages and extends for managing (create/renew) certificates - Should only be executed on Openshift Container Platform +- Uses a Python 3.12-based container image and a current Certbot release - Creates an OpenShift `CronJob` which will run on a regular schedule for renewing TLS certificates - The `CronJob` will manage all `Route` objects annotated with the label `certbot-managed=true` - - You have the option of a single certificate being issued/renewed for all the managed hosts/domains, or of an individual certificate being issued/renewed for each managed host/domain. -- If a cert is created/renewed, patch the new certificate to the managed OpenShift routes + - The `CronJob` will manage all `Ingress` objects annotated with the label `certbot-managed=true` by updating the TLS `Secret` resources referenced from `.spec.tls` + - You have the option of a single certificate being issued/renewed for all managed hosts/domains, or of individual certificates being issued/renewed per managed host or ingress TLS secret, depending on configuration. +- If a cert is created/renewed, patch the new certificate to the managed OpenShift routes and ingress TLS secrets ## Environment Variables The Certbot container image supports an array of environment variables to configure how it will behave. Certbot behavior can be modified by modifying which variables are defined. The following variables change the way how the internal Certbot application will behave. +Managed ingress behavior: + +- Add the label `certbot-managed=true` to any `Ingress` that should be included. +- Each `Ingress.spec.tls[*].secretName` is treated as a managed TLS target. +- When `CERTBOT_CERT_PER_HOST=false`, one combined certificate is used for routes and ingress TLS secrets. +- When `CERTBOT_CERT_PER_HOST=true`, routes receive one certificate per host and each ingress TLS secret receives one certificate covering the hosts listed in that TLS entry. +- If a referenced ingress TLS secret does not already exist, Certbot creates it as a `kubernetes.io/tls` secret. + | Environment Variable | Default Value | Notes | | --- | --- | --- | | `CERTBOT_CONFIG_DIR` | `/etc/letsencrypt` | Certbot Config Directory (Should be backed by a persistent volume) | @@ -65,10 +73,11 @@ The following provides you a quick way to get Certbot set up and running as an O oc project $NAMESPACE ``` -1. Ensure that the Routes you want Certbot to manage have been annotated with the label `certbot-managed=true`. You can list routes that meet this criteria with the following: +1. Ensure that the Routes and Ingresses you want Certbot to manage have been annotated with the label `certbot-managed=true`. You can list managed resources with the following: ```sh oc get route -n $NAMESPACE -l certbot-managed=true -o=jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' + oc get ingress -n $NAMESPACE -l certbot-managed=true -o=jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' ``` 1. Install Certbot to your project/namespace by processing `certbot.dc.yaml` to create the CronJob and supporting objects (ServiceAccount, RoleBinding, PVC, etc). @@ -95,7 +104,8 @@ The following provides you a quick way to get Certbot set up and running as an O - For non-prod environments, you may set `CERTBOT_STAGING=true`, so you don't hit any service limits with LetsEncrypt. - By default, this template will use LetsEncrypt for certificate generation. If you are just testing, you may use Let's Encrypt testing endpoint `https://acme-staging-v02.api.letsencrypt.org/directory` to avoid being rate limited. - For your production applications, we strongly recommend **NOT** using LetsEncrypt certificates. Contact your ministry/department to determine best practices for production SSL/TLS certificate management. - - If you are using a certificate provider that gives you extra domains on top of what you have requested (like Entrust), you should make sure that the `CERTBOT_SUBSET` option is set to true. Otherwise certificate renewals will always fail because their extra domain will never be managed on our end and choke. If you require stringent domain validation, set `CERTBOT_SUBSET` to false explicitly. + - If you are using a certificate provider that gives you extra domains on top of what you have requested, make sure that the `CERTBOT_SUBSET` option is set to true. Otherwise certificate renewals can fail because the unmanaged extra domains will not pass validation. If you require stringent domain validation, set `CERTBOT_SUBSET` to false explicitly. + - The certbot service account must be able to read `Ingress` resources and get, create, update, and patch referenced TLS `Secret` resources. ```sh export CERTBOT_EMAIL= @@ -151,9 +161,9 @@ Where Entrust does support Certbot, there are a few extra steps required to requ 1. Make sure `CERTBOT_STAGING` is set to `false`. The Entrust server does not have a staging mode -1. If a Certbot job has previously on the same route using LetsEncrypt server, then you will need to delete the existing PVC. This will remove old Let's Encrypt files and a new PVC will be created on the next step. +1. If a Certbot job has previously managed the same route or ingress hosts using a different certificate authority, then you may need to delete the existing PVC. This removes prior Certbot account and certificate state so a clean issuance flow can start on the next run. -1. Apply the deployment config and run the job manually or by cron trigger. The job logs will display it has failed to obtain the certificates and the route will remain unmodified. This is normal because the certificate request still needs to be approved by your ministry first. +1. Apply the deployment config and run the job manually or by cron trigger. The job logs may show that the certificate request is pending and the route or ingress TLS secret will remain unmodified until the request is approved by your ministry. 1. In the `CERTBOT_EMAIL` inbox you should receive an email from `auto-notice@entrust.com` containing a `Tracking ID`. @@ -169,7 +179,7 @@ Where Entrust does support Certbot, there are a few extra steps required to requ ## Tips -1. If you are going to setup automatic cert renewals for the first time, backup "Certficate", "Private Key" and "CA Certificate" contents from your route. +1. If you are setting up automatic certificate renewals for the first time, back up the existing route TLS material or ingress TLS secret before the first run. 1. List your cron jobs @@ -201,7 +211,7 @@ Where Entrust does support Certbot, there are a few extra steps required to requ oc process -n $NAMESPACE -f "https://raw.githubusercontent.com/BCDevOps/certbot/master/openshift/certbot.dc.yaml" -p CERTBOT_EMAIL=$EMAIL -p CERTBOT_SERVER=$CERTBOT_SERVER -p CERTBOT_STAGING=false -p CERTBOT_DEBUG=true -p CERTBOT_DELETE_ACME_ROUTES=false | oc apply -n $NAMESPACE -f - ``` - _PS: Ensure that you manually delete the ACME Route and Service after you are done troubleshooting and redeploy without the DEBUG and DELETE_ACME_ROUTES options!_ + _PS: Ensure that you manually delete the temporary ACME Route, Service, and NetworkPolicy after you are done troubleshooting and redeploy without the DEBUG and DELETE_ACME_ROUTES options._ 1. If you end up running the setup process multiple times, ensure that you have deleted all the duplicate copies of those cron jobs and only keep the latest one. Or to delete all the certbot jobs and start fresh you can use the below. From 7488b03a2db5c6b0982d689a9f9361be85c2d014 Mon Sep 17 00:00:00 2001 From: Wade Barnes Date: Wed, 22 Apr 2026 15:19:17 -0700 Subject: [PATCH 06/10] Refactor the Dockerfile to make it easier to update packages Signed-off-by: Wade Barnes --- docker/Dockerfile | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 9cec4c4..261640a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,7 +1,12 @@ # cat Dockerfile | oc new-build -D - --name=certbot -FROM docker.io/python:3.12-alpine -ENV PYTHONUNBUFFERED=1 +ARG PYTHON_VERSION=3.12-alpine +FROM docker.io/python:${PYTHON_VERSION} + +ARG CERTBOT_VERSION=3 +ARG OCP_VERSION=stable-4.18 ARG APP_ROOT=/usr/local/bin + +ENV PYTHONUNBUFFERED=1 WORKDIR ${APP_ROOT} # Install Prerequisites @@ -9,17 +14,19 @@ RUN apk add --no-cache bash gcompat py3-setuptools \ && rm -rf /var/cache/apk/* # Install Certbot +# CERTBOT_VERSION: Major version constraint for Certbot (e.g., "3" for 3.x) RUN apk add --no-cache --virtual certbot-build gcc libc-dev libffi-dev openssl-dev \ && pip install --no-cache-dir --upgrade pip setuptools wheel \ - && pip install --no-cache-dir 'certbot>=3,<4' \ + && pip install --no-cache-dir "certbot>=${CERTBOT_VERSION},<$((CERTBOT_VERSION+1))" \ && certbot --version \ && certbot --help paths \ && apk del certbot-build \ && rm -rf /var/cache/apk/* # Install Openshift CLI +# OCP_VERSION: OpenShift client stream (e.g., "stable-4.18", "stable-4.19") RUN apk add --no-cache --virtual oc-build curl tar \ - && curl -sfL https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable-4.18/openshift-client-linux.tar.gz | tar -zxvf - -C ${APP_ROOT} \ + && curl -sfL "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/${OCP_VERSION}/openshift-client-linux.tar.gz" | tar -zxvf - -C ${APP_ROOT} \ && apk del oc-build \ && rm -rf /var/cache/apk/* From e57bd4a5fd1071e7bbf1ca3c5d8b56807fa91d2f Mon Sep 17 00:00:00 2001 From: Wade Barnes Date: Wed, 22 Apr 2026 15:24:51 -0700 Subject: [PATCH 07/10] Add dependabot configuration Signed-off-by: Wade Barnes --- .github/dependabot.yml | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8ec8950 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,46 @@ +version: 2 +updates: + # Monitor Dockerfile for base image updates + - package-ecosystem: "docker" + directory: "/docker" + schedule: + interval: "weekly" + day: "monday" + time: "02:00" + open-pull-requests-limit: 5 + labels: + - "dependencies" + - "docker" + commit-message: + prefix: "chore(docker):" + include: "scope" + + # Monitor GitHub Actions workflow files + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "02:00" + open-pull-requests-limit: 5 + labels: + - "dependencies" + - "github-actions" + commit-message: + prefix: "chore(actions):" + include: "scope" + + # Monitor Helm chart dependencies + - package-ecosystem: "helm" + directory: "/charts/certbot" + schedule: + interval: "weekly" + day: "monday" + time: "02:00" + open-pull-requests-limit: 5 + labels: + - "dependencies" + - "helm" + commit-message: + prefix: "chore(helm):" + include: "scope" From ccff2ccbbc45fe5ee4ed92aada27d62a39f1a3e9 Mon Sep 17 00:00:00 2001 From: Wade Barnes Date: Wed, 22 Apr 2026 15:33:30 -0700 Subject: [PATCH 08/10] Update workflows, add permissions Signed-off-by: Wade Barnes --- .github/workflows/charts-release.yaml | 4 ++++ .github/workflows/on-pr-opened.yaml | 4 ++++ .github/workflows/on-push.yaml | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/.github/workflows/charts-release.yaml b/.github/workflows/charts-release.yaml index 2db9003..8273f5a 100644 --- a/.github/workflows/charts-release.yaml +++ b/.github/workflows/charts-release.yaml @@ -1,5 +1,9 @@ name: Release Charts +permissions: + contents: write + pages: write + on: push: paths: diff --git a/.github/workflows/on-pr-opened.yaml b/.github/workflows/on-pr-opened.yaml index f558080..2636f86 100644 --- a/.github/workflows/on-pr-opened.yaml +++ b/.github/workflows/on-pr-opened.yaml @@ -1,5 +1,9 @@ name: Pull Request Opened +permissions: + contents: read + packages: write + env: APP_NAME: certbot diff --git a/.github/workflows/on-push.yaml b/.github/workflows/on-push.yaml index d5a02a6..e13fefb 100644 --- a/.github/workflows/on-push.yaml +++ b/.github/workflows/on-push.yaml @@ -1,5 +1,9 @@ name: Push +permissions: + contents: read + packages: write + env: APP_NAME: certbot From 09411cda0e9cd01a2dedf20986b45881450bd4f8 Mon Sep 17 00:00:00 2001 From: Wade Barnes Date: Thu, 23 Apr 2026 05:04:04 -0700 Subject: [PATCH 09/10] Update start and active deadlines Signed-off-by: Wade Barnes --- charts/certbot/templates/_helpers.tpl | 2 +- charts/certbot/templates/cronjob.yaml | 2 +- openshift/certbot.dc.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/charts/certbot/templates/_helpers.tpl b/charts/certbot/templates/_helpers.tpl index f450aee..2036002 100644 --- a/charts/certbot/templates/_helpers.tpl +++ b/charts/certbot/templates/_helpers.tpl @@ -82,7 +82,7 @@ When running helm template, or using --dry-run, lookup returns an empty object */}} {{- define "certbot.jobSpec" }} backoffLimit: 6 -activeDeadlineSeconds: 300 +activeDeadlineSeconds: 600 parallelism: 1 completions: 1 template: diff --git a/charts/certbot/templates/cronjob.yaml b/charts/certbot/templates/cronjob.yaml index 6ef39f2..7da305f 100644 --- a/charts/certbot/templates/cronjob.yaml +++ b/charts/certbot/templates/cronjob.yaml @@ -7,7 +7,7 @@ spec: concurrencyPolicy: Forbid failedJobsHistoryLimit: 3 successfulJobsHistoryLimit: 3 - startingDeadlineSeconds: 60 + startingDeadlineSeconds: 600 jobTemplate: metadata: labels: {{ include "certbot.labels" . | nindent 8 }} diff --git a/openshift/certbot.dc.yaml b/openshift/certbot.dc.yaml index 84f1622..a209bae 100644 --- a/openshift/certbot.dc.yaml +++ b/openshift/certbot.dc.yaml @@ -118,12 +118,12 @@ objects: concurrencyPolicy: Forbid failedJobsHistoryLimit: 3 successfulJobsHistoryLimit: 3 - startingDeadlineSeconds: 60 + startingDeadlineSeconds: 600 jobTemplate: metadata: spec: backoffLimit: 6 - activeDeadlineSeconds: 300 + activeDeadlineSeconds: 600 parallelism: 1 completions: 1 template: From 0e59c889fd6158654bbbcd2b9424355133a83518 Mon Sep 17 00:00:00 2001 From: Wade Barnes Date: Thu, 23 Apr 2026 05:15:38 -0700 Subject: [PATCH 10/10] Update resource requests Signed-off-by: Wade Barnes --- charts/certbot/templates/_helpers.tpl | 5 ++--- openshift/certbot.bc.yaml | 5 ++--- openshift/certbot.dc.yaml | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/charts/certbot/templates/_helpers.tpl b/charts/certbot/templates/_helpers.tpl index 2036002..673b7e4 100644 --- a/charts/certbot/templates/_helpers.tpl +++ b/charts/certbot/templates/_helpers.tpl @@ -126,9 +126,8 @@ template: value: {{ .Values.certbot.certPerHost | quote }} resources: requests: - cpu: 50m - limits: - cpu: 250m + cpu: 100m + memory: 256Mi volumeMounts: - mountPath: /etc/letsencrypt name: certbot-config diff --git a/openshift/certbot.bc.yaml b/openshift/certbot.bc.yaml index 7a92d86..0ba7e9d 100644 --- a/openshift/certbot.bc.yaml +++ b/openshift/certbot.bc.yaml @@ -28,9 +28,8 @@ objects: postCommit: {} resources: requests: - cpu: 1 - limits: - cpu: 1 + cpu: 100m + memory: 256Mi source: contextDir: docker git: diff --git a/openshift/certbot.dc.yaml b/openshift/certbot.dc.yaml index a209bae..8cb09ae 100644 --- a/openshift/certbot.dc.yaml +++ b/openshift/certbot.dc.yaml @@ -155,9 +155,8 @@ objects: value: "${CERTBOT_CERT_PER_HOST}" resources: requests: - cpu: 50m - limits: - cpu: 250m + cpu: 100m + memory: 256Mi volumeMounts: - mountPath: /etc/letsencrypt name: certbot-config