Preuves Segur

Comment configurer la DevBox-sante MSS pour apporter les preuves SEGUR

Génération de preuves

Pour générer une preuve, il faut :

  1. configurer la DevBox-Sante MSS sur mailiz de formation via le fichier application.yml :

    devbox-sante:
      ms-sante:
        mailiz:
          servicesUrl: https://mss-msg-igcsante.formation.mssante.fr/mss-msg-services/services
          authenticationServiceUrl: https://mss-idp-igcsante.formation.mssante.fr/openam/SSOSoap/metaAlias/asip/idp
        igcsante:
          gammes: ELEMENTAIRE_ORGANISATIONS, ELEMENTAIRE_ORGANISATIONS_TEST
    
  2. configurer les logs de l’IGCSanteTrustoreManager en debug via le fichier application.yml

logging:
  level:
    fr.devboxsante.igsante: DEBUG # à minima
    fr.devboxsante: DEBUG # pour plus de traces
  1. activer les logs de debug SSL de la JVM : javax.net.debug=ssl:handshake

  2. lancer la DevBox-Sante MSS avec cette configuration. Exemple de ligne de commande depuis l’installation de la devbox-sante :

    cd "C:\Program Files\DevBoxSante"
    "jre\bin\java.exe" -Djavax.net.debug=ssl:handshake -Dspring.config.location=application.yml -jar "repository\devboxsante.jar"
    
  3. Une fois lancée, accéder à un endpoint /mssante pour générer les traces nécessaires comparable à celles-ci : all.log

    curl -X GET "http://localhost:9999/mssante/authentification/cps" -H "accept: */*"
    

