Skip to content

fix(oe-tsa-core,tsa-server): le journal trace le jeton émis, pas le certificat - #52

Merged
PhilippeVienne merged 1 commit into
devfrom
feat/tsa-audit-token-serial
Sep 30, 2026
Merged

PhilippeVienne merged 1 commit into
devfrom
feat/tsa-audit-token-serial

Conversation

@PhilippeVienne

Copy link
Copy Markdown
Contributor

Objet

Constat J-3 de l'audit de préparation eIDAS/WebTrust du 2026-09-25
(docs/AUDIT_2026_09_25.md, EN 319 421 OVR-7.13-05) : le journal
consignait, pour chaque jeton timestamp.granted, la série du certificat
de la TSU (constante d'un appel à l'autre) au lieu de celle du jeton
réellement émis. Après un incident (horloge fautive, clé suspecte), il était
impossible d'identifier quels jetons avaient été affectés — contrairement à
ce qu'affirme la documentation.

oe-tsa-core journalise maintenant, pour chaque timestamp.granted :

  • la série du jeton (tst_info.serial_number, tirée à chaque appel) ;
  • l'OID et la valeur du messageImprint soumis ;
  • l'empreinte du certificat de la TSU ;
  • gen_time au format RFC 3339 (avec fraction), plus lisible que le format
    Debug utilisé jusqu'ici.

Toutes ces valeurs viennent du jeton et de la requête réellement traités
(déjà en mémoire au moment du journal), pas reconstruites après coup :
l'ordre journal-avant-signature (§15 étape 2b, PR précédentes) reste
inchangé, rien ne le remettait en cause ici.

tsa-server ajoute aussi l'état de l'horloge (traçabilité, écart,
sources) au moment de l'émission — dernier volet de la recommandation de
l'audit. oe_tsa_core::Clock reste délibérément découplé d'oe-timesource
(décision déjà prise, documentée dans le module) : l'enrichissement se fait
dans un Recorder englobant côté tsa-server, qui connaît déjà les deux
côtés, sans qu'oe-tsa-core ait à en savoir quoi que ce soit.

Base : dev (branche indépendante de la pile 2b).

Vérifications

  • cargo fmt --check : silencieux.
  • cargo clippy --workspace --all-targets -- -D warnings : silencieux, sur
    toolchain 1.97 (local) et 1.98.1 (CI).
  • cargo test -p oe-tsa-core -p tsa-server et cargo test --workspace :
    tout au vert.
  • cargo audit --ignore RUSTSEC-2023-0071 : aucune vulnérabilité.
  • Nouveau test oe-tsa-core : deux appels à timestamp() produisent deux
    séries distinctes au journal (recommandation explicite de l'audit), et
    la série journalisée n'est jamais celle du certificat. Mutation : en
    revenant à l'ancien code (série du certificat), le test échoue bien.
  • Nouveaux tests tsa-server : describe_clock_status produit la forme
    attendue, et le Recorder englobant ajoute réellement le champ horloge
    au journal écrit sur disque. Mutation : en retirant l'enrichissement, le
    test échoue bien.

Revue humaine obligatoire

Voir PROVENANCE.md. Chaque case est cochée par le
contributeur humain qui valide la PR, après l'avoir fait lui-même.

  • Revue d'architecture validée par l'humain
  • Code relu et tests unitaires/intégration vérifiés localement
  • Absence de dépendances tierces incompatibles avec la double licence EUPL-1.2 / AGPL-3.0 (make licenses)
  • Validation de l'apport intellectuel et de la paternité humaine sur la modification

Assistance par IA

  • Cette PR a été produite avec l'assistance de Claude Code : les commits concernés portent la remorque Co-authored-by: Claude <noreply@anthropic.com>, auteur et committer restent humains, et scripts/provenance.py archive a été lancé
  • Cette PR a été écrite sans assistance par IA

…ertificat

Constat J-3 de l'audit du 2026-09-25 (EN 319 421 OVR-7.13-05) : le journal
consignait, pour chaque jeton, la série du certificat de la TSU — identique
d'un appel à l'autre — au lieu de celle du TSTInfo réellement émis. Après un
incident (horloge fautive, clé suspecte), il était impossible d'identifier
quels jetons avaient été affectés.

oe-tsa-core : `timestamp.granted` journalise maintenant la série du jeton
(`tst_info.serial_number`, tirée à chaque appel), l'OID et la valeur du
`messageImprint` soumis, et l'empreinte du certificat de la TSU — tous tirés
du jeton et de la requête réellement traités, pas reconstruits après coup.
`gen_time` passe au format RFC 3339 (avec fraction si non nulle) plutôt que
le format `Debug` de `time::OffsetDateTime`. L'ordre journal-avant-signature
(§15 étape 2b) est inchangé : ces valeurs sont déjà connues avant de signer,
aucune raison de journaliser après.

tsa-server : ajoute aussi l'état de l'horloge (traçabilité, écart, sources)
au moment de l'émission, dernier volet de la recommandation de l'audit.
`oe_tsa_core::Clock` reste délibérément découplé d'`oe-timesource` (décision
déjà prise, voir la note de module) : l'enrichissement se fait dans un
`Recorder` englobant côté `tsa-server`, qui connaît déjà les deux, sans que
`oe-tsa-core` ait à en savoir quoi que ce soit.

