This commit is contained in:
2026-01-21 22:33:19 +01:00
parent 39853b7882
commit 0027501e09
13 changed files with 0 additions and 1087 deletions

View File

@@ -1,56 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cert-manager-apps
namespace: argocd-ops
spec:
generators:
# Utilise un générateur merge pour combiner :
# 1. Les répertoires Helm existants (détermine quels environnements sont disponibles pour cert-manager)
# 2. Les fichiers de config partagés (pour obtenir name et server)
- merge:
generators:
# Premier générateur : scanne uniquement les répertoires Helm qui existent pour cert-manager
- git:
repoURL: https://git.gkdomaine.fr/kubernetes/argocd.git
revision: main
directories:
- path: "helm/cert-manager/*"
# Deuxième générateur : lit les fichiers de config partagés
# ApplicationSet utilisera seulement les fichiers config.json dont le basename
# correspond à un répertoire Helm trouvé
- git:
repoURL: https://git.gkdomaine.fr/kubernetes/argocd.git
revision: main
files:
- path: "configs/*/config.json"
mergeKeys:
- path.basename
template:
metadata:
# Utilise path.basename qui vient du générateur git (plus fiable que environment du JSON)
name: 'cert-manager-{{path.basename}}'
spec:
# Utilise path.basename pour le projet (ou {{environment}} si disponible dans le JSON)
project: '{{path.basename}}'
source:
repoURL: '{{repository}}'
targetRevision: '{{targetRevision}}'
# Construit explicitement le chemin Helm à partir du basename
path: '{{helmPath}}/cert-manager/{{path.basename}}'
helm:
valueFiles:
- values.yaml
destination:
# Les variables {{name}} et {{server}} viennent du fichier config.json
# (deuxième générateur du merge)
name: '{{name}}'
# server: '{{server}}'
namespace: 'cert-manager'
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

View File

@@ -1,44 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: tls-sync
namespace: argocd-ops
spec:
generators:
# Le CronJob de synchronisation TLS est déployé UNIQUEMENT sur le cluster OPS
- merge:
generators:
# Premier générateur : scanne les répertoires Helm pour tls-sync
- git:
repoURL: https://git.gkdomaine.fr/kubernetes/argocd.git
revision: main
directories:
- path: "helm/tls-sync/*"
# 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-{{path.basename}}'
spec:
project: default
source:
repoURL: '{{repository}}'
targetRevision: '{{targetRevision}}'
path: '{{helmPath}}/tls-sync/{{path.basename}}'
destination:
# Déploie uniquement sur le cluster OPS
name: '{{name}}'
namespace: certificates-{{path.basename}}
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

View File

@@ -1 +0,0 @@

View File

