Files
argocd/scripts/sync-all-certificates.sh
2026-01-20 07:34:11 +01:00

272 lines
9.6 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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 le cluster et namespace cible à partir du nom du certificat
# Format attendu: <app>-<env>-tls
# Exemple: homarr-dev-tls -> cluster-dev, namespace homarr-dev
determine_target() {
local cert_name=$1
# 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
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")
# 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
echo " Destination: $TARGET_CLUSTER (namespace: $TARGET_NS)"
# 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
# Synchroniser le secret
echo " Synchronisation en cours..."
# Récupérer le secret
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
# 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
# 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