Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -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"
4 changes: 4 additions & 0 deletions .github/workflows/charts-release.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
name: Release Charts

permissions:
contents: write
pages: write

on:
push:
paths:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/on-pr-opened.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
name: Pull Request Opened

permissions:
contents: read
packages: write

env:
APP_NAME: certbot

Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/on-push.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
name: Push

permissions:
contents: read
packages: write

env:
APP_NAME: certbot

Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -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
Expand Down
4 changes: 3 additions & 1 deletion charts/certbot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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`.
Expand Down
7 changes: 3 additions & 4 deletions charts/certbot/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion charts/certbot/templates/cronjob.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ spec:
concurrencyPolicy: Forbid
failedJobsHistoryLimit: 3
successfulJobsHistoryLimit: 3
startingDeadlineSeconds: 60
startingDeadlineSeconds: 600
jobTemplate:
metadata:
labels: {{ include "certbot.labels" . | nindent 8 }}
Expand Down
17 changes: 17 additions & 0 deletions charts/certbot/templates/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
22 changes: 13 additions & 9 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
# cat Dockerfile | oc new-build -D - --name=certbot
FROM docker.io/python:3.10-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
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' \
# 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>=${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.10/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/*

Expand Down
34 changes: 22 additions & 12 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -29,15 +27,25 @@ To learn more about the **Common Services** available visit the [Common Services
- Can utilize <https://letsencrypt.org/> or other ACME compliant Certificate Authority for issuing certificates
- Leverages and extends <https://certbot.eff.org/> 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) |
Expand Down Expand Up @@ -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).
Expand All @@ -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=<some-valid@email.com>
Expand Down Expand Up @@ -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`.

Expand All @@ -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

Expand Down Expand Up @@ -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.

Expand Down
Loading