For maintaining certs in F5 loadbalancers
2.3K
This project uses the Kubernetes cert-manager to maintain management certificates on F5 devices. There is a plan to traffic management certificates in the future but do not hold your breath. :)
A BatchJob is scheduled in Kubernetes with a service account which is allowed to read:
The BatchJob looks for Certificate objects with the following labels:
| Name | Value | Description |
|---|---|---|
| f5-cert-type | "management" | To support other certificates in the future |
| f5-auth-ref | string | The name of the secret that contains the credentials to the F5 device that uses this certificate |
| f5-device-fqdn | string | The FQDN to the device that uses this certificate |
When a certificate with the correct labels has been found the script gets the F5 credentials and the cert + key from the Certificate secret and updates it on the F5 device.
The following guide will guide you on how to get this started in your Kubernetes cluster. It does assume you have a bit of experience with Kubernetes and Kubectl, but not much.
Chart/ in this repository.helm template f5-certs -f Values.yaml . to see the outcome of the installation.helm install f5-certs -f Values.yaml . to install.Now you have a BatchJob which will run at 8am every morning unless you changed the default setting.
apiVersion: v1
kind: Secret
metadata:
name: f5-credentials
namespace: f5-certs # Important: Change this to the namespace name of your choice
type: Opaque
data:
F5_USERNAME: YWRtaW4= # Both the username and the credentials has to be Base64 encoded
F5_PASSWORD: aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1kUXc0dzlXZ1hjUQ==
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: bigip02-xip-se
namespace: f5-certs
labels:
f5-cert-type: "management"
f5-auth-ref: "f5-credentials" # Reference to the secret holding the credentials (same namespace)
f5-device-fqdn: "bigip01.xip.se" # The FQDN to the F5 device that will be updated
spec:
secretName: f5-cert
issuerRef:
name: letsencrypt-issuer
kind: ClusterIssuer # Depending on your setup this might be "Issuer".
dnsNames:
- "bigip01.xip.se"
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: bigip02-xip-se
namespace: f5-certs
labels:
f5-cert-type: "management"
f5-auth-ref: "f5-credentials" # Reference to the secret holding the credentials (same namespace)
f5-device-fqdn: "bigip02.domain.com" # The FQDN to the F5 device that will be updated
spec:
secretName: f5-cert
issuerRef:
name: letsencrypt-issuer
kind: ClusterIssuer
dnsNames:
- "bigip02.xip.se"
Note how there are two certs above with two different domains, but the same credentials. You can choose to create new credentials or create new ones if necessary.
To test the BatchJob you can fire one off manually like this:
kubectl create job -n f5-certs --from=cronjob/cert-updater cert-updater-01
kubectl logs -n f5-certs job/cert-updater-01
2022-08-10 18:42:20,901 - main - INFO - Restarting httpd
2022-08-10 18:42:25,905 - main - INFO - Waiting for management interface to restart
Certificate has been updated and the httpd interface is responding
Creating yet another job shows that the certificate does not need to be updated.
kubectl create job -n f5-certs --from=cronjob/cert-updater cert-updater-02
kubectl logs -n f5-certs job/cert-updater-02
2022-08-10 18:47:21,844 - main - INFO - Local certificates matches the remote certificates, no need to update on bigip.domain.com
Oh, I'd love some contributions to the project. Just two small requests:
Running the Python code within the cluster and outside differs a bit. Within the cluster the script has access to the auth token and cluster url via the service account (files are mounted into the container) but when running and debugging we want to run the code on our client.
Thus we need to replace these mounted files with environment variables. More on that below.
kubectl create ns f5-certs
Follow [the steps below](#Configure F5 Credentials and Certificate) to add the F5 Credentials and Certificate.
Either use export or set the following environment variables in your IDE:
| Name | Mandatory | DEFAULT | Description |
|---|---|---|---|
| ENVIRONMENT | Yes | Needs to be set to DEV if developing locally | |
| KUBE_TOKEN | Yes | Bearer token to the Kubernetes cluster | |
| CLUSTER_API_URL | Yes | Address to the Kubernetes kluster api (just before /api/...) | |
| NAMESPACE | Yes | Where the certificates and the batch job resides | |
| LOG_LEVEL | No | INFO | Can be either INFO or DEBUG, defaults to INFO |
Once these things are in place, just run main.py to test the script.
Once the code works you your client you might want to test it in the docker container. Since we're not using Kubernetes for this particular step you need to define the same environment variables again.
Here's a useful docker-compose example:
# This file is to test the container during development
# Don't use this in prod
version: "3.9"
services:
app:
build: .
environment:
ENVIRONMENT: DEV
CLUSTER_API_URL: https://rancher.domain.com/k8s/clusters/c-abcde
KUBE_TOKEN: <token>
NAMESPACE: f5-certs
The following Pod can be used to troubleshoot the script in Kubernetes. Just apply the config below (replace with your own image if you have built one).
apiVersion: v1
kind: Pod
metadata:
name: debug-container
namespace: f5-certs
labels:
app: ubuntu
spec:
containers:
- image: bigipreport/f5-k8s-certs:latest
command:
- "sleep"
- "604800"
imagePullPolicy: Always
name: ubuntu
restartPolicy: Always
serviceAccountName: f5-certs-sa
Content type
Image
Digest
sha256:e341c5ead…
Size
24.9 MB
Last updated
almost 2 years ago
docker pull bigipreport/f5-k8s-certs