seize-infra-doc/docs/08-secrets-management.md
Hedi Kalboussi 1e90a85359 Documentation initiale infra Seize — passation J7
- 6 docs racine (README, HANDOVER, ARCHITECTURE, DECISIONS, INSTALL, OPERATIONS)
- 9 docs thématiques dans docs/
- 10 templates docker-compose dans configs/
- 7 scripts Python/Shell d'import Furious vers Zitadel
- 2 matrices RBAC

Etat infra au 5 juin 2026 :
- 88 users Furious importes dans Zitadel
- 8 roles RBAC crees et attribues
- Intranet filtre les cartes selon role (Approche A)
- 7 outils SSO operationnels
2026-06-05 17:49:43 +00:00

315 lines
9.3 KiB
Markdown

# 08 — Gestion des secrets
> Bonnes pratiques pour les secrets de l'infrastructure : où ils sont, comment les rotater, et comment ne pas les exposer.
---
## 🔐 Inventaire des secrets
### Secrets stockés sur le serveur
| Type | Localisation | Criticité | Rotation recommandée |
|---|---|---|---|
| Mdp Postgres principal | `~/docker/postgres/.env` | 🔴 Critique | 6 mois |
| Mdp Postgres Zitadel | `~/docker/zitadel/.env` | 🔴 Critique | 6 mois |
| Zitadel MASTERKEY | `~/docker/zitadel/.env` | 🔴⛔ IMMUABLE | Jamais |
| Mdp Gitea DB | `~/docker/gitea/.env` | 🟡 Important | 6 mois |
| Mdp n8n DB | `~/docker/n8n/.env` | 🟡 Important | 6 mois |
| n8n Encryption Key | `~/docker/n8n/.env` | 🔴 Critique | Jamais (perte = perte workflows chiffrés) |
| Client Secret OAuth2 (par outil) | `~/docker/oauth2-proxy-*/env` | 🟡 Important | 6 mois |
| Cookie Secret OAuth2 | `~/docker/oauth2-proxy-*/env` | 🟢 Mineur | 1 an (déconnecte les users) |
| Code Server password (fallback) | `~/docker/code-server/.env` | 🟢 Mineur | 6 mois |
| Furious API credentials | `~/furious-to-zitadel/.env` | 🟡 Important | 6 mois |
| Zitadel Service Account key | `~/furious-to-zitadel/zitadelfuriousimportkey.json` | 🔴 Critique | 1 an (avec expiration prévue) |
| Traefik basic auth | `~/docker/traefik/docker-compose.yml` (label) | 🟡 Important | 6 mois |
### Secrets stockés ailleurs
| Secret | Localisation |
|---|---|
| Mdp utilisateurs Zitadel | Dans la base Postgres Zitadel (hashés) |
| Tokens de session OAuth2-Proxy | Dans les cookies HTTP des navigateurs des users |
| Certificats Let's Encrypt | `~/docker/traefik/letsencrypt/acme.json` (chmod 600) |
---
## 🔒 Bonnes pratiques
### 1. Toujours utiliser un gestionnaire de mots de passe
Pour stocker **tous** les secrets de l'infra :
- **Bitwarden** (cloud + self-hosted possible) ← recommandé
- **KeePassXC** (offline)
- **1Password Business**
Créer une **collection partagée "Seize Infra"** accessible aux mainteneurs (Hedi, Philippe, futur collègue).
### 2. Permissions Linux strictes
Tous les fichiers contenant des secrets doivent avoir `chmod 600` :
```bash
# Vérifier toutes les permissions de .env
find ~/docker -name ".env" -exec ls -la {} \;
# Toutes doivent montrer "-rw-------" (600)
# Vérifier la clé Zitadel
ls -la ~/furious-to-zitadel/zitadelfuriousimportkey.json
# Doit être 600
```
Corriger si nécessaire :
```bash
chmod 600 ~/docker/<service>/.env
```
### 3. Ne JAMAIS committer de secret sur Git
Configurer `.gitignore` dans tous les dépôts :
```gitignore
# Secrets
.env
*.env
*.key
*.pem
*.p12
zitadelfuriousimportkey.json
users-credentials.csv
distribution-teams.csv
roles-mapping.json
letsencrypt/acme.json
# Logs (peuvent contenir des secrets)
*.log
import.log
```
### 4. Ne JAMAIS coller de secret dans une conversation IA
Si tu colles un token, mdp, ou clé dans Claude / ChatGPT / autre, considère-le **compromis** :
- Il peut être logué côté provider
- Il peut être utilisé pour entraîner des modèles
- L'historique est conservé pendant des mois
**Toujours masquer** les secrets (ex: `XXX_REDACTED_XXX`) avant de coller du contenu.
⚠️ Voir [HANDOVER.md](../HANDOVER.md) pour la liste des secrets qui ont été exposés pendant le développement et qui doivent être rotatés.
### 5. Audit des accès aux secrets
Périodiquement, vérifier :
- Qui a accès au gestionnaire de mots de passe ?
- Y a-t-il des anciens employés à révoquer ?
- Les permissions Linux sont-elles toujours OK ?
---
## 🔄 Procédures de rotation
### Rotation Client Secret OAuth2 (par outil)
⏱️ ~5 min par outil.
```bash
# 1. Aller dans Zitadel Console
# → Projects → Infra Seize → Applications → <outil>
# → Actions → Generate Client Secret → copier la nouvelle valeur
# 2. Mettre à jour le .env d'OAuth2-Proxy
nano ~/docker/oauth2-proxy-<outil>/.env
# Remplacer OAUTH2_PROXY_CLIENT_SECRET=...
# 3. Sauvegarder dans le gestionnaire de mdp
# 4. Restart OAuth2-Proxy
cd ~/docker/oauth2-proxy-<outil>
docker compose down
docker compose up -d
# 5. Tester le SSO en incognito
```
### Rotation Postgres password (Gitea ou n8n)
⏱️ ~10 min. **Hors heures de bureau** (le service s'arrête brièvement).
```bash
# 1. Générer nouveau mdp
NEW_PWD=$(openssl rand -base64 32 | tr -d '+/=' | head -c 32)
echo "Nouveau mdp : $NEW_PWD"
# Sauvegarder dans le gestionnaire
# 2. Changer le mdp dans Postgres
docker exec -it postgres psql -U postgres -c "ALTER USER gitea WITH PASSWORD '$NEW_PWD';"
# 3. Mettre à jour le .env du service
nano ~/docker/gitea/.env
# Remplacer GITEA_DB_PASSWORD=...
# 4. Restart
cd ~/docker/gitea
docker compose down
docker compose up -d
# 5. Tester
curl -sI https://git.seizeconsulting.com
```
### Rotation Zitadel Service Account key
⏱️ ~10 min.
```bash
# 1. Console Zitadel → Users → furious-import-service → Keys
# → Créer une nouvelle clé (Type JSON)
# → Télécharger immédiatement
# → Supprimer l'ancienne clé (pour l'invalider)
# 2. Transférer sur le serveur
scp <nouvelle_cle>.json admin@<server>:~/furious-to-zitadel/zitadelfuriousimportkey.json
# 3. Sécuriser
ssh admin@<server>
chmod 600 ~/furious-to-zitadel/zitadelfuriousimportkey.json
# 4. Tester les scripts
cd ~/furious-to-zitadel
source venv/bin/activate
python3 assign-roles.py --dry-run # ou un autre script sans effet
```
### Rotation Furious API credentials
```bash
# 1. Sur Furious : Configuration → Utilisateurs API
# → Supprimer l'ancien compte
# → Créer un nouveau avec les mêmes permissions (User > Search uniquement)
# → Sauvegarder identifiants dans le gestionnaire de mdp
# 2. Mettre à jour le .env
nano ~/furious-to-zitadel/.env
# Remplacer FURIOUS_USERNAME et FURIOUS_PASSWORD
# 3. Tester
cd ~/furious-to-zitadel
source venv/bin/activate
./test-auth.sh
```
### ⛔ ZITADEL_MASTERKEY — IMMUABLE
⚠️ **NE JAMAIS CHANGER** le `ZITADEL_MASTERKEY` après le premier démarrage de Zitadel.
Cette clé est utilisée pour chiffrer/déchiffrer les données sensibles en base. La changer = perdre l'accès à toutes les données.
Si elle a été exposée → option drastique uniquement :
1. Backup complet des données critiques (export users via API)
2. Détruire l'instance Zitadel
3. Re-déployer from scratch avec une nouvelle MASTERKEY
4. Restore les users via les scripts d'import
---
## 📧 Configuration SMTP M365 (à faire)
⚠️ **Pas encore fait** au moment de la passation.
### Prérequis
- Admin M365 (pas Hedi → solliciter quelqu'un d'autre)
- Compte M365 dédié : `noreply@seizeconsulting.com`
### Étape 1 — Créer le compte M365
Demander à l'admin M365 :
1. Créer le compte `noreply@seizeconsulting.com`
2. Activer SMTP AUTH (peut nécessiter ticket Microsoft)
3. Désactiver MFA sur ce compte (incompatible avec SMTP)
4. Générer un **App Password** pour ce compte
### Étape 2 — Configurer dans Zitadel
Console Zitadel → Default Settings → Notifications → SMTP Provider :
| Paramètre | Valeur |
|---|---|
| Host | `smtp.office365.com` |
| Port | `587` |
| User | `noreply@seizeconsulting.com` |
| Password | `<App Password généré>` |
| From | `noreply@seizeconsulting.com` |
| From Name | `Seize Consulting` |
| Reply-to | (vide ou `it@seizeconsulting.com`) |
| TLS | ✅ Required |
### Étape 3 — Tester
Console Zitadel → Default Settings → SMTP → **Test Email**.
→ Si OK, on peut désormais utiliser :
- Welcome emails pour nouveaux users
- Reset password
- MFA Email codes
- Notifications de sécurité
---
## 🔍 Audit des secrets exposés
Pendant le développement (cf. [HANDOVER.md](../HANDOVER.md)), plusieurs secrets ont été exposés dans des conversations IA :
| Secret | Statut | Action requise |
|---|---|---|
| Compte API Furious `mick.emmaus.90849` | 🔴 Exposé | **Rotater dans Furious** |
| ID API Furious `6a0b0396817841ef2d3c87c8` | 🔴 Exposé | **Rotater dans Furious** |
| Token JWT user HKA (1 instance) | 🟡 Expiré | OK (1h de vie) |
| Noms + emails + job_titles ~10 collaborateurs | 🟡 Exposé | Pas de rotation possible, vigilance |
### Procédure post-incident
1. Rotater immédiatement le secret (procédures ci-dessus)
2. Vérifier les **logs d'accès** Zitadel/Furious pour détecter usage suspect
3. Documenter dans un fichier sécurité (qui, quand, quoi)
4. Si données personnelles exposées → notification CNIL si applicable
---
## 🛡️ Hardening complémentaire
### Activer fail2ban (recommandé)
Pour bloquer automatiquement les IPs malveillantes qui scannent SSH ou OAuth2 :
```bash
sudo apt install -y fail2ban
# Config par défaut OK pour SSH
sudo systemctl enable --now fail2ban
# Vérifier
sudo fail2ban-client status sshd
```
### Activer Crowdsec (alternative moderne)
```bash
curl -s https://install.crowdsec.net | sudo sh
# Puis configurer les bouncers (cf-firewall-bouncer, etc.)
```
### Monitoring des tentatives de login échouées Zitadel
À mettre en place via :
- Workflow n8n qui scrape les logs Zitadel toutes les heures
- Alert si > 50 échecs en 1h (potentiellement attaque par brute force)
---
## 📚 Voir aussi
- [HANDOVER.md](../HANDOVER.md) — Liste des secrets exposés à rotater en priorité
- [03-zitadel-setup.md](./03-zitadel-setup.md) — Configuration du service account
- [04-oauth2-proxy-pattern.md](./04-oauth2-proxy-pattern.md) — Rotation des secrets OAuth2
- [OPERATIONS.md](../OPERATIONS.md) — Procédures complètes de rotation