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

9.3 KiB

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 :

# 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 :

chmod 600 ~/docker/<service>/.env

3. Ne JAMAIS committer de secret sur Git

Configurer .gitignore dans tous les dépôts :

# 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 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.

# 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).

# 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.

# 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

# 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), 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 :

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)

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