@@ -1,285 +0,0 @@
# PKI Interne pour les Sites Internes
## Vue d'ensemble
Cette architecture implémente une **PKI (Public Key Infrastructure) privée** pour gérer les certificats TLS des sites internes (domaines `.local`), tout en conservant Let's Encrypt pour les sites publics (domaines `.fr`).
## Architecture
### Stratégie hybride
- **Sites publics** (`.fr`) → **Let's Encrypt** (`letsencrypt-prod`)
- Nécessite un accès Internet
- Validation via HTTP-01 challenge
- Certificats reconnus par tous les navigateurs
- **Sites internes** (`.local`) → **PKI Interne** (`ca-issuer`)
- Pas besoin d'accès Internet
- Contrôle total sur les certificats
- Certificats signés par votre propre CA root
## Composants
### 1. CA Root (`ca-root-issuer`)
Génère la **Certificate Authority root** de votre PKI interne.
```yaml
ClusterIssuer: ca-root-issuer
Certificate: ca-root-certificate
Secret: ca-root-secret
```
**Durée de vie** : 10 ans (configurable)
### 2. CA Issuer (`ca-issuer`)
Utilise la CA root pour signer les certificats des applications internes.
```yaml
ClusterIssuer: ca-issuer
```
### 3. Distribution du certificat CA root
Le certificat CA root doit être distribué aux clients (navigateurs, applications) pour qu'ils fassent confiance aux certificats signés.
**ConfigMap** : `ca-root-certificate` dans le namespace `certificates-ops`
## Avantages de la PKI Interne
**Pas d'accès Internet requis** - Les clusters DEV/RCT/PRD peuvent générer des certificats sans Internet
**Contrôle total** - Vous gérez la durée de vie, les politiques, etc.
**Pas de limites de taux** - Pas de restrictions comme Let's Encrypt (50 certificats/semaine)
**Domaines internes** - Support natif pour `.local`, `.internal`, etc.
**Sécurité renforcée** - Certificats uniquement pour votre infrastructure interne
**Renouvellement automatique** - cert-manager gère le renouvellement automatiquement
## Utilisation
### Pour un site interne (`.local`)
Créez un Certificate qui utilise `ca-issuer` :
```yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: harbor-tls
namespace: certificates-ops
annotations:
# IMPORTANT: Ce certificat doit être créé après que ca-issuer soit prêt
# ca-issuer a sync-wave "1", donc ce certificat doit avoir sync-wave "2" ou plus
argocd.argoproj.io/sync-wave: "2"
spec:
secretName: harbor-tls
issuerRef:
name: ca-issuer
kind: ClusterIssuer
dnsNames:
- harbor.gkdomaine.local
- harbor.dev.gkdomaine.local
```
**⚠️ Important** : N'oubliez pas l'annotation `argocd.argoproj.io/sync-wave: "2"` pour que le certificat soit créé après l'initialisation de la PKI.
### Pour un site public (`.fr`)
Utilisez `letsencrypt-prod` comme avant :
```yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: homarr-dev-tls
namespace: certificates-ops
spec:
secretName: homarr-dev-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- homarr.dev.gkdomaine.fr
```
## Installation
### Étape 1 : Déployer la CA root
Les ressources sont déployées automatiquement via ArgoCD :
```bash
# Vérifier que la CA root est créée
kubectl get certificate ca-root-certificate -n certificates-ops --context=cluster-ops
# Vérifier le ClusterIssuer CA
kubectl get clusterissuer ca-issuer --context=cluster-ops
```
### Étape 2 : Extraire le certificat CA root
```bash
# Extraire le certificat CA root
kubectl get secret ca-root-secret -n certificates-ops \
--context=cluster-ops \
-o jsonpath='{.data.tls\.crt}' | base64 -d > ca-root.crt
# Vérifier le certificat
openssl x509 -in ca-root.crt -text -noout
```
### Étape 3 : Distribuer le certificat CA root
#### Option A : Ajouter au ConfigMap (pour distribution dans Kubernetes)
```bash
# Mettre à jour le ConfigMap avec le certificat CA
kubectl create configmap ca-root-certificate \
--from-file=ca.crt=ca-root.crt \
-n certificates-ops \
--context=cluster-ops \
--dry-run=client -o yaml | kubectl apply -f -
```
#### Option B : Installer sur les machines clientes
**Windows** :
```powershell
# Importer dans le magasin de certificats Windows
Import-Certificate -FilePath ca-root.crt -CertStoreLocation Cert:\LocalMachine\Root
```
**Linux** :
```bash
# Copier dans le magasin de certificats système
sudo cp ca-root.crt /usr/local/share/ca-certificates/gkdomaine-ca-root.crt
sudo update-ca-certificates
```
**macOS** :
```bash
# Importer dans le trousseau système
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ca-root.crt
```
#### Option C : Configurer dans les navigateurs
- **Chrome/Edge** : Paramètres → Confidentialité et sécurité → Gérer les certificats → Autorités de certification → Importer
- **Firefox** : Paramètres → Confidentialité et sécurité → Certificats → Afficher les certificats → Autorités → Importer
### Étape 4 : Synchroniser le ConfigMap vers les autres clusters
Le ConfigMap `ca-root-certificate` peut être synchronisé vers les clusters DEV/RCT/PRD pour que les pods puissent faire confiance aux certificats :
```bash
# Synchroniser vers cluster-dev
kubectl get configmap ca-root-certificate -n certificates-ops \
--context=cluster-ops -o yaml | \
kubectl apply --context=cluster-dev -f -
```
## Vérification
### Vérifier la CA root
```bash
# Vérifier le certificat CA root
kubectl get certificate ca-root-certificate -n certificates-ops --context=cluster-ops
# Vérifier le secret CA root
kubectl get secret ca-root-secret -n certificates-ops --context=cluster-ops
# Voir les détails du certificat
kubectl get secret ca-root-secret -n certificates-ops \
--context=cluster-ops \
-o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout
```
### Vérifier un certificat signé par la CA
```bash
# Vérifier un certificat d'application
kubectl get certificate harbor-tls -n certificates-ops --context=cluster-ops
# Vérifier la chaîne de certificats
kubectl get secret harbor-tls -n certificates-ops \
--context=cluster-ops \
-o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout
# Vérifier que le certificat est signé par la CA root
kubectl get secret harbor-tls -n certificates-ops \
--context=cluster-ops \
-o jsonpath='{.data.tls\.crt}' | base64 -d | \
openssl verify -CAfile <(kubectl get secret ca-root-secret -n certificates-ops \
--context=cluster-ops -o jsonpath='{.data.tls\.crt}' | base64 -d)
```
## Migration des certificats existants
Pour migrer un certificat de Let's Encrypt vers la PKI interne :
1. **Modifier le Certificate** pour utiliser `ca-issuer` au lieu de `letsencrypt-prod`
2. **Supprimer l'ancien secret** pour forcer la régénération
3. **Vérifier** que le nouveau certificat est généré et signé par la CA root
Exemple pour Harbor :
```bash
# 1. Modifier le Certificate (dans Git)
# issuerRef.name: ca-issuer
# 2. Supprimer l'ancien secret
kubectl delete secret harbor-tls -n certificates-ops --context=cluster-ops
# 3. Vérifier la régénération
kubectl get certificate harbor-tls -n certificates-ops --context=cluster-ops -w
```
## Sécurité
### Bonnes pratiques
- 🔒 **Protéger la clé privée CA root** - Stockée dans `ca-root-secret`, ne jamais exposer
- 🔄 **Rotation périodique** - Planifier la rotation de la CA root avant expiration (tous les 10 ans)
- 📋 **Audit régulier** - Vérifier régulièrement les certificats émis
- 🚫 **Isolation** - Ne jamais utiliser la CA interne pour des sites publics
- 🔐 **Backup** - Sauvegarder régulièrement le secret `ca-root-secret`
### Rotation de la CA root
Quand la CA root approche de son expiration :
1. Créer une nouvelle CA root (`ca-root-certificate-v2`)
2. Créer un nouveau ClusterIssuer (`ca-issuer-v2`)
3. Migrer progressivement les certificats vers la nouvelle CA
4. Mettre à jour les clients avec le nouveau certificat CA root
## Troubleshooting
### Le certificat n'est pas généré
```bash
# Vérifier les logs de cert-manager
kubectl logs -n cert-manager-ops -l app.kubernetes.io/name=cert-manager --context=cluster-ops --tail=100
# Vérifier le Certificate
kubectl describe certificate <nom-certificat> -n certificates-ops --context=cluster-ops
```
### Le navigateur affiche "Certificat non fiable"
- Vérifier que le certificat CA root est installé sur la machine cliente
- Vérifier que le certificat est bien signé par la CA root
- Vérifier la date de validité du certificat
### Erreur "certificate signed by unknown authority"
- Le certificat CA root n'est pas installé sur le client
- Vérifier que le ConfigMap `ca-root-certificate` est synchronisé vers le cluster cible
## Références
- [cert-manager CA Issuer Documentation](https://cert-manager.io/docs/configuration/ca/)
- [PKI Best Practices](https://www.ssl.com/article/pki-best-practices/)
- [Kubernetes Certificate Management](https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster/)

View File

@@ -1,62 +0,0 @@
# Synchronisation des Secrets TLS Multi-Cluster
## Architecture
Les certificats Let's Encrypt sont générés dans le cluster OPS (qui a cert-manager et accès Internet). Les secrets TLS doivent ensuite être synchronisés vers les clusters DEV, RCT et PRD où les applications sont déployées.
## Solution actuelle
La solution actuelle utilise des Jobs Kubernetes pour copier les secrets, mais nécessite une configuration manuelle des contextes kubectl.
## Solution recommandée : Utiliser ArgoCD avec des Applications
### Option 1 : Synchronisation manuelle via script
Créez un script qui copie les secrets depuis OPS vers les autres clusters :
```bash
#!/bin/bash
# sync-tls-secrets.sh
SECRET_NAME="homarr-dev-tls"
SOURCE_CLUSTER="cluster-ops"
SOURCE_NS="certificates-ops"
TARGET_CLUSTER="cluster-dev"
TARGET_NS="homarr-dev"
# Récupérer le secret depuis OPS
kubectl get secret $SECRET_NAME -n $SOURCE_NS --context=$SOURCE_CLUSTER -o yaml > /tmp/secret.yaml
# Modifier les métadonnées
sed -i '/^ uid:/d' /tmp/secret.yaml
sed -i '/^ resourceVersion:/d' /tmp/secret.yaml
sed -i '/^ selfLink:/d' /tmp/secret.yaml
sed -i '/^ creationTimestamp:/d' /tmp/secret.yaml
sed -i "s/namespace: $SOURCE_NS/namespace: $TARGET_NS/" /tmp/secret.yaml
# Appliquer sur le cluster cible
kubectl apply -f /tmp/secret.yaml --context=$TARGET_CLUSTER
echo "Secret $SECRET_NAME synchronisé de $SOURCE_CLUSTER vers $TARGET_CLUSTER"
```
### Option 2 : Utiliser External Secrets Operator (Recommandé)
External Secrets Operator peut synchroniser les secrets depuis un backend (comme Kubernetes secrets dans OPS) vers les autres clusters.
### Option 3 : Utiliser un CronJob pour synchronisation automatique
Créez un CronJob qui synchronise automatiquement les secrets toutes les heures ou à chaque changement.
## Configuration actuelle
- **Source** : Namespace `certificates-ops` sur cluster OPS
- **Destination** : Namespaces des applications sur clusters DEV/RCT/PRD
- **Mécanisme** : Jobs Kubernetes (nécessite configuration manuelle)
## Prochaines étapes
1. Configurer les contextes kubectl pour accéder aux différents clusters
2. Tester la synchronisation manuelle
3. Automatiser via CronJob ou External Secrets Operator

View File

@@ -1,7 +0,0 @@
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

@@ -1,176 +0,0 @@
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

@@ -1,62 +0,0 @@
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

@@ -1,33 +0,0 @@
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

@@ -1,24 +0,0 @@
# 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

@@ -1,36 +0,0 @@
# 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

View File

@@ -1,119 +0,0 @@
#!/bin/bash
# Script pour extraire le certificat CA root et le mettre à jour dans le ConfigMap
# Usage: ./extract-ca-root-cert.sh [--context CLUSTER_CONTEXT] [--output FILE]
set -e
CONTEXT="${KUBECTL_CONTEXT:-cluster-ops}"
NAMESPACE="certificates-ops"
SECRET_NAME="ca-root-secret"
CONFIGMAP_NAME="ca-root-certificate"
OUTPUT_FILE=""
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--context)
CONTEXT="$2"
shift 2
;;
--output)
OUTPUT_FILE="$2"
shift 2
;;
*)
echo "Usage: $0 [--context CLUSTER_CONTEXT] [--output FILE]"
echo " --context: Contexte kubectl (défaut: cluster-ops)"
echo " --output: Fichier de sortie pour le certificat (optionnel)"
exit 1
;;
esac
done
echo "=== Extraction du certificat CA root ==="
echo "Cluster: $CONTEXT"
echo "Namespace: $NAMESPACE"
echo ""
# Vérifier que kubectl est disponible
if ! command -v kubectl &> /dev/null; then
echo "❌ kubectl n'est pas installé"
exit 1
fi
# Vérifier l'accès au cluster
if ! kubectl --context="$CONTEXT" cluster-info &> /dev/null; then
echo "❌ Impossible d'accéder au cluster $CONTEXT"
exit 1
fi
# Vérifier que le secret existe
if ! kubectl --context="$CONTEXT" get secret "$SECRET_NAME" -n "$NAMESPACE" &> /dev/null; then
echo "❌ Le secret $SECRET_NAME n'existe pas dans le namespace $NAMESPACE"
echo " Assurez-vous que la CA root a été générée :"
echo " kubectl get certificate ca-root-certificate -n $NAMESPACE --context=$CONTEXT"
exit 1
fi
# Extraire le certificat
echo "📋 Extraction du certificat depuis le secret..."
CA_CERT=$(kubectl --context="$CONTEXT" get secret "$SECRET_NAME" -n "$NAMESPACE" \
-o jsonpath='{.data.tls\.crt}' | base64 -d)
if [ -z "$CA_CERT" ]; then
echo "❌ Impossible d'extraire le certificat du secret"
exit 1
fi
# Sauvegarder dans un fichier si demandé
if [ -n "$OUTPUT_FILE" ]; then
echo "$CA_CERT" > "$OUTPUT_FILE"
echo "✅ Certificat sauvegardé dans: $OUTPUT_FILE"
else
TEMP_FILE=$(mktemp)
echo "$CA_CERT" > "$TEMP_FILE"
OUTPUT_FILE="$TEMP_FILE"
echo "✅ Certificat extrait dans un fichier temporaire"
fi
# Afficher les informations du certificat
echo ""
echo "📜 Informations du certificat CA root:"
echo "$CA_CERT" | openssl x509 -text -noout | grep -E "Subject:|Issuer:|Not Before|Not After|X509v3 Subject Alternative Name" || true
# Mettre à jour le ConfigMap
echo ""
echo "🔄 Mise à jour du ConfigMap $CONFIGMAP_NAME..."
# Créer ou mettre à jour le ConfigMap
kubectl --context="$CONTEXT" create configmap "$CONFIGMAP_NAME" \
--from-file=ca.crt="$OUTPUT_FILE" \
-n "$NAMESPACE" \
--dry-run=client -o yaml | \
kubectl --context="$CONTEXT" apply -f -
if [ $? -eq 0 ]; then
echo "✅ ConfigMap mis à jour avec succès"
else
echo "❌ Erreur lors de la mise à jour du ConfigMap"
exit 1
fi
# Nettoyer le fichier temporaire si créé
if [ -n "$TEMP_FILE" ] && [ -f "$TEMP_FILE" ]; then
rm "$TEMP_FILE"
fi
echo ""
echo "=== Résumé ==="
echo "✅ Certificat CA root extrait"
echo "✅ ConfigMap $CONFIGMAP_NAME mis à jour dans le namespace $NAMESPACE"
echo ""
echo "📋 Prochaines étapes:"
echo "1. Distribuer le certificat CA root aux clients (navigateurs, machines)"
echo "2. Voir docs/PKI-INTERNE.md pour les instructions détaillées"
echo ""
echo "Pour extraire le certificat dans un fichier:"
echo " $0 --output ca-root.crt"

