clear
This commit is contained in:
@@ -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
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -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/)
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
@@ -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"
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
@@ -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 }}
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
@@ -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"
|
|
||||||
|
|
||||||
@@ -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 !"
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user