add tls sync

This commit is contained in:
2026-01-21 00:33:03 +01:00
parent b3e344a1e2
commit 52832863f7
15 changed files with 631 additions and 212 deletions

View File

@@ -0,0 +1,7 @@
apiVersion: v2
name: tls-sync
description: Chart pour synchroniser automatiquement les secrets TLS depuis OPS vers les autres clusters
type: application
version: 1.0.0
appVersion: "1.0.0"

View File

@@ -0,0 +1,176 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: tls-sync-script
namespace: {{ .Release.Namespace }}
data:
sync-all-certificates.sh: |
#!/bin/bash
# Script pour synchroniser automatiquement tous les secrets TLS depuis les certificats dans OPS
# Ce script est exécuté dans un CronJob Kubernetes
set -e
SOURCE_NS="${SOURCE_NS:-{{ .Values.tlsSync.sourceNamespace }}}"
echo "=== Synchronisation automatique des secrets TLS ==="
echo "Source: namespace $SOURCE_NS (cluster OPS)"
echo "Date: $(date)"
echo ""
# Fonction pour déterminer le cluster et namespace cible à partir du nom du certificat
determine_target() {
local cert_name=$1
if [[ $cert_name =~ -dev-tls$ ]]; then
TARGET_CLUSTER="cluster-dev"
TARGET_NS="${cert_name%-tls}"
elif [[ $cert_name =~ -rct-tls$ ]]; then
TARGET_CLUSTER="cluster-rct"
TARGET_NS="${cert_name%-tls}"
elif [[ $cert_name =~ -prd-tls$ ]]; then
TARGET_CLUSTER="cluster-prd"
TARGET_NS="${cert_name%-tls}"
else
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
}
# Vérifier l'accès au cluster OPS (in-cluster)
echo "1. Vérification de l'accès au cluster OPS..."
if ! kubectl get nodes &>/dev/null; then
echo "❌ Erreur: Impossible d'accéder au cluster OPS"
exit 1
fi
echo " ✅ Accès au cluster OPS confirmé"
# Récupérer tous les certificats
echo "2. Récupération des certificats depuis $SOURCE_NS..."
CERTIFICATES=$(kubectl get certificates -n "$SOURCE_NS" -o json 2>&1)
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
# Vérifier que jq est disponible
if ! command -v jq &> /dev/null; then
echo "❌ Erreur: jq n'est pas disponible dans le conteneur"
exit 1
fi
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"
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")
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 ! kubectl get secret "$SECRET_NAME" -n "$SOURCE_NS" &>/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 ! kubectl get secret "$SECRET_NAME" -n "$SOURCE_NS" -o yaml > "$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 '/^ uid:/d' "$TEMP_FILE" 2>/dev/null || true
sed -i '/^ resourceVersion:/d' "$TEMP_FILE" 2>/dev/null || true
sed -i '/^ selfLink:/d' "$TEMP_FILE" 2>/dev/null || true
sed -i '/^ creationTimestamp:/d' "$TEMP_FILE" 2>/dev/null || true
sed -i "s/namespace: $SOURCE_NS/namespace: $TARGET_NS/" "$TEMP_FILE" 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
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" 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

View File

@@ -0,0 +1,62 @@
apiVersion: batch/v1
kind: CronJob
metadata:
name: tls-sync
namespace: {{ .Release.Namespace }}
spec:
schedule: {{ .Values.tlsSync.schedule | quote }}
concurrencyPolicy: {{ .Values.tlsSync.concurrencyPolicy }}
successfulJobsHistoryLimit: {{ .Values.tlsSync.successfulJobsHistoryLimit }}
failedJobsHistoryLimit: {{ .Values.tlsSync.failedJobsHistoryLimit }}
jobTemplate:
spec:
activeDeadlineSeconds: {{ .Values.tlsSync.jobTimeout }}
backoffLimit: 2
template:
metadata:
labels:
app: tls-sync
spec:
serviceAccountName: tls-sync
restartPolicy: OnFailure
containers:
- name: sync
image: {{ .Values.tlsSync.image.repository }}:{{ .Values.tlsSync.image.tag }}
imagePullPolicy: {{ .Values.tlsSync.image.pullPolicy }}
command:
- /bin/bash
- -c
- |
# Installer jq si nécessaire (l'image bitnami/kubectl ne contient pas jq)
if ! command -v jq &> /dev/null; then
echo "Installation de jq..."
apk add --no-cache jq 2>/dev/null || \
(apt-get update && apt-get install -y jq 2>/dev/null) || \
(yum install -y jq 2>/dev/null) || \
(echo "⚠️ Impossible d'installer jq" && exit 1)
fi
# Exécuter le script de synchronisation
/scripts/sync-all-certificates.sh
env:
- name: SOURCE_NS
value: {{ .Values.tlsSync.sourceNamespace | quote }}
volumeMounts:
- name: sync-script
mountPath: /scripts
readOnly: true
- name: kubeconfig
mountPath: /root/.kube
readOnly: true
resources:
{{- toYaml .Values.tlsSync.resources | nindent 14 }}
volumes:
- name: sync-script
configMap:
name: tls-sync-script
defaultMode: 0755
- name: kubeconfig
secret:
secretName: tls-sync-kubeconfig
optional: true

View File

@@ -0,0 +1,33 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: tls-sync
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: tls-sync-role
namespace: {{ .Release.Namespace }}
rules:
- apiGroups: ["cert-manager.io"]
resources: ["certificates"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: tls-sync-rolebinding
namespace: {{ .Release.Namespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: tls-sync-role
subjects:
- kind: ServiceAccount
name: tls-sync
namespace: {{ .Release.Namespace }}

View File

@@ -0,0 +1,24 @@
# Template pour créer le Secret contenant les kubeconfigs
# Ce fichier est un template - vous devez créer le Secret manuellement
# avec vos kubeconfigs pour chaque cluster
#
# Exemple de commande pour créer le Secret :
#
# kubectl create secret generic tls-sync-kubeconfig \
# --from-file=config=/root/.kube/config \
# -n certificates-ops \
# --dry-run=client -o yaml | kubectl apply -f -
#
# OU si vous avez plusieurs fichiers kubeconfig :
#
# kubectl create secret generic tls-sync-kubeconfig \
# --from-file=cluster-dev=/path/to/dev-kubeconfig \
# --from-file=cluster-rct=/path/to/rct-kubeconfig \
# --from-file=cluster-prd=/path/to/prd-kubeconfig \
# -n certificates-ops \
# --dry-run=client -o yaml | kubectl apply -f -
#
# Note: Le CronJob monte ce Secret dans /root/.kube
# Assurez-vous que le fichier principal s'appelle 'config' ou
# configurez votre script pour utiliser les fichiers appropriés

View File

@@ -0,0 +1,36 @@
# Configuration pour la synchronisation automatique des secrets TLS
tlsSync:
# Intervalle de synchronisation (format cron)
# Par défaut: toutes les heures
schedule: "0 * * * *" # Toutes les heures à minute 0
# Namespace source où se trouvent les certificats
sourceNamespace: "certificates-ops"
# Image à utiliser (doit contenir kubectl et bash)
image:
repository: bitnami/kubectl
tag: "1.31"
pullPolicy: IfNotPresent
# Ressources pour le Job
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"
# Nombre de jobs réussis à conserver
successfulJobsHistoryLimit: 3
# Nombre de jobs échoués à conserver
failedJobsHistoryLimit: 3
# Timeout pour le job (en secondes)
jobTimeout: 300 # 5 minutes
# Concurrency policy: Allow, Forbid, Replace
concurrencyPolicy: Forbid