View File

@@ -1,182 +0,0 @@
#!/bin/bash
# Script d'initialisation de la PKI interne
# Ce script vérifie et crée le certificat CA root si nécessaire
# Usage: ./init-pki.sh [--context CLUSTER_CONTEXT]
set -e
CONTEXT="${KUBECTL_CONTEXT:-cluster-ops}"
NAMESPACE="certificates-ops"
CERT_NAME="ca-root-certificate"
SECRET_NAME="ca-root-secret"
ISSUER_NAME="ca-root-issuer"
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--context)
CONTEXT="$2"
shift 2
;;
*)
echo "Usage: $0 [--context CLUSTER_CONTEXT]"
echo " --context: Contexte kubectl (défaut: cluster-ops)"
exit 1
;;
esac
done
echo "=== Initialisation de la PKI interne ==="
echo "Cluster: $CONTEXT"
echo "Namespace: $NAMESPACE"
echo ""
# Vérifier que kubectl est disponible
if ! command -v kubectl &> /dev/null; then
echo "❌ kubectl n'est pas installé"
exit 1
fi
# Vérifier l'accès au cluster
if ! kubectl --context="$CONTEXT" cluster-info &> /dev/null; then
echo "❌ Impossible d'accéder au cluster $CONTEXT"
exit 1
fi
# Vérifier que cert-manager est installé
if ! kubectl --context="$CONTEXT" get crd certificates.cert-manager.io &> /dev/null; then
echo "❌ cert-manager n'est pas installé sur le cluster $CONTEXT"
exit 1
fi
# Vérifier que le namespace existe
if ! kubectl --context="$CONTEXT" get namespace "$NAMESPACE" &> /dev/null; then
echo "📦 Création du namespace $NAMESPACE..."
kubectl --context="$CONTEXT" create namespace "$NAMESPACE"
fi
# Vérifier que le ClusterIssuer ca-root-issuer existe
if ! kubectl --context="$CONTEXT" get clusterissuer "$ISSUER_NAME" &> /dev/null; then
echo "❌ Le ClusterIssuer $ISSUER_NAME n'existe pas"
echo " Assurez-vous qu'il est déployé via ArgoCD"
exit 1
fi
# Vérifier si le secret existe déjà
if kubectl --context="$CONTEXT" get secret "$SECRET_NAME" -n "$NAMESPACE" &> /dev/null; then
echo "✅ Le secret $SECRET_NAME existe déjà"
echo " La PKI est déjà initialisée"
# Vérifier l'état du certificat
if kubectl --context="$CONTEXT" get certificate "$CERT_NAME" -n "$NAMESPACE" &> /dev/null; then
CERT_STATUS=$(kubectl --context="$CONTEXT" get certificate "$CERT_NAME" -n "$NAMESPACE" \
-o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || echo "Unknown")
if [ "$CERT_STATUS" == "True" ]; then
echo "✅ Le certificat CA root est prêt"
echo ""
echo "📋 Informations du certificat:"
kubectl --context="$CONTEXT" get certificate "$CERT_NAME" -n "$NAMESPACE" -o wide
echo ""
echo "✅ La PKI est opérationnelle"
exit 0
else
echo "⚠️ Le certificat existe mais n'est pas encore prêt (status: $CERT_STATUS)"
echo " Attente de la génération..."
fi
else
echo "⚠️ Le secret existe mais le Certificate n'existe pas"
echo " Cela peut indiquer un problème de configuration"
fi
else
echo "📋 Le secret $SECRET_NAME n'existe pas encore"
echo " Vérification du Certificate..."
fi
# Vérifier si le Certificate existe
if ! kubectl --context="$CONTEXT" get certificate "$CERT_NAME" -n "$NAMESPACE" &> /dev/null; then
echo "❌ Le Certificate $CERT_NAME n'existe pas dans le namespace $NAMESPACE"
echo " Assurez-vous qu'il est déployé via ArgoCD"
echo ""
echo " Le Certificate doit être créé dans:"
echo " helm/certificates/ops/templates/certificate-ca-root.yaml"
exit 1
fi
# Attendre que le certificat soit généré
echo "⏳ Attente de la génération du certificat CA root..."
echo " (Cela peut prendre quelques secondes)"
MAX_WAIT=120 # 2 minutes
ELAPSED=0
INTERVAL=5
while [ $ELAPSED -lt $MAX_WAIT ]; do
if kubectl --context="$CONTEXT" get secret "$SECRET_NAME" -n "$NAMESPACE" &> /dev/null; then
CERT_STATUS=$(kubectl --context="$CONTEXT" get certificate "$CERT_NAME" -n "$NAMESPACE" \
-o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || echo "False")
if [ "$CERT_STATUS" == "True" ]; then
echo ""
echo "✅ Certificat CA root généré avec succès !"
break
fi
fi
echo -n "."
sleep $INTERVAL
ELAPSED=$((ELAPSED + INTERVAL))
done
echo ""
# Vérifier le résultat final
if ! kubectl --context="$CONTEXT" get secret "$SECRET_NAME" -n "$NAMESPACE" &> /dev/null; then
echo ""
echo "❌ Le secret n'a pas été généré après $MAX_WAIT secondes"
echo ""
echo "🔍 Diagnostic:"
echo ""
echo "1. Vérifier le Certificate:"
kubectl --context="$CONTEXT" get certificate "$CERT_NAME" -n "$NAMESPACE" -o yaml
echo ""
echo "2. Vérifier les événements:"
kubectl --context="$CONTEXT" get events -n "$NAMESPACE" --sort-by='.lastTimestamp' | tail -10
echo ""
echo "3. Vérifier les logs de cert-manager:"
echo " kubectl --context=$CONTEXT logs -n cert-manager-ops -l app.kubernetes.io/name=cert-manager --tail=50"
exit 1
fi
# Vérifier que le ClusterIssuer ca-issuer fonctionne maintenant
echo "🔍 Vérification du ClusterIssuer ca-issuer..."
sleep 2
if kubectl --context="$CONTEXT" get clusterissuer ca-issuer &> /dev/null; then
ISSUER_STATUS=$(kubectl --context="$CONTEXT" get clusterissuer ca-issuer \
-o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || echo "False")
if [ "$ISSUER_STATUS" == "True" ]; then
echo "✅ Le ClusterIssuer ca-issuer est prêt"
else
echo "⚠️ Le ClusterIssuer ca-issuer n'est pas encore prêt (status: $ISSUER_STATUS)"
echo " Il devrait se mettre à jour automatiquement"
fi
fi
echo ""
echo "=== Résumé ==="
echo "✅ Certificat CA root: $(kubectl --context="$CONTEXT" get certificate "$CERT_NAME" -n "$NAMESPACE" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || echo "Unknown")"
echo "✅ Secret CA root: $(kubectl --context="$CONTEXT" get secret "$SECRET_NAME" -n "$NAMESPACE" &> /dev/null && echo "Existe" || echo "Manquant")"
echo ""
echo "📋 Prochaines étapes:"
echo "1. Extraire le certificat CA root:"
echo " ./scripts/extract-ca-root-cert.sh --context=$CONTEXT"
echo ""
echo "2. Distribuer le certificat aux clients (voir docs/PKI-INTERNE.md)"
echo ""
echo "3. Créer des certificats pour vos applications internes en utilisant 'ca-issuer'"
echo ""
echo "🎉 Initialisation terminée !"