enable
This commit is contained in:
168
helm/cert-manager-webhook-ovh/ops/README.md
Normal file
168
helm/cert-manager-webhook-ovh/ops/README.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# cert-manager-webhook-ovh
|
||||
|
||||
Ce chart déploie le webhook OVH pour cert-manager, permettant l'utilisation du challenge DNS-01 avec OVH pour obtenir des certificats wildcard Let's Encrypt.
|
||||
|
||||
## Configuration des credentials OVH
|
||||
|
||||
Les credentials OVH peuvent être gérés de deux façons :
|
||||
|
||||
### Option 1 : Secret Kubernetes classique (par défaut)
|
||||
|
||||
Créez manuellement le Secret `cert-manager-webhook-ovh` dans les deux namespaces :
|
||||
|
||||
```bash
|
||||
# Dans cert-manager-webhook-ovh-ops
|
||||
kubectl create secret generic cert-manager-webhook-ovh \
|
||||
--from-literal=application-key="VOTRE_APPLICATION_KEY" \
|
||||
--from-literal=application-secret="VOTRE_APPLICATION_SECRET" \
|
||||
--from-literal=consumer-key="VOTRE_CONSUMER_KEY" \
|
||||
-n cert-manager-webhook-ovh-ops \
|
||||
--context=cluster-ops
|
||||
|
||||
# Dans cert-manager-ops
|
||||
kubectl create secret generic cert-manager-webhook-ovh \
|
||||
--from-literal=application-key="VOTRE_APPLICATION_KEY" \
|
||||
--from-literal=application-secret="VOTRE_APPLICATION_SECRET" \
|
||||
--from-literal=consumer-key="VOTRE_CONSUMER_KEY" \
|
||||
-n cert-manager-ops \
|
||||
--context=cluster-ops
|
||||
```
|
||||
|
||||
### Option 2 : External Secrets Operator - Stratégie Multi-Namespace (recommandé)
|
||||
|
||||
Utilisez External Secrets Operator pour synchroniser automatiquement les credentials depuis HashiCorp Vault dans **plusieurs namespaces** en utilisant un **ClusterSecretStore** partagé.
|
||||
|
||||
#### Avantages de la stratégie Multi-Namespace
|
||||
|
||||
- ✅ **Un seul ClusterSecretStore** : Configuration centralisée pour tous les namespaces
|
||||
- ✅ **Synchronisation automatique** : Les secrets sont créés automatiquement dans chaque namespace
|
||||
- ✅ **Rotation automatique** : Les secrets sont rafraîchis automatiquement selon `refreshInterval`
|
||||
- ✅ **Sécurité** : Les credentials ne sont jamais stockés en clair dans Git
|
||||
- ✅ **Partage facile** : Le même secret est disponible dans `cert-manager-ops` et `cert-manager-webhook-ovh-ops`
|
||||
|
||||
#### Prérequis
|
||||
|
||||
1. **External Secrets Operator installé** dans le cluster
|
||||
2. **HashiCorp Vault configuré** avec un rôle Kubernetes auth
|
||||
3. **ServiceAccount configuré** : Le ServiceAccount `cert-manager-webhook-ovh-sa` doit être autorisé dans Vault pour les namespaces `cert-manager-ops` et `cert-manager-webhook-ovh-ops`
|
||||
|
||||
#### Configuration dans Vault
|
||||
|
||||
Créez un rôle Vault pour l'authentification Kubernetes :
|
||||
|
||||
```bash
|
||||
# Configuration du rôle Vault
|
||||
vault write auth/kubernetes/role/cert-manager-webhook-ovh-role \
|
||||
bound_service_account_names=cert-manager-webhook-ovh-sa \
|
||||
bound_service_account_namespaces=cert-manager-webhook-ovh-ops,cert-manager-ops \
|
||||
policies=cert-manager-webhook-ovh-policy \
|
||||
ttl=1h
|
||||
|
||||
# IMPORTANT : Ne configurez PAS bound_service_account_namespace_selector
|
||||
# Utilisez bound_service_account_namespaces avec une liste de namespaces
|
||||
```
|
||||
|
||||
Créez une policy Vault pour accéder aux secrets OVH :
|
||||
|
||||
```bash
|
||||
vault policy write cert-manager-webhook-ovh-policy - <<EOF
|
||||
path "secret/data/ovh" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
Stockez les credentials OVH dans Vault :
|
||||
|
||||
```bash
|
||||
vault kv put secret/ovh \
|
||||
application-key="VOTRE_APPLICATION_KEY" \
|
||||
application-secret="VOTRE_APPLICATION_SECRET" \
|
||||
consumer-key="VOTRE_CONSUMER_KEY"
|
||||
```
|
||||
|
||||
#### Configuration dans values.yaml
|
||||
|
||||
Activez External Secrets dans `values.yaml` :
|
||||
|
||||
```yaml
|
||||
externalSecret:
|
||||
enabled: true
|
||||
refreshInterval: "1h"
|
||||
secretName: "cert-manager-webhook-ovh"
|
||||
remoteRef:
|
||||
applicationKey: "secret/data/ovh#application-key"
|
||||
applicationSecret: "secret/data/ovh#application-secret"
|
||||
consumerKey: "secret/data/ovh#consumer-key"
|
||||
vault:
|
||||
secretStoreName: "vault-backend"
|
||||
server: "https://vault.example.com:8200"
|
||||
path: "secret"
|
||||
version: "v2"
|
||||
auth:
|
||||
kubernetes:
|
||||
mountPath: "kubernetes"
|
||||
role: "cert-manager-webhook-ovh-role" # Nom du rôle Vault
|
||||
serviceAccountRef:
|
||||
name: "cert-manager-webhook-ovh-sa"
|
||||
namespace: "cert-manager-webhook-ovh-ops"
|
||||
```
|
||||
|
||||
#### Fonctionnement
|
||||
|
||||
1. **ClusterSecretStore** : Un seul `ClusterSecretStore` est créé pour Vault (accessible depuis tous les namespaces)
|
||||
2. **ExternalSecrets multiples** : Deux `ExternalSecret` sont créés :
|
||||
- Un dans `cert-manager-webhook-ovh-ops` (namespace du chart)
|
||||
- Un dans `cert-manager-ops` (namespace de cert-manager)
|
||||
3. **Secrets synchronisés** : Chaque `ExternalSecret` crée le Secret `cert-manager-webhook-ovh` dans son namespace respectif
|
||||
4. **Synchronisation automatique** : Les secrets sont rafraîchis automatiquement selon `refreshInterval`
|
||||
|
||||
#### Vérification
|
||||
|
||||
```bash
|
||||
# Vérifier le ClusterSecretStore
|
||||
kubectl get clustersecretstore vault-backend --context=cluster-ops
|
||||
|
||||
# Vérifier les ExternalSecrets
|
||||
kubectl get externalsecret -n cert-manager-webhook-ovh-ops --context=cluster-ops
|
||||
kubectl get externalsecret -n cert-manager-ops --context=cluster-ops
|
||||
|
||||
# Vérifier les Secrets créés
|
||||
kubectl get secret cert-manager-webhook-ovh -n cert-manager-webhook-ovh-ops --context=cluster-ops
|
||||
kubectl get secret cert-manager-webhook-ovh -n cert-manager-ops --context=cluster-ops
|
||||
|
||||
# Vérifier le statut de synchronisation
|
||||
kubectl describe externalsecret cert-manager-webhook-ovh -n cert-manager-webhook-ovh-ops --context=cluster-ops
|
||||
kubectl describe externalsecret cert-manager-webhook-ovh -n cert-manager-ops --context=cluster-ops
|
||||
```
|
||||
|
||||
## Dépannage
|
||||
|
||||
### Erreur "invalid bound_service_account_namespace_selector configured"
|
||||
|
||||
Cette erreur se produit lors de la création d'un rôle Vault. **Ne configurez PAS** `bound_service_account_namespace_selector`. Utilisez plutôt `bound_service_account_namespaces` :
|
||||
|
||||
```bash
|
||||
# ✅ Configuration CORRECTE
|
||||
vault write auth/kubernetes/role/cert-manager-webhook-ovh-role \
|
||||
bound_service_account_names=cert-manager-webhook-ovh-sa \
|
||||
bound_service_account_namespaces=cert-manager-webhook-ovh-ops,cert-manager-ops \
|
||||
policies=cert-manager-webhook-ovh-policy \
|
||||
ttl=1h
|
||||
```
|
||||
|
||||
### Le secret n'est pas créé dans un namespace
|
||||
|
||||
Vérifiez que :
|
||||
1. Le `ClusterSecretStore` existe et est valide
|
||||
2. L'`ExternalSecret` existe dans le namespace concerné
|
||||
3. Le ServiceAccount a les permissions nécessaires dans Vault
|
||||
4. Les credentials sont correctement stockés dans Vault
|
||||
|
||||
```bash
|
||||
# Vérifier les logs d'External Secrets Operator
|
||||
kubectl logs -n external-secrets-system -l app.kubernetes.io/name=external-secrets --context=cluster-ops --tail=50
|
||||
|
||||
# Vérifier les événements de l'ExternalSecret
|
||||
kubectl describe externalsecret cert-manager-webhook-ovh -n cert-manager-ops --context=cluster-ops
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
{{- if .Values.externalSecret.enabled }}
|
||||
apiVersion: external-secrets.io/v1beta1
|
||||
kind: ClusterSecretStore
|
||||
metadata:
|
||||
name: {{ .Values.externalSecret.vault.secretStoreName | default "vault-backend" }}
|
||||
labels:
|
||||
app.kubernetes.io/name: cert-manager-webhook-ovh
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
spec:
|
||||
provider:
|
||||
vault:
|
||||
server: {{ .Values.externalSecret.vault.server }}
|
||||
path: {{ .Values.externalSecret.vault.path | default "secret" }}
|
||||
version: {{ .Values.externalSecret.vault.version | default "v2" }}
|
||||
auth:
|
||||
{{- if .Values.externalSecret.vault.auth.kubernetes }}
|
||||
kubernetes:
|
||||
mountPath: {{ .Values.externalSecret.vault.auth.kubernetes.mountPath | default "kubernetes" }}
|
||||
role: {{ .Values.externalSecret.vault.auth.kubernetes.role }}
|
||||
{{- if .Values.externalSecret.vault.auth.kubernetes.serviceAccountRef }}
|
||||
serviceAccountRef:
|
||||
name: {{ .Values.externalSecret.vault.auth.kubernetes.serviceAccountRef.name }}
|
||||
{{- if .Values.externalSecret.vault.auth.kubernetes.serviceAccountRef.namespace }}
|
||||
namespace: {{ .Values.externalSecret.vault.auth.kubernetes.serviceAccountRef.namespace }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else if .Values.externalSecret.vault.auth.token }}
|
||||
tokenSecretRef:
|
||||
name: {{ .Values.externalSecret.vault.auth.token.secretName }}
|
||||
key: {{ .Values.externalSecret.vault.auth.token.secretKey | default "token" }}
|
||||
{{- else if .Values.externalSecret.vault.auth.appRole }}
|
||||
appRole:
|
||||
path: {{ .Values.externalSecret.vault.auth.appRole.path | default "approle" }}
|
||||
roleId: {{ .Values.externalSecret.vault.auth.appRole.roleId }}
|
||||
secretRef:
|
||||
name: {{ .Values.externalSecret.vault.auth.appRole.secretRef.name }}
|
||||
key: {{ .Values.externalSecret.vault.auth.appRole.secretRef.key | default "secretId" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,64 @@
|
||||
{{- if .Values.externalSecret.enabled }}
|
||||
{{- if and .Values.externalSecret.vault.server .Values.externalSecret.remoteRef.applicationKey .Values.externalSecret.remoteRef.applicationSecret .Values.externalSecret.remoteRef.consumerKey }}
|
||||
---
|
||||
# ExternalSecret pour cert-manager-webhook-ovh-ops
|
||||
apiVersion: external-secrets.io/v1beta1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: {{ .Values.externalSecret.secretName | default "cert-manager-webhook-ovh" }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
app.kubernetes.io/name: cert-manager-webhook-ovh
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
spec:
|
||||
refreshInterval: {{ .Values.externalSecret.refreshInterval | default "1h" }}
|
||||
secretStoreRef:
|
||||
name: {{ .Values.externalSecret.vault.secretStoreName | default "vault-backend" }}
|
||||
kind: ClusterSecretStore
|
||||
target:
|
||||
name: {{ .Values.externalSecret.secretName | default "cert-manager-webhook-ovh" }}
|
||||
creationPolicy: Owner
|
||||
data:
|
||||
- secretKey: application-key
|
||||
remoteRef:
|
||||
key: {{ .Values.externalSecret.remoteRef.applicationKey }}
|
||||
- secretKey: application-secret
|
||||
remoteRef:
|
||||
key: {{ .Values.externalSecret.remoteRef.applicationSecret }}
|
||||
- secretKey: consumer-key
|
||||
remoteRef:
|
||||
key: {{ .Values.externalSecret.remoteRef.consumerKey }}
|
||||
---
|
||||
# ExternalSecret pour cert-manager-ops (partage du même secret)
|
||||
apiVersion: external-secrets.io/v1beta1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: {{ .Values.externalSecret.secretName | default "cert-manager-webhook-ovh" }}
|
||||
namespace: {{ .Values.certManager.namespace }}
|
||||
labels:
|
||||
app.kubernetes.io/name: cert-manager-webhook-ovh
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
spec:
|
||||
refreshInterval: {{ .Values.externalSecret.refreshInterval | default "1h" }}
|
||||
secretStoreRef:
|
||||
name: {{ .Values.externalSecret.vault.secretStoreName | default "vault-backend" }}
|
||||
kind: ClusterSecretStore
|
||||
target:
|
||||
name: {{ .Values.externalSecret.secretName | default "cert-manager-webhook-ovh" }}
|
||||
creationPolicy: Owner
|
||||
data:
|
||||
- secretKey: application-key
|
||||
remoteRef:
|
||||
key: {{ .Values.externalSecret.remoteRef.applicationKey }}
|
||||
- secretKey: application-secret
|
||||
remoteRef:
|
||||
key: {{ .Values.externalSecret.remoteRef.applicationSecret }}
|
||||
- secretKey: consumer-key
|
||||
remoteRef:
|
||||
key: {{ .Values.externalSecret.remoteRef.consumerKey }}
|
||||
{{- else }}
|
||||
{{- fail "External Secrets est activé mais la configuration est incomplète. Veuillez définir externalSecret.vault.server et tous les remoteRef (applicationKey, applicationSecret, consumerKey)" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -1,48 +0,0 @@
|
||||
# ClusterRole pour permettre à cert-manager d'utiliser le webhook OVH
|
||||
# Le ServiceAccount cert-manager doit pouvoir créer des ressources "ovh"
|
||||
# dans le groupe API acme.gkdomaine.fr
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: cert-manager-webhook-ovh:cert-manager
|
||||
labels:
|
||||
app: cert-manager-webhook-ovh
|
||||
rules:
|
||||
- apiGroups:
|
||||
- acme.gkdomaine.fr
|
||||
resources:
|
||||
- ovh
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
# Permissions pour lire les secrets (nécessaire pour lire ovh-credentials)
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
---
|
||||
# ClusterRoleBinding pour lier le ClusterRole au ServiceAccount cert-manager
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: cert-manager-webhook-ovh:cert-manager
|
||||
labels:
|
||||
app: cert-manager-webhook-ovh
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cert-manager-webhook-ovh:cert-manager
|
||||
subjects:
|
||||
# Le ServiceAccount cert-manager dans cert-manager-ops (selon l'erreur RBAC)
|
||||
- kind: ServiceAccount
|
||||
name: cert-manager
|
||||
namespace: cert-manager-ops
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
# ClusterRole pour permettre au webhook OVH de lire les secrets OVH
|
||||
# Utilisation d'un ClusterRole pour éviter tout problème de permissions
|
||||
# Le ServiceAccount du webhook doit pouvoir lire le secret ovh-credentials
|
||||
# dans le namespace cert-manager-ops
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: cert-manager-webhook-ovh:secrets
|
||||
labels:
|
||||
app: cert-manager-webhook-ovh
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
# Pas de resourceNames avec ClusterRole, mais on limite au namespace via le ClusterRoleBinding
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
---
|
||||
# ClusterRoleBinding pour lier le ClusterRole au ServiceAccount du webhook
|
||||
# Le nom du ServiceAccount est défini par le chart officiel
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: cert-manager-webhook-ovh:secrets
|
||||
labels:
|
||||
app: cert-manager-webhook-ovh
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cert-manager-webhook-ovh:secrets
|
||||
subjects:
|
||||
# Le ServiceAccount du webhook (nom basé sur le release name du chart)
|
||||
- kind: ServiceAccount
|
||||
name: cert-manager-webhook-ovh-ops
|
||||
namespace: cert-manager-ops
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: cert-manager-webhook-ovh-sa
|
||||
namespace: cert-manager-webhook-ovh-ops
|
||||
@@ -84,3 +84,44 @@ cert-manager-webhook-ovh:
|
||||
# Important pour vos domaines spécifiques
|
||||
# Note : Vérifiez si votre chart supporte les selectors via values,
|
||||
# sinon il faudra peut-être patcher le template.
|
||||
|
||||
# Configuration External Secrets Operator - Stratégie Multi-Namespace
|
||||
# Cette configuration permet de partager les secrets OVH entre cert-manager-ops et cert-manager-webhook-ovh-ops
|
||||
# en utilisant un ClusterSecretStore et des ExternalSecrets dans chaque namespace
|
||||
externalSecret:
|
||||
enabled: false # Activez cette option pour utiliser External Secrets
|
||||
refreshInterval: "1h" # Intervalle de rafraîchissement du secret
|
||||
secretName: "cert-manager-webhook-ovh" # Nom du Secret créé dans chaque namespace
|
||||
|
||||
# Références aux clés dans Vault
|
||||
remoteRef:
|
||||
applicationKey: "" # Chemin/clef dans Vault pour application-key (ex: "secret/data/ovh#application-key")
|
||||
applicationSecret: "" # Chemin/clef dans Vault pour application-secret (ex: "secret/data/ovh#application-secret")
|
||||
consumerKey: "" # Chemin/clef dans Vault pour consumer-key (ex: "secret/data/ovh#consumer-key")
|
||||
|
||||
# Configuration HashiCorp Vault
|
||||
vault:
|
||||
secretStoreName: "vault-backend" # Nom du ClusterSecretStore à créer
|
||||
server: "https://vault.example.com:8200" # URL de votre serveur Vault
|
||||
path: "secret" # Chemin du secret engine (secret, kv, etc.)
|
||||
version: "v2" # Version de l'API KV (v1 ou v2)
|
||||
auth:
|
||||
# Authentification Kubernetes (recommandé pour la stratégie Multi-Namespace)
|
||||
kubernetes:
|
||||
mountPath: "kubernetes" # Chemin du mount Kubernetes dans Vault
|
||||
role: "" # Nom du rôle Vault configuré pour Kubernetes auth
|
||||
# Le ServiceAccount doit être autorisé dans les namespaces cert-manager-ops et cert-manager-webhook-ovh-ops
|
||||
serviceAccountRef:
|
||||
name: "cert-manager-webhook-ovh-sa" # ServiceAccount utilisé pour l'authentification
|
||||
namespace: "cert-manager-webhook-ovh-ops" # Namespace du ServiceAccount
|
||||
# Alternative : Authentification par token
|
||||
# token:
|
||||
# secretName: "vault-token" # Nom du Secret contenant le token
|
||||
# secretKey: "token" # Clé dans le Secret
|
||||
# Alternative : Authentification AppRole
|
||||
# appRole:
|
||||
# path: "approle"
|
||||
# roleId: "" # Role ID
|
||||
# secretRef:
|
||||
# name: "vault-approle-secret" # Secret contenant le Secret ID
|
||||
# key: "secretId"
|
||||
|
||||
Reference in New Issue
Block a user