add webhook ovh

This commit is contained in:
2026-01-21 22:55:38 +01:00
parent b125232ec0
commit 9affd7959c
16 changed files with 499 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
apiVersion: v2
name: cert-manager-webhook-ovh
description: Webhook OVH pour cert-manager (DNS-01 challenge)
type: application
version: 1.0.0

View File

@@ -0,0 +1,57 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: cert-manager-webhook-ovh
namespace: cert-manager-ops
labels:
app: cert-manager-webhook-ovh
app.kubernetes.io/name: cert-manager-webhook-ovh
app.kubernetes.io/instance: cert-manager-webhook-ovh
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: cert-manager-webhook-ovh
template:
metadata:
labels:
app: cert-manager-webhook-ovh
annotations:
{{- toYaml .Values.podAnnotations | nindent 8 }}
spec:
serviceAccountName: {{ .Values.serviceAccount.name }}
containers:
- name: webhook
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
args:
- --v=2
- --group-name={{ .Values.groupName }}
- --secure-port=10250
- --cert-dir=/tmp/cert-manager-webhook-ovh
ports:
- name: https
containerPort: 10250
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- name: certs
mountPath: /tmp/cert-manager-webhook-ovh
readOnly: false
volumes:
- name: certs
emptyDir: {}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@@ -0,0 +1,22 @@
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: cert-manager-webhook-ovh
labels:
app: cert-manager-webhook-ovh
webhooks:
- name: webhook.cert-manager.io
admissionReviewVersions: ["v1", "v1beta1"]
clientConfig:
service:
name: cert-manager-webhook-ovh
namespace: cert-manager-ops
path: "/mutate"
rules:
- apiGroups: ["acme.cert-manager.io"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["challenges"]
sideEffects: None
failurePolicy: Fail

View File

@@ -0,0 +1,28 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cert-manager-webhook-ovh
namespace: cert-manager-ops
labels:
app: cert-manager-webhook-ovh
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cert-manager-webhook-ovh
namespace: cert-manager-ops
labels:
app: cert-manager-webhook-ovh
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: cert-manager-webhook-ovh
subjects:
- kind: ServiceAccount
name: {{ .Values.serviceAccount.name }}
namespace: cert-manager-ops

View File

@@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: cert-manager-webhook-ovh
namespace: cert-manager-ops
labels:
app: cert-manager-webhook-ovh
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: https
protocol: TCP
name: https
selector:
app: cert-manager-webhook-ovh

View File

@@ -0,0 +1,8 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.serviceAccount.name }}
namespace: cert-manager-ops
labels:
app: cert-manager-webhook-ovh

View File

