# 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)

**Méthode A : Via values.yaml (recommandé si vous n'utilisez pas External Secrets)**

Configurez les credentials dans `values.yaml` :

```yaml
externalSecret:
  enabled: false  # External Secrets désactivé

ovhCredentials:
  applicationKey: "VOTRE_APPLICATION_KEY"
  applicationSecret: "VOTRE_APPLICATION_SECRET"
  consumerKey: "VOTRE_CONSUMER_KEY"
```

Le chart créera automatiquement le secret `cert-manager-webhook-ovh` dans les deux namespaces (`cert-manager-webhook-ovh-ops` et `cert-manager-ops`).

**Méthode B : Création manuelle via kubectl**

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/cert-manager-webhook-ovh" {
  capabilities = ["read"]
}
EOF
```

Stockez les credentials OVH dans Vault :

```bash
# Pour Vault KV v2, utilisez cette commande :
vault kv put secret/cert-manager-webhook-ovh \
  application-key="VOTRE_APPLICATION_KEY" \
  application-secret="VOTRE_APPLICATION_SECRET" \
  consumer-key="VOTRE_CONSUMER_KEY"

# Vérifiez que le secret est bien stocké :
vault kv get secret/cert-manager-webhook-ovh
```

**Important** : 
- Le format du chemin dans `remoteRef` pour External Secrets est `cert-manager-webhook-ovh#application-key` (sans le préfixe `secret/data/`), car le mount path `secret` est déjà défini dans le ClusterSecretStore.
- Le nom du secret dans Vault (`cert-manager-webhook-ovh`) doit correspondre exactement au nom utilisé dans `remoteRef`.

#### Configuration dans values.yaml

Activez External Secrets dans `values.yaml` :

```yaml
externalSecret:
  enabled: true
  refreshInterval: "1h"
  secretName: "cert-manager-webhook-ovh"
  remoteRef:
    applicationKey: "cert-manager-webhook-ovh#application-key"
    applicationSecret: "cert-manager-webhook-ovh#application-secret"
    consumerKey: "cert-manager-webhook-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 "could not get secret data from provider" ou "permission denied"

Cette erreur indique que External Secrets Operator ne peut pas lire les secrets depuis Vault. Vérifiez les points suivants :

#### 1. Vérifier que le secret existe dans Vault

```bash
# Vérifier que le secret existe
vault kv get secret/cert-manager-webhook-ovh

# Si le secret n'existe pas, créez-le :
vault kv put secret/cert-manager-webhook-ovh \
  application-key="VOTRE_APPLICATION_KEY" \
  application-secret="VOTRE_APPLICATION_SECRET" \
  consumer-key="VOTRE_CONSUMER_KEY"
```

#### 2. Vérifier la policy Vault

```bash
# Vérifier que la policy existe
vault policy read cert-manager-webhook-ovh-policy

# Si la policy n'existe pas, créez-la :
vault policy write cert-manager-webhook-ovh-policy - <<EOF
path "secret/data/cert-manager-webhook-ovh" {
  capabilities = ["read"]
}
EOF
```

#### 3. Vérifier le rôle Vault et les permissions

```bash
# Vérifier la configuration du rôle
vault read auth/kubernetes/role/cert-manager-webhook-ovh-role

# Vérifier que le rôle utilise la bonne policy
# Le rôle doit avoir : policies = cert-manager-webhook-ovh-policy
```

#### 4. Vérifier que le ServiceAccount peut s'authentifier

```bash
# Vérifier que le ServiceAccount existe
kubectl get serviceaccount cert-manager-webhook-ovh-sa -n cert-manager-webhook-ovh-ops

# Vérifier les permissions RBAC
kubectl auth can-i use secret --namespace=cert-manager-webhook-ovh-ops \
  --as=system:serviceaccount:cert-manager-webhook-ovh-ops:cert-manager-webhook-ovh-sa
```

#### 5. Vérifier la connexion à Vault

```bash
# Vérifier que le ClusterSecretStore peut se connecter à Vault
kubectl describe clustersecretstore vault-backend

# Vérifier les logs d'External Secrets Operator
kubectl logs -n external-secrets-system \
  -l app.kubernetes.io/name=external-secrets \
  --tail=50 | grep -i "vault\|error\|failed"
```

#### 6. Vérifier le format des chemins

Le format correct pour Vault KV v2 est `cert-manager-webhook-ovh#application-key` (sans le préfixe `secret/data/`).

Vérifiez dans `values.yaml` :
```yaml
remoteRef:
  applicationKey: "cert-manager-webhook-ovh#application-key"  # ✅ Correct
  # ❌ Incorrect: "secret/data/cert-manager-webhook-ovh#application-key"
```

**Important** : Le nom du secret dans Vault doit correspondre exactement au nom utilisé dans `remoteRef` (ici `cert-manager-webhook-ovh`).

#### 7. Forcer une nouvelle synchronisation

```bash
# Forcer une synchronisation immédiate
kubectl annotate externalsecret cert-manager-webhook-ovh \
  -n cert-manager-ops \
  force-sync=$(date +%s) \
  --overwrite
```

### 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
```