Ces traces fournissent les preuves de la prise en compte des exigences [MSS1] (Référentiel socle MSSanté #2 -Clients de Messageries Sécurisées de Santé)

Remarque : Les preuves demandées nécessitent l’appel de l’url https://mss-msg-igcsante.formation.mssante.fr/mss-msg-services/services/Annuaire/soap/v1/listEmails qui correspond au endpoint /mssante/emails de la DevBox-santé.

Néanmoins pour que la DevBox-santé MSS se comporte normalement, il faut au préalable appeler un des endpoints d’authentification, c’est à dire /mssante/authentification/otp ou /mssante/authentification/cps

MSS 1 : trust IGCSante seulement

Un client de messagerie MSSanté doit établir une connexion TLS avec un Opérateur MSSanté, quels que soient les transactions et protocoles utilisés entre les 2 parties.

MSS 1.1 Étapes

  1. Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST

  2. Monter une connexion TLS depuis le logiciel via une requete HTTP GET sur l’URL https://mss-msg-igcsante.formation.mssante.fr/mss-msg-services/services/Annuaire/soap/v1/listEmails.

1.1.1 Preuve

Extrait de configuration TLS du client de messagerie.

La DevBox-sante a développé un IGCSanteTrustoreManager spécifique afin de prendre en compte les différentes IGC-Santé définies sur http://igc-sante.esante.gouv.fr/PC/ . Tous les composants DevBox-Sante comme la MSS peuvent être configurés de manière à accepter les certificats d’une ou plusieurs gammes. Comme par exemple, pour l’environnement de formation de Mailiz :

devbox-sante:
  ms-sante:
    igcsante:
      gammes: ELEMENTAIRE_ORGANISATIONS, ELEMENTAIRE_ORGANISATIONS_TEST

Le choix de cette gamme en configuration permet le téléchargement à la volée des certificat à ajouter au trust store lors de son lancement :

   public void loadCertificateAndCRLs() {
        gammeCertificats.stream().forEach(gammeCertificat -> {
            _loadCertificate(gammeCertificat);
            _loadCRL(gammeCertificat);
        });
    }

    @Scheduled(cron = "${devbox-sante.igc-sante.fetch.cron:0 0 */2 * * *}")
    public void scheduledLoadCertificateAndCRLs() {
        log.debug("scheduledLoadCertificateAndCRLs");
        loadCertificateAndCRLs();
    }

     private void _loadCertificate(IGCSanteGammeCertificat gammeCertificat) {
        String url = gammeCertificat.getCertificatUrl();
        log.info("Chargement du certificat {}", url);
        var certificate = certificateFetcher.getCertificate(url);
        if (certificate.isPresent()) {
            certificateMap.put(gammeCertificat, certificate.get());
        } else if (!certificateMap.containsKey(gammeCertificat)) {
           ...
        }

1.1.2 Preuve

Logs de la connexion TLS

Dans les logs (all.log) on peut s’intéresser à l’initialisation de l’IGCSanteTrustStoreManager :

2025-12-15T17:30:46.863+01:00  INFO 21976 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Initialisation du truststore
2025-12-15T17:30:46.865+01:00  INFO 21976 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Ajout du certificat ELEMENTAIRE_ORGANISATIONS au trustStore
2025-12-15T17:30:46.865+01:00  INFO 21976 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Chargement du certificat http://igc-sante.esante.gouv.fr/AC/ACI-EL-ORG.cer
2025-12-15T17:30:46.867+01:00 DEBUG 21976 --- [           main] f.d.igcsante.CertificateFetcher          : load http://igc-sante.esante.gouv.fr/AC/ACI-EL-ORG.cer

MSS 2 : TLSv1.2 uniquement

Conformément au référentiel socle MSSanté #2 (Clients de Messageries Sécurisées de Santé): Le client de messageries MSSanté du système doit supporter uniquement la version TLS 1.2 pour établir la connexion TLS avec l’Opérateur MSSanté, lors de la négociation TLS. (cf. RFC 2246 - http://tools.ietf.org/html/rfc2246). Dans le cas contraire, la connexion ne doit pas être établie.

MSS 2.1 Scenario

  1. Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST

  2. Monter une connexion TLS depuis le logiciel via une requete HTTP GET sur l’URL https://mss-msg-igcsante.formation.mssante.fr/mss-msg-services/services/Annuaire/soap/v1/listEmails.

MSS 2.1.1 Preuve

Extrait de configuration TLS du client de messagerie.

Réponse :

Nous utilisons une JVM en version 11 minimale. Lors de l’initialisation d’un contexte SSL via la JVM nous spécifions de manière statique le protocole TLSv1.2.

SSLContext sslContext = SSLContext.getInstance("TLSv1.2");

MSS 2.1.2 Preuve

Logs de connexion TLS

Dans les logs (all.log) on peut s’intéresser à juste après l’envoi de la requête :

2022-10-12 11:43:32.117  INFO 20756 --- [           main] o.a.c.services.AnnuaireService.REQ_OUT   : REQ_OUT
    Address: https://mss-msg-igcsante.formation.mssante.fr/mss-msg-services/services/Annuaire/soap/v1/listEmails
    HttpMethod: POST
   ...

le Handshake Message du client demande une TLSv1.2:

javax.net.ssl|DEBUG|10|main|2025-12-15 17:30:48.853 CET|ClientHello.java:638|Produced ClientHello handshake message (
"ClientHello": {
  "client version"      : "TLSv1.2",
  ...

et la réponse du serveur valide le protocole :

javax.net.ssl|DEBUG|10|main|2025-12-15 17:30:48.870 CET|SSLSocketInputRecord.java:247|READ: TLSv1.2 handshake, length = 89
javax.net.ssl|DEBUG|10|main|2025-12-15 17:30:48.870 CET|ServerHello.java:878|Consuming ServerHello handshake message (
"ServerHello": {
  "server version"      : "TLSv1.2",
  ...

MSS 3 : choix des cyphers

Conformément au référentiel socle MSSanté #2 (Clients de Messageries Sécurisées de Santé) [MSS1] : Le client de messageries MSSanté du système doit nécessairement utiliser l’une des suites de chiffrement suivantes, lors de la négociation TLS :

  • 0xC030: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • 0xC02F: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • 0xC028: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  • 0xC027: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA25

Dans le cas contraire, la connexion ne doit pas être établie.

MSS 3.1 Étapes

  1. Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST

  2. Monter une connexion TLS depuis le logiciel via une requete HTTP GET sur l’URL https://mss-msg-igcsante.formation.mssante.fr/mss-msg-services/services/Annuaire/soap/v1/listEmails.

MSS 3.1.1

Afin de forcer le choix des cyphers nous initialisons une MaillSSLSocketFactory java réduisant le choix des cipher suites par défaute de la JVM :

public abstract class IGCSanteSSLSocketFactory extends SSLSocketFactory {

   
   public static final String VERSION = "TLSv1.3";

  private static String CIPHER_SUITE = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "
      + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "
      + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 "
      + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 "
      + "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"
      + " TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";

   ...
   private void initSslSocketFactory() {
      props.put("mail.imap.ssl.ciphersuites", CIPHER_SUITE);
      props.put("mail.smtp.ssl.ciphersuites", CIPHER_SUITE);
      MailSSLSocketFactory sslSocketFactory = new MailSSLSocketFactory();
      return sslSocketFactory;
   } 
    

MSS 3.1.2

Dans les logs (all.log) on peut s’intéresser à juste après l’envoi de la requête :

2022-10-12 11:43:32.117  INFO 20756 --- [           main] o.a.c.services.AnnuaireService.REQ_OUT   : REQ_OUT
    Address: https://mss-msg-igcsante.formation.mssante.fr/mss-msg-services/services/Annuaire/soap/v1/listEmails
    HttpMethod: POST
   ...

le Handshake Message du client demande les cyphers suivants :

javax.net.ssl|DEBUG|01|main|2022-10-12 12:00:38.363 CEST|ClientHello.java:653|Produced ClientHello handshake message (
"ClientHello": {
  "client version"      : "TLSv1.2",
  ...
  "cipher suites"       : "[TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(0xC02C), TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256(0xC02B), TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(0xC030), TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(0xC02F), TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(0x009F), TLS_DHE_DSS_WITH_AES_256_GCM_SHA384(0x00A3), TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(0x009E), TLS_DHE_DSS_WITH_AES_128_GCM_SHA256(0x00A2), TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384(0xC024), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384(0xC028), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256(0xC023), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(0xC027), TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(0x006B), TLS_DHE_DSS_WITH_AES_256_CBC_SHA256(0x006A), TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(0x0067), TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(0x0040), TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384(0xC02E), TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384(0xC032), TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256(0xC02D), TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256(0xC031), TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384(0xC026), TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384(0xC02A), TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256(0xC025), TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256(0xC029), TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA(0xC00A), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA(0xC014), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(0xC009), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(0xC013), TLS_DHE_RSA_WITH_AES_256_CBC_SHA(0x0039), TLS_DHE_DSS_WITH_AES_256_CBC_SHA(0x0038), TLS_DHE_RSA_WITH_AES_128_CBC_SHA(0x0033), TLS_DHE_DSS_WITH_AES_128_CBC_SHA(0x0032), TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA(0xC005), TLS_ECDH_RSA_WITH_AES_256_CBC_SHA(0xC00F), TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA(0xC004), TLS_ECDH_RSA_WITH_AES_128_CBC_SHA(0xC00E), TLS_RSA_WITH_AES_256_GCM_SHA384(0x009D), TLS_RSA_WITH_AES_128_GCM_SHA256(0x009C), TLS_RSA_WITH_AES_256_CBC_SHA256(0x003D), TLS_RSA_WITH_AES_128_CBC_SHA256(0x003C), TLS_RSA_WITH_AES_256_CBC_SHA(0x0035), TLS_RSA_WITH_AES_128_CBC_SHA(0x002F), TLS_EMPTY_RENEGOTIATION_INFO_SCSV(0x00FF)]",
  ...
}
)

Le serveur choisit :

javax.net.ssl|DEBUG|01|main|2022-10-12 12:00:38.415 CEST|ServerHello.java:872|Consuming ServerHello handshake message (
"ServerHello": {
  "server version"      : "TLSv1.2",
  ...
  "cipher suite"        : "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(0xC030)",
}
)

MSS 4 : certificat IGC Santé

Les clients de messageries MSSanté du système doivent être en capacité d’établir une connexion TLS avec un Opérateur MSSanté présentant un certificat serveur de l’IGC Santé,conformément au référentiel socle MSSanté #2 (Clients de Messageries Sécurisées de Santé) [MSS1].

MSS 4.1 Étapes

  1. Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST

  2. Monter une connexion TLS depuis le logiciel via une requete HTTP GET sur l’URL https://mss-msg-igcsante.formation.mssante.fr/mss-msg-services/services/Annuaire/soap/v1/listEmails.

MSS 4.1.1

Extrait de configuration des AC supportées par le client de messagerie.

idem 1.1.1

MSS 5 : certificat Opérateur non expiré

Le client de messageries MSSanté du système DOIT vérifier que le certificat présenté par l’opérateur MSSanté n’est pas expiré, conformément au référentiel socle MSSanté #2 (Clients de Messageries Sécurisées de Santé) [MSS1].

MSS 5.1 Étapes

  1. Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST

  2. Monter une connexion TLS depuis le logiciel via une requete HTTP GET sur l’URL https://mss-msg-igcsante.formation.mssante.fr/mss-msg-services/services/Annuaire/soap/v1/listEmails.

MSS 5.1.1

Extrait de configuration qui permet de montrer que le client a bien configuré pour respecter cette exigence.

Pas de configuration ici, les traces parlent d’elles mêmes.

2025-12-15T18:03:53.302+01:00 DEBUG 44272 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Date de validité du certificat (CN=AC IGC-SANTE ELEMENTAIRE ORGANISATIONS, OU=IGC-SANTE, OU=0002 187512751, O=ASIP-SANTE, C=FR) est : Tue Jun 25 02:00:00 CEST 2013 - Fri Jun 24 02:00:00 CEST 2033
2025-12-15T18:03:53.302+01:00 DEBUG 44272 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Certificat (CN=AC IGC-SANTE ELEMENTAIRE ORGANISATIONS, OU=IGC-SANTE, OU=0002 187512751, O=ASIP-SANTE, C=FR) valide
2025-12-15T18:03:53.302+01:00  INFO 44272 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Ajout du certificat ELEMENTAIRE_ORGANISATIONS_TEST au trustStore
2025-12-15T18:03:53.302+01:00 DEBUG 44272 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Date de validité du certificat (CN=TEST AC IGC-SANTE ELEMENTAIRE ORGANISATIONS, OU=IGC-SANTE TEST, OU=0002 187512751, O=ASIP-SANTE, C=FR) est : Tue Jun 25 02:00:00 CEST 2013 - Fri Jun 24 02:00:00 CEST 2033
2025-12-15T18:03:53.302+01:00 DEBUG 44272 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Certificat (CN=TEST AC IGC-SANTE ELEMENTAIRE ORGANISATIONS, OU=IGC-SANTE TEST, OU=0002 187512751, O=ASIP-SANTE, C=FR) valide
javax.net.ssl|DEBUG|10|main|2025-12-15 18:03:53.308 CET|X509TrustManagerImpl.java:99|adding as trusted certificates (
  "certificate" : {
    "version"            : "v3",
    "serial number"      : "11:20:65:3a:6b:f4:ae:a5:cc:3d:38:fa:05:62:23:f5:ac:f1",
    "signature algorithm": "SHA256withRSA",
    "issuer"             : "CN=AC RACINE IGC-SANTE ELEMENTAIRE, OU=IGC-SANTE, OU=0002 187512751, O=ASIP-SANTE, C=FR",
    "not before"         : "2013-06-25 02:00:00.000 CEST",
    "not  after"         : "2033-06-24 02:00:00.000 CEST",
    "subject"            : "CN=AC IGC-SANTE ELEMENTAIRE ORGANISATIONS, OU=IGC-SANTE, OU=0002 187512751, O=ASIP-SANTE, C=FR",
    "subject public key" : "RSA",

Puis plus tard lors de la vérification du certificat présenté par le serveur :

javax.net.ssl|DEBUG|10|main|2025-12-15 18:03:54.266 CET|CertificateMessage.java:360|Consuming server Certificate handshake message (
"Certificates": [
  "certificate" : {
    "version"            : "v3",
    "serial number"      : "5f:82:12:a0:4a:51:d9:87:0e:cb:e8:74:91:de:d4:48",
    "signature algorithm": "SHA256withRSA",
    "issuer"             : "CN=AC IGC-SANTE ELEMENTAIRE ORGANISATIONS, OU=IGC-SANTE, OU=0002 187512751, O=ASIP-SANTE, C=FR",
    "not before"         : "2025-11-06 11:54:24.000 CET",
    "not  after"         : "2027-11-06 11:54:24.000 CET",
    "subject"            : "CN=mail-org-tests-editeur.espacedeconfiance.mssante.fr, OU=347976684200724, O=CAPGEMINI TECHNOLOGY SERVICES, ST=Hauts-de-Seine (92), C=FR",
...

2025-12-15T18:03:54.269+01:00 DEBUG 44272 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Date de validité du certificat (CN=mail-org-tests-editeur.espacedeconfiance.mssante.fr, OU=347976684200724, O=CAPGEMINI TECHNOLOGY SERVICES, ST=Hauts-de-Seine (92), C=FR) est : Thu Nov 06 11:54:24 CET 2025 - Sat Nov 06 11:54:24 CET 2027
2025-12-15T18:03:54.269+01:00 DEBUG 44272 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Certificat (CN=mail-org-tests-editeur.espacedeconfiance.mssante.fr, OU=347976684200724, O=CAPGEMINI TECHNOLOGY SERVICES, ST=Hauts-de-Seine (92), C=FR) valide

On voit que l’IGCSanteTrustoreManager vérifie la date d’expiration de la chaîne de certificats utilisée.

MSS 5.1.2

Si besoin, extrait du code qui vérifie la non expiration du certificat

Lors de l’initialisation d’une connexion et une fois le certificat validé par le truststore la date d’expiration du certificat présenté par l’opérateur MSS est vérifiée :

private void _checkExpirationDate(X509Certificate certificat) {
        log.debug("Date de validité du certificat ({}) est : {} - {}", certificat.getSubjectDN().toString(), certificat.getNotBefore(), certificat.getNotAfter());
        if (Instant.now().isAfter(certificat.getNotAfter().toInstant())) {
            throw new IGCSanteException(String.format("Le certificat (%s) est expiré. La date d'expiration est : %s",
                    certificat.getSubjectDN().toString(),
                    sdf.format(certificat.getNotAfter()))
            );
        }
        if (Instant.now().isBefore(certificat.getNotBefore().toInstant())) {
            throw new IGCSanteException(String.format("Le certificat (%s) n'est pas encore valide. La date de début est : %s",
                    certificat.getSubjectDN().toString(),
                    sdf.format(certificat.getNotBefore()))
            );
        }
        log.debug("Certificat ({}) valide", certificat.getSubjectDN().toString());

    }

MSS 6 : non révocation du certificat

Le client de messageries MSSanté du système doit vérifier que le certificat présenté par l’Opérateur MSSanté n’est pas révoqué au moyen des CRL ou d’un répondeur OCSP, et ce quelle que soit l’autorité de certification utilisée par un Opérateur MSSanté, conformément au référentiel socle MSSanté #2 (Clients de Messageries Sécurisées de Santé) [MSS1].

MSS 6.1 : Étapes

  1. Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST

  2. Monter une connexion TLS depuis le logiciel via une requête HTTP GET sur l’URL https://mss-msg-igcsante.formation.mssante.fr/mss-msg-services/services/Annuaire/soap/v1/listEmails.

MSS 6.1.1

Extrait de configuration qui permet de montrer que le client a bien configuré pour respecter cette exigence.

Lors du lancement de la JVM (version 11 minimal) du connecteur MSS un truststore est généré avec un sous ensemble de la gamme de certificats de l’AC définit à l’url suivante : http://igc-sante.esante.gouv.fr/PC/

Nous prenons en compte les CRL disponibles pour chaque certificat donné à cette même URL.

Les logs montrent cette prise en charge :

2025-12-15T17:30:46.863+01:00  INFO 21976 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Initialisation du truststore
2025-12-15T17:30:46.865+01:00  INFO 21976 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Ajout du certificat ELEMENTAIRE_ORGANISATIONS au trustStore
2025-12-15T17:30:46.865+01:00  INFO 21976 --- [           main] f.d.igcsante.IGCSanteTrustoreManager     : Chargement du certificat http://igc-sante.esante.gouv.fr/AC/ACI-EL-ORG.cer
2025-12-15T17:30:46.867+01:00 DEBUG 21976 --- [           main] f.d.igcsante.CertificateFetcher          : load http://igc-sante.esante.gouv.fr/AC/ACI-EL-ORG.cer

MSC 6.1.2

Si besoin, extrait du code qui vérifie la non révocation du certificat

L’IGCSanteTrustoreManager est codé pour vérifier les CRLs disponibles sur http://igc-sante.esante.gouv.fr/PC/, dont voici l’extrait de code (implémentation basé sur https://stackoverflow.com/questions/45460015/crl-check-in-java):

Le chargement des CRL est lancé toutes les 2 heures (délai configurable).

 public TrustManager[] getTrustManagers() {

        return new X509TrustManager[]{
            new X509TrustManager() {
             ...
                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String string) throws CertificateException {
                        getWrapped().checkServerTrusted(x509Certificates, string);
                }
...
                private X509TrustManager getWrapped() {
                    if (trustManagerFactory.getTrustManagers() == null || trustManagerFactory.getTrustManagers().length == 0) {
                        init(gammeCertificats);
                    }
                    return (X509TrustManager) trustManagerFactory.getTrustManagers()[0];
                }
            }
        };
    }


public final void init(List<IGCSanteGammeCertificat> gammeCertificats) {
    this.gammeCertificats = gammeCertificats;
    
        trustManagerFactory = TrustManagerFactory.getInstance(PKIX);
        ...
        _initCRLs(gammeCertificats);
        ...
}

 private Optional<ManagerFactoryParameters> _initCRLs(List<IGCSanteGammeCertificat> gammeCertificats) throws KeyStoreException, InvalidAlgorithmParameterException {
        if (gammeCertificats.isEmpty()) {
            log.warn("Aucune gamme IGCSanté définie.");
            return Optional.empty();
        }
        PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(trustStore, new X509CertSelector());
        List<CertStore> certStoreList = gammeCertificats.stream()
                .map(gammeCertificat -> certStoreMap.getOrDefault(gammeCertificat, null))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        if (!certStoreList.isEmpty()) {
            pkixParams.setCertStores(certStoreList);
            pkixParams.setRevocationEnabled(true);
            return Optional.of(new CertPathTrustManagerParameters(pkixParams));
        }
        log.warn("Aucune CRL des gammes IGCSanté n'ont pu être chargées.");
        return Optional.empty();
    }


    @Scheduled(cron = "${devbox-sante.igc-sante.fetch.cron:0 0 */2 * * *}")
    public void scheduledLoadCertificateAndCRLs() {
        log.debug("scheduledLoadCertificateAndCRLs");
        gammeCertificats.stream().forEach(gammeCertificat -> {
            _loadCertificate(gammeCertificat);
            _loadCRL(gammeCertificat);
        });
    }

  private void _loadCRL(IGCSanteGammeCertificat gammeCertificat) {
        String url = gammeCertificat.getCrlUrl();
        log.info("Chargement de la CRL {}", url);
        var certStore = certificateFetcher.getCrlStore(url);
        if (certStore.isPresent()) {
            certStoreMap.put(gammeCertificat, certStore.get());
        }
    }