PD-8 — Retour d'expérience¶
📚 Navigation User Story
| Document | | | ---------- | -- | | 📋 [Spécification](PD-8-specification.md) | | | 🛠️ [Plan d'implémentation](PD-8-plan.md) | | | ✅ [Critères d'acceptation](PD-8-acceptability.md) | | | 📝 **Retour d'expérience** | *(ce document)* | [← Retour à infrastructure-souveraine](../PD-193-epic.md) · [↑ Index User Story](index.md)1. Résumé exécutif¶
La User Story PD-8 visait à configurer HashiCorp Vault sur OVH pour la gestion centralisée des secrets (credentials PostgreSQL, OVH, AWS, tokens API, CI/CD). L'implémentation fournit un rôle Ansible complet avec installation Vault, backend PostgreSQL TLS, secrets engines (KV v2 + Database), AppRoles avec TTL courts, policies least-privilege et audit logging fichier. Cependant, 2 écarts MAJEURS sont identifiés : audit syslog désactivé (spec §7.7) et certificat autosigné avec proxy_ssl_verify off (spec §7.1), ainsi que 3 écarts MINEURS : policy worker avec bootstrap api-backend, chemin database/ au lieu de db/, et backup pg_dump local sans upload S3. Verdict : ACCEPTÉ AVEC RÉSERVES.
2. Points fluides¶
- Vault installé : version 1.15.4 via playbook Ansible avec service systemd
- Backend PostgreSQL :
vault_storageavec connexion TLS (sslmode=require) - TLS 1.3 : listener Vault configuré avec
tls_min_version = "tls13" - KV v2 activé : secrets engine à
/kvavec versioning (max 10 versions) - Database secrets engine : credentials dynamiques PostgreSQL (TTL 1h, Max TTL 24h)
- AppRoles créés :
api-backend(30m/2h),worker(20m/1h),ci(5m/10m) - SecretIDs single-use :
secret_id_num_uses: 1pour AC4 compliance - Policies least-privilege :
api-backend,worker,ci,vault-observer - Audit fichier :
/var/log/vault/audit.logavec logrotate 90 jours - HMAC accessor : masquage des accessors dans les logs d'audit
- Nginx reverse proxy : Let's Encrypt avec TLS 1.2/1.3 + HSTS
- Health check script :
/opt/vault/scripts/vault-health-check.sh - Backup automatisé : pg_dump quotidien avec rétention 30 jours
- Shamir 5/3 : initialisation avec distribution multi-opérateurs
- mlock activé :
disable_mlock = falsepour sécurité mémoire - Prometheus telemetry : métriques exposées pour monitoring
- Réseau restreint : accès limité à localhost + VPN (10.10.10.0/24)
- Variables chiffrées : credentials dans vault.yml (ansible-vault)
3. Points difficiles¶
| Difficulté | Contexte |
|---|---|
| Certificat autosigné Vault | Spec demande "certificat valide", implémentation génère cert autosigné avec nginx proxy_ssl_verify off |
| Audit syslog désactivé | Spec demande fichier + syslog, code a vault_audit_syslog_enabled: false |
| Chemin database engine | Spec attend db/pv-postgres, code monte sur database/ avec config pv-postgres |
| Bootstrap cross-role | Policy worker autorise génération SecretID api-backend (pattern Prefect) |
| Backup S3 | Plan prévoit snapshots S3 chiffrés + tests, implémentation = pg_dump local |
| Auto-unseal | Plan prévoit AWS KMS, non activé dans config dev (Shamir manuel) |
4. Hypothèses révélées tardivement¶
| Hypothèse initiale | Réalité découverte |
|---|---|
| Raft storage backend | FAUX — PostgreSQL choisi pour consistance avec stack existante |
| AWS KMS auto-unseal en dev | FAUX — Shamir 5/3 manuel, KMS optionnel via vault_seal_type |
| Certificat CA pour Vault | FAUX — Autosigné, Nginx vérifie via Let's Encrypt côté client |
| Secrets engines isolés | PARTIELLEMENT — Worker peut bootstrap api-backend SecretIDs |
| Backup Raft snapshots | FAUX — pg_dump sur PostgreSQL backend |
5. Invariants complexes à implémenter¶
| Invariant | Complexité |
|---|---|
| AppRole TTL courts | SecretID 2-5min single-use nécessite orchestration Prefect pour bootstrap |
| Bootstrap cross-role | Worker génère SecretIDs pour api-backend avant démarrage backend |
| PostgreSQL backend HA | ha_enabled disponible mais non activé en mono-instance |
| Audit obligatoire | Vault refuse de démarrer si audit device échoue |
| TLS end-to-end | Nginx TLS + Vault TLS avec validation désactivée entre les deux |
| Policies read-only | Principe appliqué mais worker a create pour SecretIDs |
6. Dette technique¶
| Dette | Impact | Priorité |
|---|---|---|
| Certificat autosigné + proxy_ssl_verify off | Pas de validation TLS Nginx→Vault, risque MITM interne | HAUTE |
| Audit syslog absent | Centralisation logs limitée, SIEM non alimenté | MOYENNE |
| Chemin database divergent | Documentation/consommateurs à aligner sur database/ vs db/ | BASSE |
| Backup sans upload S3 | Résilience limitée au disque local | MOYENNE |
| Test restauration absent | Procédure de recovery non validée automatiquement | MOYENNE |
| Root token révocation | Rappelé mais non automatisé post-configuration | BASSE |
7. Risques résiduels¶
| Risque | Probabilité | Impact | Mitigation suggérée |
|---|---|---|---|
| Perte clés unseal | Faible | CRITIQUE | Distribution 5 opérateurs, coffre physique |
| MITM Nginx→Vault | Faible | MOYEN | Remplacer par cert PKI interne ou mutual TLS |
| Fuite SecretID CI | Faible | ÉLEVÉ | TTL 2min + single-use, network isolation |
| Backup corrompu | Moyenne | ÉLEVÉ | Ajouter vérification intégrité + test restore |
| Policy trop permissive | Faible | MOYEN | Audit régulier des accès via audit log |
| Secrets engine désynchronisé | Faible | MOYEN | Monitoring connexion database engine |
8. Améliorations processus¶
| Amélioration | Bénéfice attendu |
|---|---|
| Activer audit syslog | Centralisation logs pour SIEM/alerting |
| PKI interne pour Vault TLS | Validation certificat Nginx→Vault (mutual TLS) |
| Aligner chemin database | db/ au lieu de database/ ou MAJ documentation |
| Upload backup S3 chiffré | Résilience offsite avec versioning |
| Test restauration automatisé | Validation mensuelle de la procédure de recovery |
| Rotation root token | Générer token limité post-setup, révoquer root |
| Monitoring AppRole usage | Alertes sur échecs d'authentification |
9. Enseignements clés¶
-
PostgreSQL backend vs Raft — Le choix PostgreSQL plutôt que Raft (embedded) simplifie les backups (pg_dump standard) et s'intègre à la stack existante, au prix d'une dépendance externe. Pour un setup mono-instance, c'est un compromis acceptable.
-
TLS end-to-end nécessite attention — La combinaison Nginx Let's Encrypt (externe) + Vault autosigné (interne) avec
proxy_ssl_verify offcrée une zone de confiance implicite. Un cert PKI interne ou mutual TLS améliorerait la posture de sécurité. -
Bootstrap AppRole cross-role est un pattern accepté — Permettre au worker de générer des SecretIDs pour api-backend (pattern Prefect) évite les credentials statiques au démarrage. Ce trade-off est documenté et limité au périmètre bootstrap.
-
Audit syslog = centralisation obligatoire pour conformité — L'audit fichier seul ne suffit pas pour une architecture avec SIEM. L'activation syslog permettrait l'agrégation et l'alerting temps réel sur les accès sensibles.
-
Les backups Vault nécessitent tests de restoration — Un pg_dump quotidien sans test de restore automatisé est insuffisant pour garantir le RTO. Un job périodique de validation (restore sur instance test) sécuriserait la continuité.