Skip to content

feat(tsa-server): contreseing du journal par des TSA tierces (constat J-1) - #102

Open
PhilippeVienne wants to merge 1 commit into
devfrom
feat/tsa-audit-cross-seal
Open

PhilippeVienne wants to merge 1 commit into
devfrom
feat/tsa-audit-cross-seal

Conversation

@PhilippeVienne

Copy link
Copy Markdown
Contributor

Objet

Deuxième tranche du constat J-1 (EN 319 401 REQ-7.10-02, REQ-7.10-08), après #101. Base dev, PR indépendante. Le sceau que la TSU pose sur son propre journal est auto-référentiel : il ne prouve rien à qui ne lui fait pas déjà confiance. oe-crosstsa était écrit et testé, aucun binaire ne l'appelait.

  • Contreseing : à chaque passe, la tête de chaîne que la TSU vient de sceller est aussi horodatée par chaque autorité d'OPENEIDAS_CROSS_TSA_URLS. Chaque réponse est consignée (log.cross_sealed) avec le nom de l'autorité, la date, la série et le jeton RFC 3161.
  • Santé : /healthz rend cross_tsas, last_cross_seal, last_cross_seal_count et cross_seal_failures ; trois passes sans aucun contreseing le dégradent.
  • Désactivation explicite : posée à vide, OPENEIDAS_CROSS_TSA_URLS désactive le contreseing au lieu de retomber sur les deux autorités par défaut.

Points d'attention pour la revue :

  • Effet à la fusion, hors du dépôt : le staging garde la valeur par défaut du chart (FreeTSA et DigiCert). Une fois réépinglé, sa TSA enverra à ces deux services publics l'empreinte de la tête de son journal, au démarrage puis toutes les heures. Seule cette empreinte sort ; pour l'éviter, poser tsa.crossTSA.urls: "" dans values-staging.yaml. C'était la configuration prévue depuis l'origine, mais elle devient effective avec cette PR.
  • La signature des jetons tiers n'est pas vérifiée à la collecte : le service contrôle que le jeton porte l'empreinte soumise, faute d'ancres de confiance pour ces autorités. La vérification se fait après coup, avec openssl ts -verify et leur certificat. Un tiers qui répondrait un jeton à la bonne empreinte mais mal signé serait donc compté.
  • Succès partiel : une seule autorité qui répond suffit à ne pas compter d'échec ; last_cross_seal_count dit combien ont répondu. Le contreseing en échec attend l'intervalle normal, pour ne pas solliciter les tiers plus que de raison.
  • CI : les démonstrations kind et compose désactivent le contreseing, pour ne solliciter aucune TSA publique à chaque exécution. docker-compose.yml passe de ${VAR:-défaut} à ${VAR-défaut} pour qu'une valeur vide reste vide.
  • Matrice : l'exigence reste en « écart documenté », les journaux de ca-server et de ra-console n'étant ni scellés ni contresignés (tranche suivante).

Vérifications

  • cargo fmt --check, cargo clippy --workspace --all-targets -- -D warnings (toolchain locale et 1.98.1) : verts.
  • cargo test --workspace --features oe-castore/postgres -- --nocapture avec PostgreSQL et SoftHSM : vert, 96 suites, aucun test ignoré.
  • Sur le binaire réel (bin/tsa-server/tests/serve.rs, token SoftHSM) : une seconde instance de tsa-server prend la première pour TSA tierce ; son journal porte un log.cross_sealed sur la même tête que son log.sealed, le jeton est vérifié par openssl ts -verify -digest <tête>, et la première instance a journalisé ce jeton.
  • cargo audit --ignore RUSTSEC-2023-0071, cargo deny check licenses, helm lint, docker compose config : verts. docs/CONFORMITE-ETSI.md régénéré.
  • Mutations, toutes tuées par le test attendu :
Mutation Test qui échoue
la TSA tierce horodate autre chose que la tête scellée the_sealed_head_is_countersigned_by_each_reachable_third_party
contreseings surcomptés idem
absence de contreseing non comptée three_passes_without_any_countersignature_degrade_health
absence de contreseing jamais signalée idem
zéro contreseing compté comme un succès idem

Non vérifié : un contreseing réel par FreeTSA ou DigiCert. Les tests n'utilisent que des autorités locales, à dessein.

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

https://claude.ai/code/session_01YRg8X9dbmth9GXcR9hP4QQ

… J-1)

Le sceau que la TSU pose sur son propre journal est auto-référentiel : il
ne prouve rien à qui ne lui fait pas déjà confiance. `oe-crosstsa` était
écrit et testé, aucun binaire ne l'appelait.

- À chaque passe, la tête de chaîne que la TSU vient de sceller est aussi
  horodatée par chaque autorité d'OPENEIDAS_CROSS_TSA_URLS. Chaque
  réponse est consignée (`log.cross_sealed`) avec le nom de l'autorité,
  la date, la série et le jeton RFC 3161, vérifiable par `openssl ts
  -verify`. Seule l'empreinte de la tête de chaîne sort du service.
- Une autorité injoignable n'empêche pas les autres de compter. Trois
  passes sans aucun contreseing dégradent `/healthz`, qui rend aussi le
  nombre d'autorités configurées et de réponses à la dernière passe.
- Posée à vide, OPENEIDAS_CROSS_TSA_URLS désactive le contreseing au
  lieu de retomber sur les deux autorités par défaut. Les démonstrations
  de la CI et le test du binaire l'utilisent pour ne solliciter aucune
  TSA publique.
- Le service contrôle que le jeton porte l'empreinte soumise ; il n'en
  vérifie pas la signature, faute d'ancres de confiance pour ces
  autorités.

Cinq mutations tuées : autre empreinte que la tête scellée, absence de
contreseing non comptée, jamais signalée, comptée comme un succès,
contreseings surcomptés.

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