Skip to content

feat(ra-console): GET /api/v1/audit/search, lecture et vérification des deux journaux - #51

Closed
PhilippeVienne wants to merge 4 commits into
feat/ra-console-audit-s3from
feat/ra-console-audit-search
Closed

PhilippeVienne wants to merge 4 commits into
feat/ra-console-audit-s3from
feat/ra-console-audit-search

Conversation

@PhilippeVienne

Copy link
Copy Markdown
Contributor

Objet

Étape 2b-D du plan WEBUI (docs/WEBUI.md §7, §15), dernière lettre du
découpage A→D : GET /api/v1/audit/search relit et vérifie intégralement
les deux journaux chaînés — celui de ca-server (fait foi pour la PKI) et
celui de ra-console — depuis le stockage S3 commun, avant de répondre.
Jamais un index qui pourrait avoir divergé des fichiers source.

Contrat déjà fixé par docs/WEBUI.md §7 (pas de nouvelle décision de
conception à valider) : filtres serial/from/to, réponse
{chain_verified, entries_checked, results}, chaque résultat marqué de son
journal d'origine, entries_checked sur l'intégralité relue.

Empilée sur #50 (2b-C) : réutilise le champ S3Config qu'elle étend
(OPENEIDAS_S3_CA_KEY, nouvelle variable, défaut ca-server/audit.log) et
AppState.s3. Base : feat/ra-console-audit-s3 (#50), pas dev.

Deux décisions explicites de cette tranche :

  • Chaîne rompue → blocage total (chain_verified: false, results
    vide), même si l'autre chaîne est saine : personne ne doit pouvoir
    l'ignorer par inattention (cohérent avec §7).
  • S3 non configuré → 503 : ra-console n'a aucun accès local au
    journal de ca-server, la route refuse plutôt que de ne vérifier qu'une
    moitié des deux chaînes.
  • Une panne S3 (503, indisponibilité) est distinguée d'une chaîne rompue
    (200, chain_verified: false) : l'appelant ne doit jamais confondre
    « je n'ai pas pu vérifier » avec « j'ai vérifié, et c'est rompu ».

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 ra-console (avec OE_CASTORE_TEST_DSN) : tout au vert,
    tests/no_pkcs11.rs compris.
  • cargo test --workspace : tout au vert.
  • cargo audit --ignore RUSTSEC-2023-0071 : aucune vulnérabilité.
  • bin/ra-console/tests/audit_search.rs (nouveau), contre un serveur HTTP
    qui se comporte comme un service S3-compatible (pas d'image MinIO
    accessible dans cet environnement) : fusion et tri des deux journaux,
    filtre par série, panne S3 distinguée d'une chaîne rompue, et surtout —
    une chaîne rompue bloque tout l'affichage.
  • Mutation : en retirant le blocage sur chaîne rompue, le test dédié échoue
    bien ; restauré ensuite.

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

PhilippeVienne and others added 2 commits September 28, 2026 10:20
…le vers l'arc PEN (#44)

Ajoute OPENEIDAS_PRODUCTION : quand elle est activée, le service refuse de démarrer si
l'OID de politique appartient à un arc de test (ancien numéro 99999 ou sous-arc 9 d'un
numéro d'entreprise), garde-fou prévu par le plan d'OID d'OTSPI.

Ajoute scripts/set-oid-arc.sh <PEN> pour remplacer l'OID de test historique par l'arc de
test 1.3.6.1.4.1.<PEN>.9.1.1.1 dans le code, les tests, le déploiement et la documentation,
dès que l'IANA aura attribué le numéro d'entreprise. Prépare la résolution de l'issue #36.
…mpatible (#49)

Étape 2b (docs/WEBUI.md §7, §15) : le journal d'audit de ca-server peut être
copié à chaque écriture sur un stockage objet compatible S3, auto-hébergé
(MinIO, Garage, Ceph… jamais AWS ni un service géré, décision de
l'association) — voir crates/oe-s3, ajouté et vérifié précédemment.

- OPENEIDAS_S3_ENDPOINT/BUCKET/REGION/ACCESS_KEY/SECRET_KEY/KEY, toutes
  optionnelles ensemble : sans OPENEIDAS_S3_ENDPOINT, le journal reste
  purement local, rétrocompatible.
- AuditRecorder écrit d'abord en local (source de vérité, verrou et
  chaînage), puis, si S3 est configuré, relit le fichier entier et
  l'envoie en une fois (S3 ne connaît pas d'ajout partiel).
- Bloquant comme le reste du journal (PR précédentes sur oe-ca-core,
  oe-raflow, oe-tsa-core) : un échec de l'envoi S3 fait échouer
  l'opération qui en dépend, rien n'est journalisé tant que S3 ne l'a
  pas reçu.
- tests/s3_journal.rs : contre un vrai PostgreSQL et un serveur HTTP qui
  se comporte comme un service S3-compatible, deux preuves — la copie
  envoyée à S3 est identique au journal local, et un envoi S3 en échec
  ne commit rien en base (pas seulement une erreur rendue). Testé par
  mutation : en retirant le blocage, le second test échoue bien.

Co-authored-by: Claude <noreply@anthropic.com>
@PhilippeVienne
PhilippeVienne added this pull request to stack #74 September 28, 2026 08:21
PhilippeVienne and others added 2 commits September 28, 2026 10:22
)