- oe-tsa-core : nouveau test unitaire prouvant que deux jetons produisent
  deux séries distinctes au journal, et que la série journalisée n'est
  jamais celle du certificat (recommandation explicite de l'audit). Testé
  par mutation.
- tsa-server : nouveaux tests unitaires pour `describe_clock_status` et pour
  la présence effective du champ `horloge` dans le journal écrit. Testé par
  mutation.

Co-authored-by: Claude <noreply@anthropic.com>
PhilippeVienne added a commit that referenced this pull request Sep 30, 2026
…D-1)

Constat D-1 de l'audit du 2026-09-25 : la documentation revendiquait des
mécanismes absents. Mieux vaut un écart déclaré qu'un contrôle revendiqué
et introuvable.

- Matrice : EN 319 401 §7.11 passe en écart (contreseing et réplication
  écrits mais appelés par aucun binaire, cible J-1) ; §7.10 aussi (durée de
  conservation contrôlée côté CA seulement). CONFORMITE-ETSI.md régénéré :
  22 couvertes, 4 écarts, 2 hors périmètre.
- ARCHITECTURE.md §7 et §8 : ce que le journal consigne réellement, l'écart
  J-3 en cours (PR #52), la limite du chaînage sans clé ; scellement,
  contreseing et réplication décrits comme non câblés.
- README : plus de contreseing FreeTSA/DigiCert revendiqué ni d'interface
  webui (reste d'OpenXPKI).
- CA.md (modèle de menace, continuité), API.md, docker-compose.yml,
  values.yaml : les variables de scellement et de réplication sont lues
  mais pas encore exploitées.
- oe-tsa-core : l'en-tête disait CheckTSUCertificate non portée, elle l'est.

Co-authored-by: Claude <noreply@anthropic.com>
@PhilippeVienne
PhilippeVienne force-pushed the feat/tsa-audit-token-serial branch from bb5e608 to 58fb5dd Compare September 30, 2026 12:35
PhilippeVienne added a commit that referenced this pull request Sep 30, 2026
…D-1) (#60)

Constat D-1 de l'audit du 2026-09-25 : la documentation revendiquait des
mécanismes absents. Mieux vaut un écart déclaré qu'un contrôle revendiqué
et introuvable.

- Matrice : EN 319 401 §7.11 passe en écart (contreseing et réplication
  écrits mais appelés par aucun binaire, cible J-1) ; §7.10 aussi (durée de
  conservation contrôlée côté CA seulement). CONFORMITE-ETSI.md régénéré :
  22 couvertes, 4 écarts, 2 hors périmètre.
- ARCHITECTURE.md §7 et §8 : ce que le journal consigne réellement, l'écart
  J-3 en cours (PR #52), la limite du chaînage sans clé ; scellement,
  contreseing et réplication décrits comme non câblés.
- README : plus de contreseing FreeTSA/DigiCert revendiqué ni d'interface
  webui (reste d'OpenXPKI).
- CA.md (modèle de menace, continuité), API.md, docker-compose.yml,
  values.yaml : les variables de scellement et de réplication sont lues
  mais pas encore exploitées.
- oe-tsa-core : l'en-tête disait CheckTSUCertificate non portée, elle l'est.

Co-authored-by: Claude <noreply@anthropic.com>
@PhilippeVienne
PhilippeVienne merged commit 7fed5cd into dev Sep 30, 2026
9 checks passed
@PhilippeVienne
PhilippeVienne deleted the feat/tsa-audit-token-serial branch September 30, 2026 12:48
PhilippeVienne added a commit that referenced this pull request Oct 1, 2026
…a matrice (#84)

Les correctifs de l'audit du 2026-09-25 sont tous sur dev (#52 à #59, via
#76, #80, #82) : la matrice le dit, avec pour chaque ligne repassée en
« couvert » une preuve de mise en service (règle D-2, #79) — pas seulement
un test de bibliothèque.

- bin/tsa-server/tests/serve.rs, le test du binaire, prouve désormais aussi :
  le refus de démarrer quand OPENEIDAS_ACCURACY ne couvre pas la dérive
  tolérée (T-1), le refus d'émettre avec une clé TSU expirée mais un
  certificat encore valide (T-3), la fraction de seconde de genTime (T-1),
  et le journal du jeton relu (série, empreinte soumise, état de l'horloge :
  J-3), en relisant audit-monitor.log après un horodatage réel.
- Le job de démonstration Helm/kind interroge le répondeur OCSP pour un
  numéro jamais émis et exige `unknown` (O-1).
- C-1 : preuve par les tests du binaire ca-server (ARL et certificat de la
  racine servis aux adresses gravées) ; R-2 : étape Helm qui refuse
  l'approbation automatique en production ; R-1 : actions signées relayées
  par ra-console et revue de la voie de secours, toutes deux testées sur les
  binaires.
- Restent en écart, cible resserrée : l'authentification multifacteur
  (GEN-6.5.5-04 : la voie de secours CLI n'a pas de second facteur, son
  contrôle compensatoire — RBAC de l'hôte, trace non authentifiée, revue —
  est nommé dans le mécanisme, décision de l'utilisateur), la durée de
  conservation côté tsa-server (§7.10) et la nouvelle bi-clé à chaque
  renouvellement TSU (TIS-7.6.7). docs/ARCHITECTURE.md décrit le journal
  tel qu'il est.

Bilan : 23 couvertes, 1 implémentée, 10 écarts, 2 hors périmètre (avant :
17 / 1 / 16 / 2). docs/CONFORMITE-ETSI.md régénéré.

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant