Skip to content

feat(ca-server): lien interne (routes, mTLS) et enregistrement de clé des opérateurs - #19

Merged
PhilippeVienne merged 2 commits into
devfrom
feat/lien-interne-ca-server
Sep 21, 2026
Merged

PhilippeVienne merged 2 commits into
devfrom
feat/lien-interne-ca-server

Conversation

@PhilippeVienne

Copy link
Copy Markdown
Contributor

Contenu

Trois tranches de l'étape 0 du socle de confiance de la console (docs/WEBUI.md §15), livrées ensemble.

Routes internes (second port, désactivé par défaut : OPENEIDAS_INTERNAL_LISTEN)

  • POST /internal/v1/challenge et /internal/v1/actions : oe_actions::Service câblé sur le journal réel. L'exécution n'accepte aucun corps, seul celui figé à l'émission du challenge s'exécute.
  • POST /internal/v1/register/begin|finish : enregistrement de la clé avec le jeton d'invitation. L'invitation d'amorçage place la clé dans le registre ; toute autre la range dans pending_credentials (migration 0004, expiration 72 h).
  • Chargeur de la liste blanche de modèles de clés (OPENEIDAS_WEBAUTHN_MODELS_FILE).

mTLS du lien interne, terminé par ca-server (TLS 1.3 seul)

  • Profils internal_client (CN imposé ra-console) et internal_server (SAN repris du CN) : EKU unique et politique dédiée, contrôlés par oe-conformance sur le certificat réellement signé.
  • À chaque connexion, avant toute requête : EKU, politique, nom courant, présence dans certificates sous le bon profil, identique octet pour octet, non révoqué.
  • Sans TLS, le port interne reste limité à la boucle locale.
  • ca-server internal-cert server <dns> : clé logicielle (0600), demande, écriture du certificat après approbation.

oe-castore : ajout d'un build.rs. sqlx::migrate! n'est pas recompilé à l'ajout d'un fichier de migration : une nouvelle migration pouvait être absente du binaire selon l'état du cache (tests instables).

Points d'attention pour la relecture

  • OID de politique provisoires (1.3.6.1.4.1.0.1.1 et .2, sous le numéro d'entreprise 0 réservé) : 2.999 est refusé par const-oid. À remplacer par l'arc de l'association avant toute mise en production, dans oe_conformance::OID_POLICY_INTERNAL_*.
  • Le certificat du serveur n'est lu qu'au démarrage : le renouvellement (3 mois) est manuel pour l'instant.
  • Le CPS et la matrice de conformité ne sont volontairement pas modifiés (cf. TODO §5).

Vérifications

  • cargo fmt --check, cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace (avec PostgreSQL), cargo audit --ignore RUSTSEC-2023-0071 : verts.
  • Contrôle par mutation : chaque contrôle de sécurité retiré fait échouer le test visé (CN, structure et politique, statut de révocation, présence en table, deny_unknown_fields de l'exécution, administrateur actif, jeton à usage unique, aiguillage registre / clé en attente).
  • Essai réel avec SoftHSM, PostgreSQL et curl : le certificat ra-console atteint la route à travers le mTLS ; sans certificat, avec un certificat de serveur ou en HTTP clair, la connexion est refusée ; après ca-server revoke, elle est refusée avec le motif « certificat révoqué ».

… des opérateurs

Route interne, sur un second port désactivé par défaut
(OPENEIDAS_INTERNAL_LISTEN) :
- POST /internal/v1/challenge et /internal/v1/actions, câblées sur
  oe_actions::Service et le journal réel ; l'exécution n'accepte aucun
  corps, seul celui figé à l'émission du challenge s'exécute ;
- POST /internal/v1/register/begin et /finish : enregistrement de la clé
  avec le jeton d'invitation. L'invitation d'amorçage place la clé dans
  le registre, toute autre la range dans pending_credentials
  (migration 0004) en attente de confirmation ;
- chargeur de la liste blanche de modèles de clés
  (OPENEIDAS_WEBAUTHN_MODELS_FILE).

mTLS du lien interne, terminé par ca-server (TLS 1.3 seul) :
- profils internal_client (CN imposé ra-console) et internal_server (SAN
  repris du CN), EKU unique et politique dédiée, contrôlés par
  oe-conformance sur le certificat réellement signé ;
- à chaque connexion, avant toute requête : EKU, politique, nom courant,
  présence dans la table certificates sous le bon profil, identique octet
  pour octet, non révoqué ;
- sans TLS, le port interne reste limité à la boucle locale ;
- ca-server internal-cert server <dns> : clé logicielle (0600), demande
  et écriture du certificat après approbation.

Les OID de politique sont provisoires (sous le numéro d'entreprise 0) et
à remplacer par l'arc de l'association.

oe-castore : build.rs, car sqlx::migrate! n'est pas recompilé à l'ajout
d'un fichier de migration.
Comment thread bin/ca-server/src/main.rs Fixed
Comment thread bin/ca-server/src/main.rs Fixed
…ement

CodeQL signale trois « Cleartext logging of sensitive information » sur cette
PR : deux messages de ca-server operators internal-cert, et le message d'un
panic! de test d'oe-raflow. Ce sont des faux positifs (un certificat est une
donnée publique, l'identifiant de demande aussi), mais l'analyse de flux traite
comme sensible toute valeur qui dérive d'un SubmitResult, qui porte le
certificat, même pour un champ public.

- internal-cert n'affiche plus l'identifiant ni l'état de la demande : le
  chemin du certificat vient de la configuration, et l'opérateur retrouve la
  demande avec ca-server ra list PENDING ;
- le test d'oe-raflow n'affiche plus le résultat entier (un Ok porte le
  certificat émis), seulement s'il s'agit d'un succès ou de l'erreur.

Aucun changement de comportement.
@PhilippeVienne
PhilippeVienne merged commit fb1ea95 into dev Sep 21, 2026
15 checks passed
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.

2 participants