add tls sync
This commit is contained in:
47
apps/applicationset-tls-sync-wildcard.yaml
Normal file
47
apps/applicationset-tls-sync-wildcard.yaml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: ApplicationSet
|
||||||
|
metadata:
|
||||||
|
name: tls-sync-wildcard
|
||||||
|
namespace: argocd-ops
|
||||||
|
spec:
|
||||||
|
generators:
|
||||||
|
# Le CronJob de synchronisation est déployé UNIQUEMENT sur le cluster OPS
|
||||||
|
- merge:
|
||||||
|
generators:
|
||||||
|
# Premier générateur : scanne les répertoires Helm pour tls-sync-wildcard
|
||||||
|
- git:
|
||||||
|
repoURL: https://git.gkdomaine.fr/kubernetes/argocd.git
|
||||||
|
revision: main
|
||||||
|
directories:
|
||||||
|
- path: "helm/tls-sync-wildcard/*"
|
||||||
|
# Deuxième générateur : lit la config OPS uniquement
|
||||||
|
- git:
|
||||||
|
repoURL: https://git.gkdomaine.fr/kubernetes/argocd.git
|
||||||
|
revision: main
|
||||||
|
files:
|
||||||
|
- path: "configs/ops/config.json"
|
||||||
|
mergeKeys:
|
||||||
|
- path.basename
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
name: 'tls-sync-wildcard-{{path.basename}}'
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: '{{repository}}'
|
||||||
|
targetRevision: '{{targetRevision}}'
|
||||||
|
path: '{{helmPath}}/tls-sync-wildcard/{{path.basename}}'
|
||||||
|
helm:
|
||||||
|
valueFiles:
|
||||||
|
- values.yaml
|
||||||
|
destination:
|
||||||
|
# Déploie uniquement sur le cluster OPS
|
||||||
|
name: '{{name}}'
|
||||||
|
namespace: certificates-{{path.basename}}
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
apiVersion: cert-manager.io/v1
|
|
||||||
kind: ClusterIssuer
|
|
||||||
metadata:
|
|
||||||
name: letsencrypt-dns01-prod
|
|
||||||
spec:
|
|
||||||
acme:
|
|
||||||
server: https://acme-v02.api.letsencrypt.org/directory
|
|
||||||
email: gkpoubelle78@gmail.com
|
|
||||||
privateKeySecretRef:
|
|
||||||
name: letsencrypt-dns01-prod
|
|
||||||
solvers:
|
|
||||||
- dns01:
|
|
||||||
webhook:
|
|
||||||
groupName: acme.gkdomaine.fr
|
|
||||||
solverName: ovh
|
|
||||||
config:
|
|
||||||
# Noms des champs imposés par le chart aureq
|
|
||||||
ovhEndpointName: "ovh-eu"
|
|
||||||
ovhAuthenticationMethod: "application"
|
|
||||||
|
|
||||||
# ATTENTION : Notez bien les noms des clés ci-dessous
|
|
||||||
applicationKey: "1d1a85ccc3a5bcc9"
|
|
||||||
applicationSecretRef:
|
|
||||||
name: ovh-credentials
|
|
||||||
key: application-secret
|
|
||||||
applicationConsumerKeyRef: # et non consumerKeyRef
|
|
||||||
name: ovh-credentials
|
|
||||||
key: consumer-key
|
|
||||||
selector:
|
|
||||||
dnsZones:
|
|
||||||
- "dev.gkdomaine.fr"
|
|
||||||
- "rct.gkdomaine.fr"
|
|
||||||
- "prd.gkdomaine.fr"
|
|
||||||
6
helm/tls-sync-wildcard/ops/Chart.yaml
Normal file
6
helm/tls-sync-wildcard/ops/Chart.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: tls-sync-wildcard
|
||||||
|
description: CronJob pour synchroniser automatiquement les secrets TLS wildcard dans tous les namespaces
|
||||||
|
type: application
|
||||||
|
version: 1.0.0
|
||||||
|
|
||||||
208
helm/tls-sync-wildcard/ops/README.md
Normal file
208
helm/tls-sync-wildcard/ops/README.md
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
# TLS Sync Wildcard - Synchronisation automatique des certificats wildcard
|
||||||
|
|
||||||
|
Ce chart Helm déploie un CronJob qui synchronise automatiquement les secrets TLS wildcard depuis le cluster OPS vers tous les namespaces qui en ont besoin dans les clusters DEV, RCT et PRD.
|
||||||
|
|
||||||
|
## Problème résolu
|
||||||
|
|
||||||
|
En Kubernetes, un Ingress ne peut référencer un secret TLS que s'il est dans le **même namespace** que l'Ingress. C'est une limitation de Kubernetes.
|
||||||
|
|
||||||
|
Pour les certificats wildcard utilisés par plusieurs applications dans différents namespaces, il faut donc copier le secret dans chaque namespace.
|
||||||
|
|
||||||
|
Ce CronJob automatise cette synchronisation.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### 1. Créer le Secret avec le kubeconfig
|
||||||
|
|
||||||
|
Le CronJob a besoin d'accéder aux différents clusters. Créez un Secret contenant les kubeconfigs :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Option 1 : Utiliser le kubeconfig par défaut (si tous les contextes sont dedans)
|
||||||
|
kubectl create secret generic tls-sync-kubeconfig \
|
||||||
|
--from-file=config=$HOME/.kube/config \
|
||||||
|
-n certificates-ops \
|
||||||
|
--dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
# Option 2 : Créer un kubeconfig combiné avec tous les contextes
|
||||||
|
kubectl config view --flatten > /tmp/combined-kubeconfig.yaml
|
||||||
|
kubectl create secret generic tls-sync-kubeconfig \
|
||||||
|
--from-file=config=/tmp/combined-kubeconfig.yaml \
|
||||||
|
-n certificates-ops \
|
||||||
|
--dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important** : Assurez-vous que le fichier dans le Secret s'appelle `config` pour que kubectl le trouve automatiquement dans `/root/.kube/config`.
|
||||||
|
|
||||||
|
### 2. Créer le ConfigMap avec le script
|
||||||
|
|
||||||
|
Le script de synchronisation doit être disponible dans un ConfigMap :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl create configmap tls-sync-wildcard-script \
|
||||||
|
--from-file=sync-all-certificates.sh=../../scripts/sync-all-certificates.sh \
|
||||||
|
-n certificates-ops \
|
||||||
|
--dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Déployer via ArgoCD
|
||||||
|
|
||||||
|
Créez un ApplicationSet ou une Application ArgoCD pour déployer ce chart :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: tls-sync-wildcard
|
||||||
|
namespace: argocd-ops
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: https://git.gkdomaine.fr/kubernetes/argocd.git
|
||||||
|
targetRevision: main
|
||||||
|
path: helm/tls-sync-wildcard/ops
|
||||||
|
destination:
|
||||||
|
name: cluster-ops
|
||||||
|
namespace: certificates-ops
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Déploiement manuel (alternative)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install tls-sync-wildcard ./helm/tls-sync-wildcard/ops \
|
||||||
|
-n certificates-ops \
|
||||||
|
--create-namespace
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Modifier la fréquence de synchronisation
|
||||||
|
|
||||||
|
Éditez `helm/tls-sync-wildcard/ops/values.yaml` :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
tlsSync:
|
||||||
|
schedule: "0 */2 * * *" # Toutes les 2 heures
|
||||||
|
# Autres exemples :
|
||||||
|
# "0 * * * *" - Toutes les heures
|
||||||
|
# "*/30 * * * *" - Toutes les 30 minutes
|
||||||
|
# "0 0 * * *" - Tous les jours à minuit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ajouter des namespaces cibles
|
||||||
|
|
||||||
|
Pour ajouter d'autres namespaces qui utilisent le certificat wildcard, modifiez la fonction `get_wildcard_target_namespaces` dans `scripts/sync-all-certificates.sh` :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
case "$env" in
|
||||||
|
dev)
|
||||||
|
WILDCARD_TARGET_NAMESPACES=("headlamp-dev" "homarr-dev" "longhorn-dev" "autre-app-dev")
|
||||||
|
;;
|
||||||
|
# ...
|
||||||
|
esac
|
||||||
|
```
|
||||||
|
|
||||||
|
## Vérification
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Vérifier le CronJob
|
||||||
|
kubectl get cronjob -n certificates-ops tls-sync-wildcard
|
||||||
|
|
||||||
|
# Vérifier les Jobs créés
|
||||||
|
kubectl get jobs -n certificates-ops -l app=tls-sync-wildcard
|
||||||
|
|
||||||
|
# Voir les logs du dernier Job
|
||||||
|
kubectl logs -n certificates-ops -l app=tls-sync-wildcard --tail=100
|
||||||
|
|
||||||
|
# Déclencher manuellement une synchronisation
|
||||||
|
kubectl create job --from=cronjob/tls-sync-wildcard tls-sync-wildcard-manual-$(date +%s) -n certificates-ops
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dépannage
|
||||||
|
|
||||||
|
### Le CronJob ne se déclenche pas
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Vérifier le schedule
|
||||||
|
kubectl get cronjob tls-sync-wildcard -n certificates-ops -o yaml | grep schedule
|
||||||
|
|
||||||
|
# Vérifier les événements
|
||||||
|
kubectl get events -n certificates-ops --sort-by='.lastTimestamp' | grep tls-sync-wildcard
|
||||||
|
```
|
||||||
|
|
||||||
|
### Les Jobs échouent
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Voir les logs du dernier Job
|
||||||
|
kubectl logs -n certificates-ops -l app=tls-sync-wildcard --tail=100
|
||||||
|
|
||||||
|
# Vérifier les erreurs
|
||||||
|
kubectl describe job -n certificates-ops -l app=tls-sync-wildcard
|
||||||
|
```
|
||||||
|
|
||||||
|
### Erreur "context not found"
|
||||||
|
|
||||||
|
Le Secret `tls-sync-kubeconfig` n'est pas correctement configuré ou les contextes kubectl ne sont pas disponibles.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Vérifier le Secret
|
||||||
|
kubectl get secret tls-sync-kubeconfig -n certificates-ops -o yaml
|
||||||
|
|
||||||
|
# Tester l'accès depuis un pod
|
||||||
|
kubectl run -it --rm debug --image=bitnami/kubectl:1.31 --restart=Never \
|
||||||
|
-n certificates-ops \
|
||||||
|
--overrides='
|
||||||
|
{
|
||||||
|
"spec": {
|
||||||
|
"containers": [{
|
||||||
|
"name": "debug",
|
||||||
|
"image": "bitnami/kubectl:1.31",
|
||||||
|
"volumeMounts": [{
|
||||||
|
"name": "kubeconfig",
|
||||||
|
"mountPath": "/root/.kube",
|
||||||
|
"readOnly": true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"volumes": [{
|
||||||
|
"name": "kubeconfig",
|
||||||
|
"secret": {
|
||||||
|
"secretName": "tls-sync-kubeconfig"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}' \
|
||||||
|
-- kubectl config get-contexts
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────┐
|
||||||
|
│ Cluster OPS │
|
||||||
|
│ │
|
||||||
|
│ cert-manager │─── Génère les certificats Let's Encrypt
|
||||||
|
│ │
|
||||||
|
│ Certificates │─── Crée les secrets TLS dans certificates-ops
|
||||||
|
│ │
|
||||||
|
│ CronJob │─── Synchronise automatiquement les secrets
|
||||||
|
│ tls-sync- │ wildcard vers tous les namespaces nécessaires
|
||||||
|
│ wildcard │
|
||||||
|
└─────────────────┘
|
||||||
|
│
|
||||||
|
├───► Cluster DEV
|
||||||
|
│ ├─── headlamp-dev (wildcard-dev-tls)
|
||||||
|
│ ├─── homarr-dev (wildcard-dev-tls)
|
||||||
|
│ └─── longhorn-dev (wildcard-dev-tls)
|
||||||
|
│
|
||||||
|
├───► Cluster RCT
|
||||||
|
│ └─── (même principe)
|
||||||
|
│
|
||||||
|
└───► Cluster PRD
|
||||||
|
└─── (même principe)
|
||||||
|
```
|
||||||
|
|
||||||
388
helm/tls-sync-wildcard/ops/scripts/sync-all-certificates.sh
Normal file
388
helm/tls-sync-wildcard/ops/scripts/sync-all-certificates.sh
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Script pour synchroniser automatiquement tous les secrets TLS depuis les certificats dans OPS
|
||||||
|
# Usage: ./sync-all-certificates.sh [--sourceCluster "cluster-name"] [--sourceNS "certificates-ops"]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Valeurs par défaut
|
||||||
|
SOURCE_CLUSTER="${SOURCE_CLUSTER:-}"
|
||||||
|
SOURCE_NS="${SOURCE_NS:-certificates-ops}"
|
||||||
|
|
||||||
|
# Parsing des arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--sourceCluster)
|
||||||
|
SOURCE_CLUSTER="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--sourceNS)
|
||||||
|
SOURCE_NS="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--help|-h)
|
||||||
|
echo "Usage: $0 [OPTIONS]"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " --sourceCluster NAME Nom du cluster source (défaut: contexte actuel)"
|
||||||
|
echo " --sourceNS NAME Namespace source (défaut: certificates-ops)"
|
||||||
|
echo " --help, -h Afficher cette aide"
|
||||||
|
echo ""
|
||||||
|
echo "Ce script récupère automatiquement tous les certificats depuis OPS"
|
||||||
|
echo "et synchronise les secrets TLS vers les clusters appropriés."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "❌ Option inconnue: $1"
|
||||||
|
echo "Utilisez --help pour voir l'aide"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "=== Synchronisation automatique des secrets TLS ==="
|
||||||
|
echo "Source: $SOURCE_CLUSTER (namespace: $SOURCE_NS)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Fonction pour déterminer les namespaces cibles pour un certificat wildcard
|
||||||
|
# Les certificats wildcard doivent être copiés dans tous les namespaces qui les utilisent
|
||||||
|
get_wildcard_target_namespaces() {
|
||||||
|
local cert_name=$1
|
||||||
|
local env=""
|
||||||
|
|
||||||
|
# Extraire l'environnement depuis le nom du certificat
|
||||||
|
if [[ $cert_name =~ wildcard-dev-tls ]]; then
|
||||||
|
env="dev"
|
||||||
|
elif [[ $cert_name =~ wildcard-rct-tls ]]; then
|
||||||
|
env="rct"
|
||||||
|
elif [[ $cert_name =~ wildcard-prd-tls ]]; then
|
||||||
|
env="prd"
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Liste des namespaces qui utilisent le certificat wildcard pour cet environnement
|
||||||
|
# Ajoutez ici tous les namespaces qui référencent ce secret dans leurs Ingress
|
||||||
|
case "$env" in
|
||||||
|
dev)
|
||||||
|
WILDCARD_TARGET_NAMESPACES=("headlamp-dev" "homarr-dev" "longhorn-dev")
|
||||||
|
;;
|
||||||
|
rct)
|
||||||
|
WILDCARD_TARGET_NAMESPACES=("headlamp-rct" "homarr-rct" "longhorn-rct")
|
||||||
|
;;
|
||||||
|
prd)
|
||||||
|
WILDCARD_TARGET_NAMESPACES=("headlamp-prd" "homarr-prd" "longhorn-prd")
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fonction pour déterminer le cluster et namespace cible à partir du nom du certificat
|
||||||
|
# Format attendu: <app>-<env>-tls
|
||||||
|
# Exemple: homarr-dev-tls -> cluster-dev, namespace homarr-dev
|
||||||
|
# Pour les certificats wildcard, cette fonction détermine seulement le cluster
|
||||||
|
determine_target() {
|
||||||
|
local cert_name=$1
|
||||||
|
|
||||||
|
# Détecter les certificats wildcard
|
||||||
|
if [[ $cert_name =~ ^wildcard- ]]; then
|
||||||
|
# Pour les certificats wildcard, on détermine seulement le cluster
|
||||||
|
# Les namespaces seront déterminés par get_wildcard_target_namespaces
|
||||||
|
if [[ $cert_name =~ -dev-tls$ ]]; then
|
||||||
|
TARGET_CLUSTER="cluster-dev"
|
||||||
|
TARGET_NS="" # Sera rempli par get_wildcard_target_namespaces
|
||||||
|
IS_WILDCARD=true
|
||||||
|
elif [[ $cert_name =~ -rct-tls$ ]]; then
|
||||||
|
TARGET_CLUSTER="cluster-rct"
|
||||||
|
TARGET_NS=""
|
||||||
|
IS_WILDCARD=true
|
||||||
|
elif [[ $cert_name =~ -prd-tls$ ]]; then
|
||||||
|
TARGET_CLUSTER="cluster-prd"
|
||||||
|
TARGET_NS=""
|
||||||
|
IS_WILDCARD=true
|
||||||
|
else
|
||||||
|
echo "⚠️ Impossible de déterminer le cluster cible pour $cert_name"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Certificats normaux (non-wildcard)
|
||||||
|
IS_WILDCARD=false
|
||||||
|
# Extraire l'environnement (dev, rct, prd)
|
||||||
|
if [[ $cert_name =~ -dev-tls$ ]]; then
|
||||||
|
TARGET_CLUSTER="cluster-dev"
|
||||||
|
TARGET_NS="${cert_name%-tls}" # Garde le suffixe -dev
|
||||||
|
elif [[ $cert_name =~ -rct-tls$ ]]; then
|
||||||
|
TARGET_CLUSTER="cluster-rct"
|
||||||
|
TARGET_NS="${cert_name%-tls}" # Garde le suffixe -rct
|
||||||
|
elif [[ $cert_name =~ -prd-tls$ ]]; then
|
||||||
|
TARGET_CLUSTER="cluster-prd"
|
||||||
|
TARGET_NS="${cert_name%-tls}" # Garde le suffixe -prd
|
||||||
|
else
|
||||||
|
# Par défaut, essayer de deviner depuis le nom
|
||||||
|
# Si le nom contient "dev", utiliser cluster-dev
|
||||||
|
if [[ $cert_name == *"dev"* ]]; then
|
||||||
|
TARGET_CLUSTER="cluster-dev"
|
||||||
|
TARGET_NS="${cert_name%-tls}"
|
||||||
|
else
|
||||||
|
echo "⚠️ Impossible de déterminer le cluster cible pour $cert_name"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Déterminer le contexte à utiliser
|
||||||
|
echo "1. Détermination du contexte kubectl..."
|
||||||
|
if [ -z "$SOURCE_CLUSTER" ] || [ "$SOURCE_CLUSTER" == "in-cluster" ]; then
|
||||||
|
# Utiliser le contexte actuel
|
||||||
|
SOURCE_CLUSTER=$(kubectl config current-context 2>/dev/null)
|
||||||
|
if [ -z "$SOURCE_CLUSTER" ]; then
|
||||||
|
echo "❌ Erreur: Aucun contexte kubectl actuel trouvé"
|
||||||
|
echo " Contextes disponibles:"
|
||||||
|
kubectl config get-contexts -o name 2>/dev/null || echo " (aucun contexte trouvé)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " Utilisation du contexte actuel: $SOURCE_CLUSTER"
|
||||||
|
else
|
||||||
|
# Vérifier que le contexte spécifié existe
|
||||||
|
if ! kubectl config get-contexts "$SOURCE_CLUSTER" &>/dev/null; then
|
||||||
|
echo "❌ Erreur: Le contexte kubectl '$SOURCE_CLUSTER' n'existe pas"
|
||||||
|
echo " Contextes disponibles:"
|
||||||
|
kubectl config get-contexts -o name 2>/dev/null || echo " (aucun contexte trouvé)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " Utilisation du contexte: $SOURCE_CLUSTER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Vérifier l'accès au cluster
|
||||||
|
echo "2. Vérification de l'accès au cluster..."
|
||||||
|
if [ -z "$SOURCE_CLUSTER" ]; then
|
||||||
|
# Pas de contexte spécifié, utiliser le contexte actuel
|
||||||
|
if ! kubectl get nodes &>/dev/null; then
|
||||||
|
echo "❌ Erreur: Impossible d'accéder au cluster"
|
||||||
|
echo " Vérifiez votre configuration kubectl et votre connexion réseau"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Utiliser le contexte spécifié
|
||||||
|
if ! kubectl get nodes --context="$SOURCE_CLUSTER" &>/dev/null; then
|
||||||
|
echo "❌ Erreur: Impossible d'accéder au cluster $SOURCE_CLUSTER"
|
||||||
|
echo " Vérifiez votre configuration kubectl et votre connexion réseau"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Récupérer tous les certificats
|
||||||
|
echo "3. Récupération des certificats depuis $SOURCE_CLUSTER..."
|
||||||
|
if [ -z "$SOURCE_CLUSTER" ]; then
|
||||||
|
CERTIFICATES=$(kubectl get certificates -n "$SOURCE_NS" -o json 2>&1)
|
||||||
|
else
|
||||||
|
CERTIFICATES=$(kubectl get certificates -n "$SOURCE_NS" --context="$SOURCE_CLUSTER" -o json 2>&1)
|
||||||
|
fi
|
||||||
|
KUBECTL_EXIT_CODE=$?
|
||||||
|
|
||||||
|
if [ $KUBECTL_EXIT_CODE -ne 0 ]; then
|
||||||
|
echo "❌ Erreur lors de la récupération des certificats:"
|
||||||
|
echo "$CERTIFICATES" | head -5
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$CERTIFICATES" ] || [ "$CERTIFICATES" == "null" ] || [ "$(echo "$CERTIFICATES" | jq -r '.items // empty')" == "" ]; then
|
||||||
|
echo "⚠️ Aucun certificat trouvé dans $SOURCE_NS sur $SOURCE_CLUSTER"
|
||||||
|
echo " Vérifiez que les certificats existent avec:"
|
||||||
|
if [ -z "$SOURCE_CLUSTER" ]; then
|
||||||
|
echo " kubectl get certificates -n $SOURCE_NS"
|
||||||
|
else
|
||||||
|
echo " kubectl get certificates -n $SOURCE_NS --context=$SOURCE_CLUSTER"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Vérifier que jq est installé
|
||||||
|
if ! command -v jq &> /dev/null; then
|
||||||
|
echo "❌ Erreur: jq n'est pas installé"
|
||||||
|
echo " Installez jq avec: sudo apt-get install jq (Ubuntu/Debian) ou brew install jq (macOS)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extraire les certificats et leurs informations
|
||||||
|
CERT_COUNT=$(echo "$CERTIFICATES" | jq -r '.items | length' 2>/dev/null)
|
||||||
|
if [ -z "$CERT_COUNT" ] || [ "$CERT_COUNT" == "null" ] || [ "$CERT_COUNT" == "0" ]; then
|
||||||
|
echo "⚠️ Aucun certificat trouvé dans $SOURCE_NS sur $SOURCE_CLUSTER"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " Trouvé $CERT_COUNT certificat(s)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Traiter chaque certificat
|
||||||
|
SUCCESS_COUNT=0
|
||||||
|
SKIP_COUNT=0
|
||||||
|
ERROR_COUNT=0
|
||||||
|
|
||||||
|
for i in $(seq 0 $((CERT_COUNT - 1))); do
|
||||||
|
CERT_NAME=$(echo "$CERTIFICATES" | jq -r ".items[$i].metadata.name")
|
||||||
|
SECRET_NAME=$(echo "$CERTIFICATES" | jq -r ".items[$i].spec.secretName")
|
||||||
|
CERT_NAMESPACE=$(echo "$CERTIFICATES" | jq -r ".items[$i].metadata.namespace")
|
||||||
|
IS_WILDCARD=false # Initialisation par défaut
|
||||||
|
|
||||||
|
# Si secretName n'est pas défini, utiliser le nom du certificat
|
||||||
|
if [ "$SECRET_NAME" == "null" ] || [ -z "$SECRET_NAME" ]; then
|
||||||
|
SECRET_NAME="$CERT_NAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "📋 Traitement du certificat: $CERT_NAME"
|
||||||
|
echo " Secret: $SECRET_NAME"
|
||||||
|
|
||||||
|
# Déterminer le cluster et namespace cible
|
||||||
|
if ! determine_target "$CERT_NAME"; then
|
||||||
|
echo " ⚠️ Ignoré (impossible de déterminer la destination)"
|
||||||
|
SKIP_COUNT=$((SKIP_COUNT + 1))
|
||||||
|
echo ""
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Vérifier que le secret existe dans la source
|
||||||
|
if [ -z "$SOURCE_CLUSTER" ]; then
|
||||||
|
SECRET_CHECK_CMD="kubectl get secret \"$SECRET_NAME\" -n \"$SOURCE_NS\""
|
||||||
|
else
|
||||||
|
SECRET_CHECK_CMD="kubectl get secret \"$SECRET_NAME\" -n \"$SOURCE_NS\" --context=\"$SOURCE_CLUSTER\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! eval "$SECRET_CHECK_CMD" &>/dev/null; then
|
||||||
|
echo " ⚠️ Le secret $SECRET_NAME n'existe pas encore (certificat peut-être en cours de génération)"
|
||||||
|
SKIP_COUNT=$((SKIP_COUNT + 1))
|
||||||
|
echo ""
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Récupérer le secret une seule fois
|
||||||
|
TEMP_FILE=$(mktemp)
|
||||||
|
if [ -z "$SOURCE_CLUSTER" ]; then
|
||||||
|
SECRET_GET_CMD="kubectl get secret \"$SECRET_NAME\" -n \"$SOURCE_NS\" -o yaml"
|
||||||
|
else
|
||||||
|
SECRET_GET_CMD="kubectl get secret \"$SECRET_NAME\" -n \"$SOURCE_NS\" --context=\"$SOURCE_CLUSTER\" -o yaml"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! eval "$SECRET_GET_CMD" > "$TEMP_FILE" 2>/dev/null; then
|
||||||
|
echo " ❌ Erreur: Impossible de récupérer le secret"
|
||||||
|
rm -f "$TEMP_FILE"
|
||||||
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
||||||
|
echo ""
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Traitement spécial pour les certificats wildcard
|
||||||
|
if [ "$IS_WILDCARD" = true ]; then
|
||||||
|
echo " 🌐 Certificat wildcard détecté"
|
||||||
|
|
||||||
|
# Obtenir la liste des namespaces cibles
|
||||||
|
if ! get_wildcard_target_namespaces "$CERT_NAME"; then
|
||||||
|
echo " ⚠️ Impossible de déterminer les namespaces cibles pour le wildcard"
|
||||||
|
rm -f "$TEMP_FILE"
|
||||||
|
SKIP_COUNT=$((SKIP_COUNT + 1))
|
||||||
|
echo ""
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " Destination: $TARGET_CLUSTER (namespaces: ${WILDCARD_TARGET_NAMESPACES[*]})"
|
||||||
|
|
||||||
|
# Copier le secret dans chaque namespace cible
|
||||||
|
for TARGET_NS in "${WILDCARD_TARGET_NAMESPACES[@]}"; do
|
||||||
|
echo " → Synchronisation vers namespace: $TARGET_NS"
|
||||||
|
|
||||||
|
# Créer une copie temporaire du fichier pour ce namespace
|
||||||
|
TEMP_FILE_NS=$(mktemp)
|
||||||
|
cp "$TEMP_FILE" "$TEMP_FILE_NS"
|
||||||
|
|
||||||
|
# Modifier les métadonnées pour ce namespace
|
||||||
|
sed -i.bak '/^ uid:/d' "$TEMP_FILE_NS" 2>/dev/null || true
|
||||||
|
sed -i.bak '/^ resourceVersion:/d' "$TEMP_FILE_NS" 2>/dev/null || true
|
||||||
|
sed -i.bak '/^ selfLink:/d' "$TEMP_FILE_NS" 2>/dev/null || true
|
||||||
|
sed -i.bak '/^ creationTimestamp:/d' "$TEMP_FILE_NS" 2>/dev/null || true
|
||||||
|
sed -i.bak "s/namespace: $SOURCE_NS/namespace: $TARGET_NS/" "$TEMP_FILE_NS" 2>/dev/null || true
|
||||||
|
rm -f "${TEMP_FILE_NS}.bak" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Créer le namespace s'il n'existe pas
|
||||||
|
kubectl create namespace "$TARGET_NS" --context="$TARGET_CLUSTER" --dry-run=client -o yaml | kubectl apply --context="$TARGET_CLUSTER" -f - >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
# Appliquer le secret
|
||||||
|
if kubectl apply -f "$TEMP_FILE_NS" --context="$TARGET_CLUSTER" >/dev/null 2>&1; then
|
||||||
|
# Vérifier que le secret existe maintenant
|
||||||
|
if kubectl get secret "$SECRET_NAME" -n "$TARGET_NS" --context="$TARGET_CLUSTER" >/dev/null 2>&1; then
|
||||||
|
echo " ✅ Synchronisé avec succès dans $TARGET_NS"
|
||||||
|
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
|
||||||
|
else
|
||||||
|
echo " ❌ Erreur: Le secret n'a pas été créé dans $TARGET_NS"
|
||||||
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ❌ Erreur lors de l'application du secret dans $TARGET_NS"
|
||||||
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Nettoyage
|
||||||
|
rm -f "$TEMP_FILE_NS" "${TEMP_FILE_NS}.bak" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
else
|
||||||
|
# Certificats normaux (non-wildcard) - comportement original
|
||||||
|
echo " Destination: $TARGET_CLUSTER (namespace: $TARGET_NS)"
|
||||||
|
echo " Synchronisation en cours..."
|
||||||
|
|
||||||
|
# Modifier les métadonnées
|
||||||
|
sed -i.bak '/^ uid:/d' "$TEMP_FILE" 2>/dev/null || true
|
||||||
|
sed -i.bak '/^ resourceVersion:/d' "$TEMP_FILE" 2>/dev/null || true
|
||||||
|
sed -i.bak '/^ selfLink:/d' "$TEMP_FILE" 2>/dev/null || true
|
||||||
|
sed -i.bak '/^ creationTimestamp:/d' "$TEMP_FILE" 2>/dev/null || true
|
||||||
|
sed -i.bak "s/namespace: $SOURCE_NS/namespace: $TARGET_NS/" "$TEMP_FILE" 2>/dev/null || true
|
||||||
|
rm -f "${TEMP_FILE}.bak" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Créer le namespace s'il n'existe pas
|
||||||
|
kubectl create namespace "$TARGET_NS" --context="$TARGET_CLUSTER" --dry-run=client -o yaml | kubectl apply --context="$TARGET_CLUSTER" -f - >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
# Appliquer le secret
|
||||||
|
if kubectl apply -f "$TEMP_FILE" --context="$TARGET_CLUSTER" >/dev/null 2>&1; then
|
||||||
|
# Vérifier que le secret existe maintenant
|
||||||
|
if kubectl get secret "$SECRET_NAME" -n "$TARGET_NS" --context="$TARGET_CLUSTER" >/dev/null 2>&1; then
|
||||||
|
echo " ✅ Synchronisé avec succès"
|
||||||
|
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
|
||||||
|
else
|
||||||
|
echo " ❌ Erreur: Le secret n'a pas été créé"
|
||||||
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ❌ Erreur lors de l'application du secret"
|
||||||
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Nettoyage
|
||||||
|
rm -f "$TEMP_FILE" "${TEMP_FILE}.bak" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
# Résumé
|
||||||
|
echo "=== Résumé ==="
|
||||||
|
echo "✅ Synchronisés avec succès: $SUCCESS_COUNT"
|
||||||
|
echo "⚠️ Ignorés: $SKIP_COUNT"
|
||||||
|
echo "❌ Erreurs: $ERROR_COUNT"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ $ERROR_COUNT -eq 0 ] && [ $SUCCESS_COUNT -gt 0 ]; then
|
||||||
|
echo "🎉 Toutes les synchronisations réussies !"
|
||||||
|
exit 0
|
||||||
|
elif [ $ERROR_COUNT -gt 0 ]; then
|
||||||
|
echo "⚠️ Certaines synchronisations ont échoué"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "ℹ️ Aucune synchronisation effectuée"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
11
helm/tls-sync-wildcard/ops/templates/configmap.yaml
Normal file
11
helm/tls-sync-wildcard/ops/templates/configmap.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: tls-sync-wildcard-script
|
||||||
|
namespace: {{ .Values.tlsSync.sourceNamespace }}
|
||||||
|
labels:
|
||||||
|
app: tls-sync-wildcard
|
||||||
|
data:
|
||||||
|
sync-all-certificates.sh: |
|
||||||
|
{{- .Files.Get "scripts/sync-all-certificates.sh" | indent 4 }}
|
||||||
|
|
||||||
61
helm/tls-sync-wildcard/ops/templates/cronjob.yaml
Normal file
61
helm/tls-sync-wildcard/ops/templates/cronjob.yaml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: tls-sync-wildcard
|
||||||
|
namespace: {{ .Values.tlsSync.sourceNamespace }}
|
||||||
|
labels:
|
||||||
|
app: tls-sync-wildcard
|
||||||
|
spec:
|
||||||
|
schedule: {{ .Values.tlsSync.schedule | quote }}
|
||||||
|
successfulJobsHistoryLimit: {{ .Values.tlsSync.successfulJobsHistoryLimit }}
|
||||||
|
failedJobsHistoryLimit: {{ .Values.tlsSync.failedJobsHistoryLimit }}
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
backoffLimit: {{ .Values.tlsSync.backoffLimit }}
|
||||||
|
activeDeadlineSeconds: {{ .Values.tlsSync.activeDeadlineSeconds }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: tls-sync-wildcard
|
||||||
|
spec:
|
||||||
|
restartPolicy: {{ .Values.tlsSync.restartPolicy }}
|
||||||
|
serviceAccountName: tls-sync-wildcard
|
||||||
|
containers:
|
||||||
|
- name: sync
|
||||||
|
image: {{ .Values.tlsSync.image.repository }}:{{ .Values.tlsSync.image.tag }}
|
||||||
|
imagePullPolicy: {{ .Values.tlsSync.image.pullPolicy }}
|
||||||
|
command:
|
||||||
|
- /bin/bash
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Copier le script depuis le ConfigMap
|
||||||
|
cp /scripts/sync-all-certificates.sh /tmp/sync-all-certificates.sh
|
||||||
|
chmod +x /tmp/sync-all-certificates.sh
|
||||||
|
|
||||||
|
# Exécuter le script
|
||||||
|
/tmp/sync-all-certificates.sh \
|
||||||
|
--sourceCluster "{{ .Values.tlsSync.sourceCluster }}" \
|
||||||
|
--sourceNS "{{ .Values.tlsSync.sourceNamespace }}"
|
||||||
|
volumeMounts:
|
||||||
|
- name: kubeconfig
|
||||||
|
mountPath: /root/.kube
|
||||||
|
readOnly: true
|
||||||
|
- name: script
|
||||||
|
mountPath: /scripts
|
||||||
|
readOnly: true
|
||||||
|
env:
|
||||||
|
- name: KUBECONFIG
|
||||||
|
value: /root/.kube/config
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.tlsSync.resources | nindent 14 }}
|
||||||
|
volumes:
|
||||||
|
- name: kubeconfig
|
||||||
|
secret:
|
||||||
|
secretName: {{ .Values.tlsSync.kubeconfigSecret }}
|
||||||
|
- name: script
|
||||||
|
configMap:
|
||||||
|
name: tls-sync-wildcard-script
|
||||||
|
defaultMode: 0755
|
||||||
|
|
||||||
51
helm/tls-sync-wildcard/ops/templates/rbac.yaml
Normal file
51
helm/tls-sync-wildcard/ops/templates/rbac.yaml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: tls-sync-wildcard
|
||||||
|
labels:
|
||||||
|
app: tls-sync-wildcard
|
||||||
|
rules:
|
||||||
|
# Permissions pour lire les certificats et secrets dans le namespace source
|
||||||
|
- apiGroups:
|
||||||
|
- cert-manager.io
|
||||||
|
resources:
|
||||||
|
- certificates
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
# Permissions pour créer et gérer les secrets dans tous les namespaces
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
- namespaces
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- create
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: tls-sync-wildcard
|
||||||
|
labels:
|
||||||
|
app: tls-sync-wildcard
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: tls-sync-wildcard
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: tls-sync-wildcard
|
||||||
|
namespace: {{ .Values.tlsSync.sourceNamespace }}
|
||||||
|
|
||||||
8
helm/tls-sync-wildcard/ops/templates/serviceaccount.yaml
Normal file
8
helm/tls-sync-wildcard/ops/templates/serviceaccount.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: tls-sync-wildcard
|
||||||
|
namespace: {{ .Values.tlsSync.sourceNamespace }}
|
||||||
|
labels:
|
||||||
|
app: tls-sync-wildcard
|
||||||
|
|
||||||
41
helm/tls-sync-wildcard/ops/values.yaml
Normal file
41
helm/tls-sync-wildcard/ops/values.yaml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Configuration pour le CronJob de synchronisation des secrets TLS wildcard
|
||||||
|
tlsSync:
|
||||||
|
# Schedule Cron pour la synchronisation (toutes les heures par défaut)
|
||||||
|
schedule: "0 * * * *" # Toutes les heures
|
||||||
|
|
||||||
|
# Cluster source (où les certificats sont générés)
|
||||||
|
sourceCluster: "cluster-ops"
|
||||||
|
sourceNamespace: "certificates-ops"
|
||||||
|
|
||||||
|
# Image à utiliser (doit contenir kubectl et bash)
|
||||||
|
image:
|
||||||
|
repository: bitnami/kubectl
|
||||||
|
tag: "1.31"
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
# Ressources
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "128Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "256Mi"
|
||||||
|
cpu: "500m"
|
||||||
|
|
||||||
|
# Nom du secret contenant le kubeconfig
|
||||||
|
# Ce secret doit être créé manuellement avec tous les contextes kubectl
|
||||||
|
kubeconfigSecret: "tls-sync-kubeconfig"
|
||||||
|
|
||||||
|
# Restart policy pour les Jobs
|
||||||
|
restartPolicy: OnFailure
|
||||||
|
|
||||||
|
# Nombre de tentatives en cas d'échec
|
||||||
|
backoffLimit: 3
|
||||||
|
|
||||||
|
# Timeout pour les Jobs (en secondes)
|
||||||
|
activeDeadlineSeconds: 600
|
||||||
|
|
||||||
|
# Historique des Jobs à conserver
|
||||||
|
successfulJobsHistoryLimit: 3
|
||||||
|
failedJobsHistoryLimit: 3
|
||||||
|
|
||||||
@@ -43,12 +43,73 @@ echo "=== Synchronisation automatique des secrets TLS ==="
|
|||||||
echo "Source: $SOURCE_CLUSTER (namespace: $SOURCE_NS)"
|
echo "Source: $SOURCE_CLUSTER (namespace: $SOURCE_NS)"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
# Fonction pour déterminer les namespaces cibles pour un certificat wildcard
|
||||||
|
# Les certificats wildcard doivent être copiés dans tous les namespaces qui les utilisent
|
||||||
|
get_wildcard_target_namespaces() {
|
||||||
|
local cert_name=$1
|
||||||
|
local env=""
|
||||||
|
|
||||||
|
# Extraire l'environnement depuis le nom du certificat
|
||||||
|
if [[ $cert_name =~ wildcard-dev-tls ]]; then
|
||||||
|
env="dev"
|
||||||
|
elif [[ $cert_name =~ wildcard-rct-tls ]]; then
|
||||||
|
env="rct"
|
||||||
|
elif [[ $cert_name =~ wildcard-prd-tls ]]; then
|
||||||
|
env="prd"
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Liste des namespaces qui utilisent le certificat wildcard pour cet environnement
|
||||||
|
# Ajoutez ici tous les namespaces qui référencent ce secret dans leurs Ingress
|
||||||
|
case "$env" in
|
||||||
|
dev)
|
||||||
|
WILDCARD_TARGET_NAMESPACES=("headlamp-dev" "homarr-dev" "longhorn-dev")
|
||||||
|
;;
|
||||||
|
rct)
|
||||||
|
WILDCARD_TARGET_NAMESPACES=("headlamp-rct" "homarr-rct" "longhorn-rct")
|
||||||
|
;;
|
||||||
|
prd)
|
||||||
|
WILDCARD_TARGET_NAMESPACES=("headlamp-prd" "homarr-prd" "longhorn-prd")
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# Fonction pour déterminer le cluster et namespace cible à partir du nom du certificat
|
# Fonction pour déterminer le cluster et namespace cible à partir du nom du certificat
|
||||||
# Format attendu: <app>-<env>-tls
|
# Format attendu: <app>-<env>-tls
|
||||||
# Exemple: homarr-dev-tls -> cluster-dev, namespace homarr-dev
|
# Exemple: homarr-dev-tls -> cluster-dev, namespace homarr-dev
|
||||||
|
# Pour les certificats wildcard, cette fonction détermine seulement le cluster
|
||||||
determine_target() {
|
determine_target() {
|
||||||
local cert_name=$1
|
local cert_name=$1
|
||||||
|
|
||||||
|
# Détecter les certificats wildcard
|
||||||
|
if [[ $cert_name =~ ^wildcard- ]]; then
|
||||||
|
# Pour les certificats wildcard, on détermine seulement le cluster
|
||||||
|
# Les namespaces seront déterminés par get_wildcard_target_namespaces
|
||||||
|
if [[ $cert_name =~ -dev-tls$ ]]; then
|
||||||
|
TARGET_CLUSTER="cluster-dev"
|
||||||
|
TARGET_NS="" # Sera rempli par get_wildcard_target_namespaces
|
||||||
|
IS_WILDCARD=true
|
||||||
|
elif [[ $cert_name =~ -rct-tls$ ]]; then
|
||||||
|
TARGET_CLUSTER="cluster-rct"
|
||||||
|
TARGET_NS=""
|
||||||
|
IS_WILDCARD=true
|
||||||
|
elif [[ $cert_name =~ -prd-tls$ ]]; then
|
||||||
|
TARGET_CLUSTER="cluster-prd"
|
||||||
|
TARGET_NS=""
|
||||||
|
IS_WILDCARD=true
|
||||||
|
else
|
||||||
|
echo "⚠️ Impossible de déterminer le cluster cible pour $cert_name"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Certificats normaux (non-wildcard)
|
||||||
|
IS_WILDCARD=false
|
||||||
# Extraire l'environnement (dev, rct, prd)
|
# Extraire l'environnement (dev, rct, prd)
|
||||||
if [[ $cert_name =~ -dev-tls$ ]]; then
|
if [[ $cert_name =~ -dev-tls$ ]]; then
|
||||||
TARGET_CLUSTER="cluster-dev"
|
TARGET_CLUSTER="cluster-dev"
|
||||||
@@ -70,6 +131,7 @@ determine_target() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@@ -167,6 +229,7 @@ for i in $(seq 0 $((CERT_COUNT - 1))); do
|
|||||||
CERT_NAME=$(echo "$CERTIFICATES" | jq -r ".items[$i].metadata.name")
|
CERT_NAME=$(echo "$CERTIFICATES" | jq -r ".items[$i].metadata.name")
|
||||||
SECRET_NAME=$(echo "$CERTIFICATES" | jq -r ".items[$i].spec.secretName")
|
SECRET_NAME=$(echo "$CERTIFICATES" | jq -r ".items[$i].spec.secretName")
|
||||||
CERT_NAMESPACE=$(echo "$CERTIFICATES" | jq -r ".items[$i].metadata.namespace")
|
CERT_NAMESPACE=$(echo "$CERTIFICATES" | jq -r ".items[$i].metadata.namespace")
|
||||||
|
IS_WILDCARD=false # Initialisation par défaut
|
||||||
|
|
||||||
# Si secretName n'est pas défini, utiliser le nom du certificat
|
# Si secretName n'est pas défini, utiliser le nom du certificat
|
||||||
if [ "$SECRET_NAME" == "null" ] || [ -z "$SECRET_NAME" ]; then
|
if [ "$SECRET_NAME" == "null" ] || [ -z "$SECRET_NAME" ]; then
|
||||||
@@ -184,8 +247,6 @@ for i in $(seq 0 $((CERT_COUNT - 1))); do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo " Destination: $TARGET_CLUSTER (namespace: $TARGET_NS)"
|
|
||||||
|
|
||||||
# Vérifier que le secret existe dans la source
|
# Vérifier que le secret existe dans la source
|
||||||
if [ -z "$SOURCE_CLUSTER" ]; then
|
if [ -z "$SOURCE_CLUSTER" ]; then
|
||||||
SECRET_CHECK_CMD="kubectl get secret \"$SECRET_NAME\" -n \"$SOURCE_NS\""
|
SECRET_CHECK_CMD="kubectl get secret \"$SECRET_NAME\" -n \"$SOURCE_NS\""
|
||||||
@@ -200,10 +261,7 @@ for i in $(seq 0 $((CERT_COUNT - 1))); do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Synchroniser le secret
|
# Récupérer le secret une seule fois
|
||||||
echo " Synchronisation en cours..."
|
|
||||||
|
|
||||||
# Récupérer le secret
|
|
||||||
TEMP_FILE=$(mktemp)
|
TEMP_FILE=$(mktemp)
|
||||||
if [ -z "$SOURCE_CLUSTER" ]; then
|
if [ -z "$SOURCE_CLUSTER" ]; then
|
||||||
SECRET_GET_CMD="kubectl get secret \"$SECRET_NAME\" -n \"$SOURCE_NS\" -o yaml"
|
SECRET_GET_CMD="kubectl get secret \"$SECRET_NAME\" -n \"$SOURCE_NS\" -o yaml"
|
||||||
@@ -219,6 +277,63 @@ for i in $(seq 0 $((CERT_COUNT - 1))); do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Traitement spécial pour les certificats wildcard
|
||||||
|
if [ "$IS_WILDCARD" = true ]; then
|
||||||
|
echo " 🌐 Certificat wildcard détecté"
|
||||||
|
|
||||||
|
# Obtenir la liste des namespaces cibles
|
||||||
|
if ! get_wildcard_target_namespaces "$CERT_NAME"; then
|
||||||
|
echo " ⚠️ Impossible de déterminer les namespaces cibles pour le wildcard"
|
||||||
|
rm -f "$TEMP_FILE"
|
||||||
|
SKIP_COUNT=$((SKIP_COUNT + 1))
|
||||||
|
echo ""
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " Destination: $TARGET_CLUSTER (namespaces: ${WILDCARD_TARGET_NAMESPACES[*]})"
|
||||||
|
|
||||||
|
# Copier le secret dans chaque namespace cible
|
||||||
|
for TARGET_NS in "${WILDCARD_TARGET_NAMESPACES[@]}"; do
|
||||||
|
echo " → Synchronisation vers namespace: $TARGET_NS"
|
||||||
|
|
||||||
|
# Créer une copie temporaire du fichier pour ce namespace
|
||||||
|
TEMP_FILE_NS=$(mktemp)
|
||||||
|
cp "$TEMP_FILE" "$TEMP_FILE_NS"
|
||||||
|
|
||||||
|
# Modifier les métadonnées pour ce namespace
|
||||||
|
sed -i.bak '/^ uid:/d' "$TEMP_FILE_NS" 2>/dev/null || true
|
||||||
|
sed -i.bak '/^ resourceVersion:/d' "$TEMP_FILE_NS" 2>/dev/null || true
|
||||||
|
sed -i.bak '/^ selfLink:/d' "$TEMP_FILE_NS" 2>/dev/null || true
|
||||||
|
sed -i.bak '/^ creationTimestamp:/d' "$TEMP_FILE_NS" 2>/dev/null || true
|
||||||
|
sed -i.bak "s/namespace: $SOURCE_NS/namespace: $TARGET_NS/" "$TEMP_FILE_NS" 2>/dev/null || true
|
||||||
|
rm -f "${TEMP_FILE_NS}.bak" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Créer le namespace s'il n'existe pas
|
||||||
|
kubectl create namespace "$TARGET_NS" --context="$TARGET_CLUSTER" --dry-run=client -o yaml | kubectl apply --context="$TARGET_CLUSTER" -f - >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
# Appliquer le secret
|
||||||
|
if kubectl apply -f "$TEMP_FILE_NS" --context="$TARGET_CLUSTER" >/dev/null 2>&1; then
|
||||||
|
# Vérifier que le secret existe maintenant
|
||||||
|
if kubectl get secret "$SECRET_NAME" -n "$TARGET_NS" --context="$TARGET_CLUSTER" >/dev/null 2>&1; then
|
||||||
|
echo " ✅ Synchronisé avec succès dans $TARGET_NS"
|
||||||
|
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
|
||||||
|
else
|
||||||
|
echo " ❌ Erreur: Le secret n'a pas été créé dans $TARGET_NS"
|
||||||
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ❌ Erreur lors de l'application du secret dans $TARGET_NS"
|
||||||
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Nettoyage
|
||||||
|
rm -f "$TEMP_FILE_NS" "${TEMP_FILE_NS}.bak" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
else
|
||||||
|
# Certificats normaux (non-wildcard) - comportement original
|
||||||
|
echo " Destination: $TARGET_CLUSTER (namespace: $TARGET_NS)"
|
||||||
|
echo " Synchronisation en cours..."
|
||||||
|
|
||||||
# Modifier les métadonnées
|
# Modifier les métadonnées
|
||||||
sed -i.bak '/^ uid:/d' "$TEMP_FILE" 2>/dev/null || true
|
sed -i.bak '/^ uid:/d' "$TEMP_FILE" 2>/dev/null || true
|
||||||
sed -i.bak '/^ resourceVersion:/d' "$TEMP_FILE" 2>/dev/null || true
|
sed -i.bak '/^ resourceVersion:/d' "$TEMP_FILE" 2>/dev/null || true
|
||||||
@@ -244,6 +359,7 @@ for i in $(seq 0 $((CERT_COUNT - 1))); do
|
|||||||
echo " ❌ Erreur lors de l'application du secret"
|
echo " ❌ Erreur lors de l'application du secret"
|
||||||
ERROR_COUNT=$((ERROR_COUNT + 1))
|
ERROR_COUNT=$((ERROR_COUNT + 1))
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Nettoyage
|
# Nettoyage
|
||||||
rm -f "$TEMP_FILE" "${TEMP_FILE}.bak" 2>/dev/null || true
|
rm -f "$TEMP_FILE" "${TEMP_FILE}.bak" 2>/dev/null || true
|
||||||
|
|||||||
Reference in New Issue
Block a user