Étape 2b-C du plan WEBUI (docs/WEBUI.md §7, §15) : le journal d'audit propre
à ra-console (2b-A) peut lui aussi être copié sur le stockage objet
compatible S3 auto-hébergé (mêmes variables OPENEIDAS_S3_* que ca-server,
OPENEIDAS_S3_KEY distinguant les deux journaux dans le même compartiment).

À la différence de ca-server (journal bloquant, preuve légale de la PKI),
celui de ra-console reste best-effort — décision déjà prise et documentée
dans audit.rs : un journal qui n'écrit pas ne doit pas faire échouer une
connexion par ailleurs valide. L'envoi S3 suit la même règle : il est tenté
dans une tâche détachée après l'écriture locale, sans jamais bloquer ni
faire échouer l'appelant.

- AuditRecorder passe d'un tuple struct à des champs nommés (log, path, s3)
  pour porter le client S3 optionnel ; API construite via AuditRecorder::new().
- tests/s3_journal.rs : contre un serveur HTTP qui se comporte comme un
  service S3-compatible (MinIO indisponible dans cet environnement) —
  la copie envoyée est identique au journal local, et un service S3 en
  panne n'empêche ni l'écriture locale ni l'appelant de continuer. Testé
  par mutation (retrait de l'envoi S3 → le premier test échoue bien).

Co-authored-by: Claude <noreply@anthropic.com>
…es deux journaux

Étape 2b-D du plan WEBUI (docs/WEBUI.md §7, §15) : la route relit et vérifie
intégralement les deux journaux chaînés (celui de ca-server, qui fait foi
pour la PKI, et celui de ra-console) depuis le stockage S3 commun, avant de
répondre — jamais un index qui pourrait avoir divergé des fichiers source.

Contrat déjà fixé par docs/WEBUI.md §7 : filtres serial/from/to, réponse
{chain_verified, entries_checked, results}, chaque résultat marqué de son
journal d'origine. entries_checked porte sur l'intégralité de ce qui a été
relu, pas seulement sur les entrées retournées.

Décision explicite pour cette tranche : un journal rompu ou illisible
(l'un des deux, ou les deux) bloque tout l'affichage (chain_verified: false,
results vide) plutôt que de montrer une moitié de la vérité à côté d'une
alerte. Sans stockage S3 configuré, la route refuse (503) : ra-console n'a
aucun accès local au journal de ca-server, seul S3 les met en commun
(nouvelle variable OPENEIDAS_S3_CA_KEY, même bucket que OPENEIDAS_S3_* de
2b-C, clé distincte par défaut "ca-server/audit.log").

Une panne S3 (indisponibilité) et une chaîne rompue (constat d'intégrité)
sont deux échecs distincts : la première répond 503, la seconde répond 200
avec chain_verified: false — l'appelant ne doit jamais confondre « je n'ai
pas pu vérifier » avec « j'ai vérifié, et c'est rompu ».

- audit_search.rs (nouveau module) : search() fait tout le travail, testable
  sans HTTP ni PostgreSQL.
- tests/audit_search.rs : contre un serveur HTTP qui se comporte comme un
  service S3-compatible (MinIO indisponible dans cet environnement) —
  fusion et tri des deux journaux, filtre par série, chaîne rompue bloque
  tout (testé par mutation : sans le blocage, ce test échoue), panne S3
  distinguée d'une chaîne rompue.

Co-authored-by: Claude <noreply@anthropic.com>
@PhilippeVienne

Copy link
Copy Markdown
Contributor Author

Remplacée par #78 (base dev) : GitHub a fermé cette PR à la suppression de sa branche de base après la fusion de #50, et refuse de rebrancher une PR d'une pile.

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