Preuves Segur
Génération de preuves
Pour générer une preuve, il faut :
-
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
-
configurer les logs de l’
IGCSanteTrustoreManager
en debug via le fichierapplication.yml
logging:
level:
fr.devboxsante.igsante: DEBUG # à minima
fr.devboxsante: DEBUG # pour plus de traces
-
activer les logs de debug SSL de la JVM :
javax.net.debug=ssl:handshake
-
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"
-
Une fois lancée, accéder à un endpoint
/mssante
pour générer les traces nécessaires comparable à celles-ci : all.logcurl -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
-
Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST
-
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 :
for (IGCSanteGammeCertificat gammeCertificat : gammeCertificats) {
log.info("Ajout du certificat {} au trustStore", gammeCertificat.getCertificatUrl());
final X509Certificate certificat = _loadCertificate(gammeCertificat);
_checkExpirationDate(certificat);
trustStore.setCertificateEntry(gammeCertificat.getAlias(), certificat);
}
private X509Certificate _loadCertificate(IGCSanteGammeCertificat gammeCertificat) {
URLConnection urlConnection = HttpHelper.noCheckCertificateOpenConnection(url);
X509Certificate certificate = (X509Certificate) CertificateFactory.getInstance(X_509).generateCertificate(urlConnection.getInputStream());
if (certificate == null) {
certificate = (X509Certificate) CertificateFactory.getInstance(X_509).generateCertificate(this.getClass().getClassLoader().getResourceAsStream(gammeCertificat.getCertificateFilename()));
}
}
return certificate;
}
1.1.2 Preuve
Logs de la connexion TLS
Dans les logs (all.log) on peut s’intéresser à l’initialisation de l’IGCSanteTrustStoreManager
:
2022-10-12 12:00:29.519 INFO igcsante.IGCSanteTrustoreManager : Initialisation du truststore
2022-10-12 12:00:29.520 INFO igcsante.IGCSanteTrustoreManager : Ajout du certificat http://igc-sante.esante.gouv.fr/AC/ACI-EL-ORG.cer au trustStore
2022-10-12 12:00:30.357 INFO igcsante.IGCSanteTrustoreManager : Ajout du certificat http://igc-sante.esante.gouv.fr/AC%20TEST/ACI-EL-ORG-TEST.cer au trustStore
trustStore
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
-
Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST
-
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|01|main|2022-10-12 11:43:32.279 CEST|ClientHello.java:653|Produced ClientHello handshake message (
"ClientHello": {
"client version" : "TLSv1.2",
...
}
)
et la réponse du serveur valide le protocole :
javax.net.ssl|DEBUG|01|main|2022-10-12 11:43:32.337 CEST|ServerHello.java:872|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
-
Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST
-
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 avons introduit une nouvelle SSLSocketFactory
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.2";
protected abstract SSLSocketFactory getSocketFactory();
@Override
public String[] getDefaultCipherSuites() {
return new String[]{
"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"};
}
@Override
public String[] getSupportedCipherSuites() {
return getDefaultCipherSuites();
}
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
-
Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST
-
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
-
Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST
-
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.
A l’initialisation, l’IGCSanteTrustoreManager
vérifie que les certificats de confiance utilisés ne sont pas expirés.
private Optional<CertStore> _loadCRL(String url) {
URLConnection urlConnection = HttpHelper.noCheckCertificateOpenConnection(url);
InputStream is = urlConnection.getInputStream();
var crls = certificateFactory.generateCRLs(is);
var certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(crls));
certStoreMap.put(url, certStore);
is.close();
return Optional.of(certStore);
}
2022-10-12 12:00:29.519 INFO - igcsante.IGCSanteTrustoreManager : Initialisation du truststore
2022-10-12 12:00:29.520 INFO - igcsante.IGCSanteTrustoreManager : Ajout du certificat http://igc-sante.esante.gouv.fr/AC/ACI-EL-ORG.cer au trustStore
2022-10-12 12:00:30.357 DEBUG - igcsante.IGCSanteTrustoreManager : Date expiration du certificat (CN=AC IGC-SANTE ELEMENTAIRE ORGANISATIONS, OU=IGC-SANTE, OU=0002 187512751, O=ASIP-SANTE, C=FR) est : Fri Jun 24 02:00:00 CEST 2033
2022-10-12 12:00:30.357 INFO - igcsante.IGCSanteTrustoreManager : Ajout du certificat http://igc-sante.esante.gouv.fr/AC%20TEST/ACI-EL-ORG-TEST.cer au trustStore
2022-10-12 12:00:30.756 DEBUG - igcsante.IGCSanteTrustoreManager : Date expiration du certificat (CN=TEST AC IGC-SANTE ELEMENTAIRE ORGANISATIONS, OU=IGC-SANTE TEST, OU=0002 187512751, O=ASIP-SANTE, C=FR) est : Fri Jun 24 02:00:00 CEST 2033
Puis plus tard lors de la vérification du certificat présenté par le serveur :
javax.net.ssl|DEBUG|01|main|2022-10-12 12:00:40.074 CEST|CertificateMessage.java:366|Consuming server Certificate handshake message (
"Certificates": [
"certificate" : {
"version" : "v3",
"serial number" : "1D 5D E2 5E 3D C1 4B DE 21 0F 2C 0F 23 0E 86 52",
"signature algorithm": "SHA256withRSA",
"issuer" : "CN=TEST AC IGC-SANTE ELEMENTAIRE ORGANISATIONS, OU=IGC-SANTE TEST, OU=0002 187512751, O=ASIP-SANTE, C=FR",
"not before" : "2022-06-02 13:49:28.000 CEST",
"not after" : "2024-06-02 13:49:28.000 CEST",
...
]
)
2022-10-12 12:00:40.075 DEBUG 7092 --- [ main] f.d.igcsante.IGCSanteTrustoreManager : Date expiration du certificat (CN=mss-msg-igcsante.formation.mssante.fr, OU=300000000099622, O=GIP - TEST9962, ST=Paris (75), C=FR) est : Sun Jun 02 13:49:28 CEST 2024
2022-10-12 12:00:40.075 DEBUG 7092 --- [ main] f.d.igcsante.IGCSanteTrustoreManager : Date expiration du certificat (CN=TEST AC IGC-SANTE ELEMENTAIRE ORGANISATIONS, OU=IGC-SANTE TEST, OU=0002 187512751, O=ASIP-SANTE, C=FR) est : Fri Jun 24 02:00:00 CEST 2033
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 :
log.debug("Date expiration du certificat ({}) est : {}", certificat.getSubjectDN().toString(), certificat.getNotAfter());
if (Instant.now().isAfter(certificat.getNotAfter().toInstant())) {
throw new IGCSanteException(String.format("Le certificat (%s) est expiré. La date d'expiration est : " ,
certificat.getSubjectDN().toString(),
certificat.getNotAfter())
);
}
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
-
Vérifier que la configuration TLS du logiciel accepte les certificats serveurs IGC Santé de la branche de TEST
-
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 :
2022-10-12 12:00:30.758 - igcsante.IGCSanteTrustoreManager : Ajout de la CRL http://igc-sante.esante.gouv.fr/CRL/ACI-EL-ORG.crl au trustStore
2022-10-12 12:00:31.848 - igcsante.IGCSanteTrustoreManager : Ajout de la CRL http://igc-sante.esante.gouv.fr/CRL/ACI-EL-ORG-TEST.crl au trustStore
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):
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 void _initCRLs(List<IGCSanteGammeCertificat> gammeCertificats) throws KeyStoreException, InvalidAlgorithmParameterException {
PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(trustStore, new X509CertSelector());
for (IGCSanteGammeCertificat gammeCertificat : gammeCertificats) {
String crlUrl = gammeCertificat.getCrlUrl();
log.info("Ajout de la CRL {} au trustStore", crlUrl);
pkixParams.addCertStore(_loadCRL(crlUrl));
}
pkixParams.setRevocationEnabled(true);
ManagerFactoryParameters trustParams = new CertPathTrustManagerParameters(pkixParams);
...
trustManagerFactory.init(trustParams);
}
private Optional<CertStore> _loadCRL(String url) {
log.info("Chargement de la CRL {} dans un certStore", url);
try {
URLConnection urlConnection = HttpHelper.openConnection(url);
InputStream is = urlConnection.getInputStream();
var crls = certificateFactory.generateCRLs(is);
var certStore = CertStore.getInstance(
"Collection",
new CollectionCertStoreParameters(crls));
certStoreMap.put(url, certStore);
is.close();
return Optional.of(certStore);
} catch (IOException | CRLException | InvalidAlgorithmParameterException | NoSuchAlgorithmException e) {
// gestion d'erreur
}
}