@@ -0,0 +1,22 @@
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: cert-manager-webhook-ovh
labels:
app: cert-manager-webhook-ovh
webhooks:
- name: webhook.cert-manager.io
admissionReviewVersions: ["v1", "v1beta1"]
clientConfig:
service:
name: cert-manager-webhook-ovh
namespace: cert-manager-ops
path: "/validate"
rules:
- apiGroups: ["acme.cert-manager.io"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["challenges"]
sideEffects: None
failurePolicy: Fail

View File

@@ -0,0 +1,39 @@
# Configuration pour cert-manager-webhook-ovh
# Ce webhook permet à cert-manager d'utiliser OVH DNS-01 challenge pour les certificats wildcard
image:
repository: harbor.gkdomaine.local/images/cert-manager-webhook-ovh
tag: "v0.6.1"
pullPolicy: IfNotPresent
replicaCount: 1
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 50m
memory: 64Mi
# Configuration du webhook
groupName: acme.gkdomaine.fr
# RBAC
serviceAccount:
create: true
name: cert-manager-webhook-ovh
# Service
service:
type: ClusterIP
port: 443
# Pod annotations
podAnnotations: {}
# Node selector, tolerations, etc.
nodeSelector: {}
tolerations: []
affinity: {}

View File

@@ -0,0 +1,138 @@
# Gestion des Certificats Let's Encrypt pour le cluster OPS
Ce chart gère les certificats TLS générés par cert-manager dans le cluster OPS via Let's Encrypt.
## Stratégie de certificats
- **Sites publics** (accessibles depuis Internet) → **Certificats individuels** avec `letsencrypt-prod` (HTTP-01)
- Exemples : `homarr.dev.gkdomaine.fr`, `longhorn.dev.gkdomaine.fr`
- Validation via HTTP-01 challenge (nécessite accès HTTP public)
- **Sites internes** (accessibles uniquement en interne) → **Certificats wildcard** avec `letsencrypt-dns01-prod` (DNS-01)
- Exemples : `*.dev.gkdomaine.fr`, `*.rct.gkdomaine.fr`, `*.prd.gkdomaine.fr`
- Validation via DNS-01 challenge (nécessite le webhook OVH)
- Un seul certificat wildcard couvre tous les sous-domaines d'un environnement
## Structure
- `Chart.yaml` : Définition du chart Helm
- `templates/` : Dossiers organisés par application
- `homarr/` : Certificats pour l'application Homarr (sites publics)
- `longhorn/` : Certificats pour Longhorn (sites publics)
- `headlamp/` : Certificats pour Headlamp (sites internes)
- `wildcard/` : Certificats wildcard pour les environnements (dev, rct, prd)
## ClusterIssuers
### letsencrypt-prod (HTTP-01)
- Utilisé pour les certificats individuels des sites publics
- Challenge HTTP-01 via Traefik
- Pas besoin de configuration DNS supplémentaire
### letsencrypt-dns01-prod (DNS-01)
- Utilisé pour les certificats wildcard des sites internes
- Challenge DNS-01 via webhook OVH
- Nécessite le secret `ovh-credentials` avec les credentials OVH API
## Ajout d'un nouveau certificat
### Pour un site public (certificat individuel)
```yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: <app>-<env>-tls
namespace: certificates-ops
spec:
secretName: <app>-<env>-tls
issuerRef:
name: letsencrypt-prod # HTTP-01 pour sites publics
kind: ClusterIssuer
dnsNames:
- <app>.<env>.gkdomaine.fr
```
### Pour un site interne (utiliser le wildcard)
**Option 1 : Utiliser le certificat wildcard existant (recommandé)**
Pas besoin de créer un Certificate ! Utilisez directement le secret wildcard dans votre Ingress :
```yaml
# Dans votre values.yaml ou Ingress
ingress:
tls:
- secretName: wildcard-dev-tls # Utilise le wildcard
hosts:
- headlamp.dev.gkdomaine.fr
```
**Option 2 : Créer un certificat individuel avec DNS-01**
Si vous avez besoin d'un certificat spécifique (par exemple pour un domaine différent) :
```yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: <app>-<env>-tls
namespace: certificates-ops
spec:
secretName: <app>-<env>-tls
issuerRef:
name: letsencrypt-dns01-prod # DNS-01 pour sites internes
kind: ClusterIssuer
dnsNames:
- <app>.<env>.gkdomaine.fr
```
## Déploiement
Les certificats sont déployés automatiquement via l'ApplicationSet `certificates-apps` dans ArgoCD.
## Prérequis
### Pour les certificats wildcard (DNS-01)
1. **Webhook OVH installé** : Le webhook `cert-manager-webhook-ovh` doit être installé
2. **Secret OVH credentials** : Le secret `ovh-credentials` doit exister dans le namespace `certificates-ops`
- Voir `templates/secret-ovh-credentials.yaml` pour le template
- Créez le secret avec vos vraies credentials OVH API
### Pour les certificats individuels (HTTP-01)
- Aucun prérequis supplémentaire
- Le cluster OPS doit avoir accès Internet
- Les domaines doivent être accessibles publiquement via HTTP
## Vérification
```bash
# Vérifier les certificats
kubectl get certificates -n certificates-ops --context=cluster-ops
# Vérifier un certificat spécifique
kubectl describe certificate wildcard-dev-tls -n certificates-ops --context=cluster-ops
# Vérifier les secrets TLS créés
kubectl get secrets -n certificates-ops --context=cluster-ops | grep tls
# Vérifier les ClusterIssuers
kubectl get clusterissuers --context=cluster-ops
```
## Synchronisation vers les autres clusters
Les secrets TLS générés dans OPS doivent être synchronisés vers les clusters DEV/RCT/PRD où les applications sont déployées.
Utilisez le script `scripts/sync-all-certificates.sh` pour synchroniser automatiquement tous les secrets TLS.
## Notes importantes
- Les certificats sont créés dans le cluster OPS où cert-manager est installé
- Le namespace du Certificate doit être `certificates-ops`
- Pour utiliser le certificat dans d'autres clusters (DEV, RCT, PRD), le secret TLS doit être synchronisé depuis OPS
- Les certificats wildcard couvrent tous les sous-domaines d'un environnement (ex: `*.dev.gkdomaine.fr`)
- Les certificats individuels sont spécifiques à un domaine (ex: `homarr.dev.gkdomaine.fr`)

View File

@@ -0,0 +1,36 @@
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns01-prod
spec:
acme:
# Serveur Let's Encrypt production
server: https://acme-v02.api.letsencrypt.org/directory
# Email pour les notifications Let's Encrypt
email: gkpoubelle78@gmail.com
# Secret pour stocker la clé privée de l'account ACME
privateKeySecretRef:
name: letsencrypt-dns01-prod
# Challenge DNS-01 pour les certificats wildcard (sites internes)
solvers:
- dns01:
webhook:
groupName: acme.gkdomaine.fr
solverName: ovh
config:
# Les credentials OVH sont dans le secret ovh-credentials
# Voir helm/certificates/ops/templates/secret-ovh-credentials.yaml
applicationKey: "1d1a85ccc3a5bcc9"
applicationSecretRef:
name: ovh-credentials
key: application-secret
consumerKeyRef:
name: ovh-credentials
key: consumer-key
# Ce solver s'applique uniquement aux domaines internes
selector:
dnsZones:
- "dev.gkdomaine.fr"
- "rct.gkdomaine.fr"
- "prd.gkdomaine.fr"

View File

@@ -0,0 +1,13 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: headlamp-dev-tls
namespace: certificates-ops
spec:
secretName: headlamp-dev-tls
issuerRef:
name: letsencrypt-dns01-prod # Utilise le wildcard pour site interne
kind: ClusterIssuer
dnsNames:
- headlamp.dev.gkdomaine.fr # Site interne accessible via .fr

View File

@@ -0,0 +1,27 @@
# Secret pour les credentials OVH (DNS-01 challenge)
# IMPORTANT: Remplacez les valeurs base64 par vos vraies credentials OVH
#
# Pour créer le Secret manuellement avec vos vraies valeurs :
# kubectl create secret generic ovh-credentials \
# --from-literal=application-secret=VOTRE_APPLICATION_SECRET \
# --from-literal=consumer-key=VOTRE_CONSUMER_KEY \
# -n certificates-ops \
# --context=cluster-ops
#
# OU utilisez ce template en remplaçant les valeurs base64 ci-dessous :
# echo -n 'VOTRE_APPLICATION_SECRET' | base64
# echo -n 'VOTRE_CONSUMER_KEY' | base64
apiVersion: v1
kind: Secret
metadata:
name: ovh-credentials
namespace: certificates-ops
type: Opaque
data:
# Encodez vos credentials en base64 :
# echo -n 'VOTRE_APPLICATION_SECRET' | base64
# echo -n 'VOTRE_CONSUMER_KEY' | base64
application-secret: N2RiNWM3ZTdmNWE5MTM2Y2I5YmE4YmRmNjRjYTNmYTI=
consumer-key: M2VjOWM5ZTdmNjgzZWI0NDkyY2IwYjhhZTg1NWU0YWM=

View File

@@ -0,0 +1,14 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-dev-tls
namespace: certificates-ops
spec:
secretName: wildcard-dev-tls
issuerRef:
name: letsencrypt-dns01-prod
kind: ClusterIssuer
dnsNames:
- "*.dev.gkdomaine.fr"
- "dev.gkdomaine.fr"

View File

@@ -0,0 +1,14 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-prd-tls
namespace: certificates-ops
spec:
secretName: wildcard-prd-tls
issuerRef:
name: letsencrypt-dns01-prod
kind: ClusterIssuer
dnsNames:
- "*.prd.gkdomaine.fr"
- "prd.gkdomaine.fr"

View File

@@ -0,0 +1,14 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-rct-tls
namespace: certificates-ops
spec:
secretName: wildcard-rct-tls
issuerRef:
name: letsencrypt-dns01-prod
kind: ClusterIssuer
dnsNames:
- "*.rct.gkdomaine.fr"
- "rct.gkdomaine.fr"