Aller au contenu

PD-7 — Retour d'expérience (REX)

1. Résumé exécutif

Objectif initial : Mettre en place un HSM certifié FIPS 140-2 Level 3 (AWS CloudHSM) pour la protection des clés cryptographiques maîtres de ProbatioVault, avec intégration PKCS#11 depuis le backend OVH via VPN IPSec.

Résultat obtenu : Infrastructure CloudHSM opérationnelle en environnement DEV avec VPC dédié, VPN site-to-site, monitoring CloudWatch complet, et intégration PKCS#11 backend fonctionnelle (SDK 5.17.0).

Verdict d'acceptabilité : ✅ ACCEPTÉ (2 février 2026) - Pipeline contractuel : 41 PASS, 0 FAIL, 0 SKIP - 3 écarts initiaux (E-01 BLOQUANT, E-02 MAJEUR, E-03 MAJEUR) tous RÉSOLUS - Progression : ⛔ REFUSÉ → ⚠️ ACCEPTÉ AVEC RÉSERVES → ✅ ACCEPTÉ

2. Points fluides

  • Spécification structurée : le cadre normatif (NF Z42-013, ISO 14641, FIPS 140-2) a fourni des exigences claires et non ambiguës, facilitant la traduction en critères d'acceptation (CA-01 à CA-08) et invariants (INV-01 à INV-04).
  • Terraform modulaire : les modules vpc_hsm et cloudhsm_cluster permettent un déploiement reproductible par environnement (dev/test/prod) avec des paramètres isolés (CIDR, HA, alarmes).
  • CloudWatch natif : l'intégration monitoring (6 alarmes, 3 metric filters, dashboard) a été entièrement codée en Terraform et déployée automatiquement avec le cluster.
  • Tests contractuels complets : la suite de 41 assertions couvre les axes nominal, erreur, performance, cycle de vie des clés, négatif et non-régression, exécutée automatiquement en CI.
  • SDK 5 env-var auth : le mécanisme CLOUDHSM_ROLE + CLOUDHSM_PIN du SDK 5 a simplifié l'authentification persistante en CI (pas de session login inter-commandes).

3. Points difficiles

  • Première acceptabilité refusée (E-01) : les tests contractuels existaient mais n'avaient pas été exécutés en CI lors de la première revue. L'infrastructure HSM/VPN n'était pas accessible depuis le runner GitLab au moment du premier verdict.
  • Séparation des permissions IAM : le user IAM backend CI (probatiovault-infra-admin) ne disposait pas de cloudwatch:DescribeAlarms, nécessaire pour TC-NEG-03. La résolution a nécessité l'injection de credentials d'un second user IAM (probatiovault-storage-admin) via Vault.
  • Timing des includes CI cross-projets : la modification du template .cloudhsm_with_client dans le repo infra n'était pas immédiatement disponible pour le pipeline backend (dépendance include:project). Le script de test a dû être rendu auto-suffisant pour le fetch Vault.
  • OOM kill Jest en CI : 220 suites de tests avec coverage provoquaient un SIGKILL sur le runner Docker. Résolu par --maxWorkers=2.
  • Permission denied deploy:dev : le répertoire tests/pd-7/ nouvellement ajouté provoquait un échec de git reset --hard sur le serveur de déploiement (ownership root vs user applicatif).
  • 7 tests SKIP bloquant le verdict : des tests liés à la HA (PROD-only), aux clés expirées (pas de rotation encore), aux credentials CU séparés, et au metric filter CloudWatch étaient en SKIP, empêchant un verdict ACCEPTÉ sans réserves.

4. Hypothèses révélées tardivement

  • H-01 : Le runner Docker CI n'a pas accès direct aux commandes ip route — la vérification de routage VPN a dû être adaptée (fallback Docker).
  • H-02 : Les policies Vault JWT pour le backend CI (gitlab-ci-cloudhsm) ne permettent que kv/data/ci/cloudhsm, excluant kv/app/aws-storage. Les credentials CloudWatch ont dû être ajoutés au secret déjà accessible.
  • H-03 : CloudHSM SDK 5 retourne du JSON structuré (pas du texte libre), ce qui a nécessité des parseurs Python inline dans les scripts bash pour extraire les clés/labels.
  • H-04 : describe-metric-filters sur CloudWatch Logs requiert des permissions distinctes de describe-alarms sur CloudWatch. Le contournement par déduction logique (alarm ⇒ filter) a été accepté.

5. Invariants complexes

  • INV-01 (non-exposition des clés privées) : vérifié par TC-ERR-02 (export refusé via pkcs11-tool) et TC-NR-02 (non-extractabilité FIPS). La garantie repose sur le firmware FIPS (CKA_EXTRACTABLE=FALSE automatique). Sensible aux mises à jour du SDK.
  • INV-04 (séparation des clés par label) : vérifié par TC-NOM-03 (patterns regex pv-master-*, pv-tsa-*, etc.). Les clés de test (pv-test-*, integration-test-*) doivent être nettoyées après exécution pour ne pas polluer l'inventaire.
  • INV-02 (journalisation) : dépend de la configuration CloudWatch log group + retention. Le log group /aws/cloudhsm/{cluster_id} est créé par Terraform avec rétention 5 ans (PROD) / 90 jours (DEV).

6. Dette technique

  • Metric filter non vérifié directement : TC-NEG-03 déduit l'existence du metric filter depuis l'alarme CloudWatch. Un accès IAM direct à logs:DescribeMetricFilters permettrait une vérification explicite.
  • TC-KL-03 initial state : l'absence de clés expirées est validée comme état initial correct. Ce test devra être ré-évalué après la première rotation annuelle.
  • TC-KL-04 functional : la vérification de séparation CU est structurelle (admin CU ≠ pv-backend-svc). Un test fonctionnel avec les credentials pv-backend-svc (tentative de suppression → refus) renforcerait la couverture.
  • TC-HA-01 en dev : validé comme "HA non requise" en dev (1 HSM). La couverture HA réelle (multi-AZ, failover) ne sera testable qu'en PROD.
  • TC-NR-04 idle HSM : en l'absence d'activité, la vérification de logs récents est remplacée par la vérification de configuration (retention). Un HSM actif produirait des logs vérifiables.

7. Risques résiduels

  • Risque opérationnel — rotation des clés : la première rotation annuelle n'a pas encore eu lieu. La procédure (Ansible rotate_master_keys.yml) devra être testée avant l'échéance.
  • Risque IAM — fragmentation des credentials : deux users IAM (infra-admin, storage-admin) avec des permissions complémentaires. Une consolidation ou un rôle IAM dédié CI réduirait la complexité.
  • Risque VPN — single point of failure en dev : un seul tunnel VPN en dev (vs 2 en prod). Une coupure VPN bloque toute opération HSM.
  • Risque coût — CloudHSM 24/7 : le cluster HSM tourne en continu (~1.50 $/h par instance). L'absence de mécanisme d'arrêt/démarrage automatique en dev génère un coût fixe.
  • Risque SDK : le passage à un SDK CloudHSM majeur ultérieur pourrait modifier le format de sortie JSON ou le comportement de CLOUDHSM_PIN.

8. Améliorations de processus

  • Exécuter les tests contractuels dès l'étape 6 : le refus initial (E-01) aurait été évité si les tests avaient été exécutés avant la soumission à l'acceptabilité.
  • Documenter les prérequis IAM par test : chaque TC-* devrait lister les permissions AWS requises pour éviter les AccessDenied en CI.
  • Centraliser les credentials CI dans un seul secret Vault : le split entre kv/ci/cloudhsm et kv/app/aws-storage a causé des allers-retours. Un secret unique par pipeline simplifie.
  • Anticiper les contraintes runner : les limitations Docker CI (pas de ip, mémoire limitée, réseau hôte) devraient être documentées dans le template de tests.
  • Séparer les tests par environnement cible : les tests PROD-only (HA, failover réel) devraient être tagués et exécutés conditionnellement sans nécessiter de logique inline.

9. Enseignements clés

  1. L'acceptabilité est un registre probatoire, pas un examen : la progression REFUSÉ → RÉSERVES → ACCEPTÉ est normale et attendue. La clé est la traçabilité des corrections (commits, pipelines, preuves).

  2. Les tests contractuels doivent être exécutés en CI avant toute revue : un verdict sur des tests ABSENT est nécessairement un refus. L'intégration CI des tests contractuels est un prérequis non négociable.

  3. La séparation des permissions IAM en CI nécessite une cartographie préalable : chaque job CI doit connaître ses besoins IAM. Les permissions manquantes ne se manifestent qu'à l'exécution et provoquent des cascades de corrections.

  4. Les SKIP sont des dettes contractuelles : un test SKIP n'est pas un PASS. Il doit être converti en validation architecturale explicite ou reporté avec justification. L'objectif 0 SKIP garantit un verdict sans réserves.

  5. L'infrastructure HSM est un engagement long terme : CloudHSM impose des contraintes de coût (24/7), de réseau (VPN), et de gestion des clés (rotation annuelle) qui dépassent le périmètre d'une user story. La gouvernance doit prévoir un suivi opérationnel post-déploiement.