doc:access_distant

Accès distant à son instance MedShake EHR/EDC local

Comme indiqué explicitement sur la documentation officielle relative à la mise en production d'une instance MedShake EHR/EDC, celle-ci ne doit jamais être exposée tel quel aux réseaux ouverts comme Internet. À la base, elle ne doit être accessible que via un réseau privé comme le réseau local du professionnel de santé.

Ce document décrit des moyens permettant de fournir un accès distant (entendez par là un accès depuis un autre endroit que le réseau local) à son instance MedShake EHR/EDC hébergée dans le local du professionnel de santé en ajoutant une couche d'authentification supplémentaire pour les clients via l'utilisation de certifcat X.509.

Ce document ne décrit pas comment effectuer le NAT permettant de rediriger les connexions envoyées depuis son IP publique vers le serveur hébergeant l'instance MedShake EHR/EDC sur le réseau local. Pour cela, je vous redirige vers le documentation de votre “routeur box” ainsi que vers les nombreuses autres ressources traitant du sujet et disponibles sur le web.

Ici on part du principe que votre installation est conforme à celle décrite dans la documentation officielle et que par conséquent on dispose de l’environnement suivant :

  • Système d'exploitation Debian 11
  • Serveur web Apache2

Si ce n'est pas le cas, il vous faudra sûrement apporter des adaptations à la procédure selon votre environnement.

Au vu de la sensibilité des données médicales stockées par le logiciel MedShake EHR/EDC et du cadre légal relatif à leur traitement, veuillez bien considérer les avertissements suivants :

Hébergement de MedShake EHR/EDC hors des locaux du professionnel de santé

Les méthodes qui sont décrites ici ne sont pas censées être utilisées pour fournir un hébergement hors des locaux du professionnel de santé, par exemple en data center ou fournis par un prestataire quelconque sur ses propres serveurs, sauf si celui-ci est agréé ou certifié Hébergeur de Données de Santés (HDS).

Je vous renvoie à la partie 6 du RÉFÉRENTIEL RELATIF AUX TRAITEMENTS DE DONNÉES À CARACTÈRE PERSONNEL DESTINÉS À LA GESTION DES CABINETS MÉDICAUX ET PARAMÉDICAUX publié par la CNILL.

Ces méthodes n’ont été ni relus ni approuvés par le concepteur de la solution MedShake EHR/EDC (le Dr BOUTILLIER)

Dans tous les cas, toujours se fier à la documentation officielle, si à un moment elle contredit celle-ci, la documentation officielle fait autorité.

N'appliquez pas cette procédure si vous ne la comprenez pas !

Ces méthodes demandent certaines compétences techniques pour être comprises et réalisées. Si vous n'êtes pas en mesure d'en comprendre le contenu, ne vous lancez pas dedans seul. Mal réalisées, elles peuvent potentiellement occasionner une fuite des données de santé des patients.

Au pire, demandez conseil sur le forum.

L’objectif est d'ajouter une couche d'authentification supplémentaire afin de restreindre l'accès à l'instance MedSake EHR/EDC aux seuls clients explicitement identifiés et autorisés.

Pour cela nous allons nous appuyer sur la mise en place d'une Autorité de certification (CA) que nous utiliserons ensuite pour délivrer des certificats X.509 signés par celle-ci et qui seront ensuite utilisés pour authentifier chaque utilisateur accédant à l'instance MedShake EHR/EDC. Nous générerons aussi une liste de révocation de certificats (CRL) afin bloquer les accès aux clients présentant des certificats qui seraient révoqués pour diverses raisons.

Pour plus de simplicité, dans la suite du document nous ferons référence aux éléments évoqués dans le paragraphe précédent avec leur forme abrégée (celle qui est décrite entre parenthèses).

En gros on peut résumer cela avec le schéma suivant :

Instance MedShake EHR/EDCClientAutorité de certification (CA)Certificats clientListe de révocation (CRL)AccèsCertificat personnelAccès refusé :* si le certificat du client n'est pas signé par l'autorité de certification (CA)* si le certificat du client se trouve dans la liste de révocation (CRL)émet et signesignerévoqueobtientprésentevérifie si signé parvérifie si non révoqué

Globalement, il existe de nombreux de moyens d’implémenter le principe précédent. Ici, nous allons en décrire deux :

  • La vérification des certificats des clients directement avec Apache.
  • La vérification des certificats des clients par 'OpenVPN qui leur permettra ou non de se connecter à son Réseau privé virtuel (VPN). L'instance Medshake EHR/EDC ne sera alors accessible qu'au travers de celui-ci.

Dans les deux cas, il nous faudra disposer de notre CA. Il faut donc procéder en deux étapes :

  • Pour commencer, il faut mettre en place la CA et voir comment l'utiliser.
  • Puis configurer les restrictions d'accès à l’instance Medshake EHR/EDC selon la méthode choisie.

Avantages et inconvénients des différentes méthodes

Chacune de ces méthodes d'accès possède ces avantages et inconvénients.

Directement via Apache

Cette méthode est moins “étanche qu'avec OpenVPN” et nous oblige à exposer le serveur web directement à internet. Il faudra donc bien vérifier et tester la configuration Apache.

Par contre, la maintenance du système et les audits de sécurité seront plus simples, car nous avons un composant de moins à gérer (le serveur VPN). De plus, la mise en place côté client est aussi plus simple, car nous n'avons pas besoin d'ajouter et de configurer le client OpenVPN; fournir le certificat au navigateur web suffit.

Plutôt recommandé si nous avons une base d'utilisateurs nombreuse ou changeante.

Via OpenVPN

Cette méthode est plus “étanche” que l'authentification directe des certificats clients avec Apache. Elle permet d'isoler l'accès à l'instance MedShake EHR/EDC au seul réseau du VPN. De ce fait, on se retrouve dans des conditions similaires à celle de l'instance uniquement accessible sur le réseau local. De plus, nous n'avons pas besoin d'exposer le serveur web à l'internet, seul le serveur VPN a besoin de l'être.

En contrepartie, on ajoute un composant supplémentaire à surveiller et maintenir qu'il faudra prendre en compte dans les audits de sécurité. De plus, la mise en place côté client sera plus complexe, car il faudra aussi installer et configurer le client OpenVPN sur tous les postes utilisateurs (y compris sur les smartphones si on veut utiliser phonecapture).

Plutôt recommandé si nous avons une base d'utilisateurs peu nombreuse ou peu changeante.

Ici la CA est installée directement sur le serveur qui héberge l'instance MedShake EHR/EDC. Sauf mention contraire, toutes les commandes décrites dans cette partie doivent y être effectuées dans un Shell sur le serveur disposant des droits root.

Il faut aussi disposer d'un moyen de récupérer les certificats se trouvant sur le serveur afin de les placer sur les postes clients. Je recommande d'utiliser scp ou sftp pour cela, mais pas directement depuis les postes clients. L'administrateur utilise son accès sécurisé au serveur via ssh depuis son poste à lui pour récupérer les certificats directement sur son poste et les transmet ensuite par le moyen qui lui convient aux autres clients.

Afin de faciliter la gestion de notre CA nous allons utiliser l'utilitaire Easy-RSA. Il s'agit d'un ensemble de scripts servant de front-end à OpenSSL.

Pour commencer, nous devons installer l'utilitaire Easy-RSA. Sur la plupart des distributions majeures, il devrait être disponible via le gestionnaire de paquets. Sous Debian et dérivés nous pouvons l'installer avec la commande suivante :

apt install easy-rsa

Il faut un endroit pour y placer notre CA. Nous allons éviter de la placer quelque part dans le dossier /home/ ce qui peut, sous certaines conditions, poser des problèmes de droits d'accès. Les emplacements /srv/ ou /var/local/ sont de bons candidats. Ici la CA se trouvera dans /var/local/easyrsa/medshake/. Le paquet Debian easy-rsa nous fournit le script make-cadir pour nous aider à l'initialiser :

mkdir /var/local/easyrsa/
cd /var/local/easyrsa/
make-cadir medshake
cd ./medshake/

On va maintenant créer une configuration pour Easy-RSA spécifique à la CA. La commande make-cadir va créer un fichier vars dans l'emplacement où nous avons initialisé la CA. De base, le fichier contient beaucoup de commentaires très utiles. Cependant pour faciliter la compréhension des paramètres que nous allons modifier, nous le remplaçons par notre propre version :

mv ./vars ./vars.old
/var/local/easyrsa/medshake/vars
# Valeurs pour les champs émetteurs des certificats.
#
# Dans notre cas ces valeurs sont purement indicatives et leur contenu n'a pas
# trop d'importance. Modifiez-les à votre convenance.
 
# Pays de l'établissement émetteur
set_var EASYRSA_REQ_COUNTRY	"FR"
# Région ou département de l'établissement
set_var EASYRSA_REQ_PROVINCE	"Nord"
# Ville de l'établissement
set_var EASYRSA_REQ_CITY	"ROUBAIX"
# Nom de l'établissement
set_var EASYRSA_REQ_ORG		"Cabinet du Dr TOTO"
# Mail de l'adminsys
set_var EASYRSA_REQ_EMAIL	"admin@cabinet-toto.fr"
# Organisation interne
set_var EASYRSA_REQ_OU		"Medshake"
 
# Utilisation de ECDSA pour les certificats.
set_var EASYRSA_ALGO		ec
 
# Durée de validité du certificat de la CA en jours.
# Ici une durée de 10 ans.
# 
# /!\ passé cette date un nouveau certificat devra être créé pour la CA
#     (l'ancien ne sera plus valide). Comme tous les certificats émis pour
#     identifier les clients sont signés par celui-ci, il faudra en même
#     temps tous les renouveler ou les remplacer.
set_var EASYRSA_CA_EXPIRE	3650
 
# Durée de validité des certificats signés par la CA en jours.
# Ici 1 an.
# /!\ les utilisateurs avec un certificat expiré ne pourront plus accéder à
#     l'instance MedShake EHR/EDC. Il ne faut donc pas oublier de les
#     renouveler régulièrement.
set_var EASYRSA_CERT_EXPIRE	365
 
# À partir de combien de jours avant son expiration peut-on renouveler
# le certificat.
set_var EASYRSA_CERT_RENEW	30

Le script make-cadir va nous créer dans /var/local/easyrsa/medshake/ un fichier easyrsa. Il s’agit en fait d'un lien symbolique vers /usr/share/easy-rsa/easyrsa. Dans la suite du document nous appellerons la commande easyrsa depuis le dossier courant en la préfixant d'un ./ (./easyrsa).

L’étape suivante a pour but d'initialiser l'arborescence qui contiendra toutes nos clés et certificats.

./easyrsa init-pki

Puis on va créer le certificat et la clé privée associée pour la CA. Un mot de passe va être demandé pour protéger la clé privée de la CA. Attention à celui-ci, cette clé sera utilisée pour signer les certificats émis par la CA ainsi que la CRL, sans lui vous ne pourrez plus émettre, renouveler ou révoquer les certificats.

./easyrsa build-ca

Il faut aussi créer le fichier pour la CRL avec la commande easyrsa gen-crls même si nous n'avons aucune révocation de certificat pour le moment. Vu que nous préciserons son emplacement plus loin dans la configuration de nos services et pour éviter tout problème lors de leur démarrage, le fichier pour la CRL doit exister en amonts.La commande demandera la saisie du mot de passe de la clé privée de la CA qui a été fourni à l'étape build-ca.

./easyrsa gen-crl

À partir ce moment notre CA est prête à l'utilisation.

Ici, nous utiliserons la commande easyrsa sign-req qui sert à créer et signer le certificat client.

La commande demande un mot de passe, il s'agit de celui de la clé privée de la CA.

Les exemples de commande ci-dessous sont à exécuter dans le dossier où nous avons initialisé la CA (/var/local/easyrsa/medshake/). La commande ./easyrsa lui est relative.

Certificats serveur

La création de certificats destinés à être utilisés côté serveur est similaire à celle des certificats clients avec une petite subtilité. Ces certificats peuvent être utilisés par nos services (Apache ou OpenVPN) pour implémenter TLS et prouver au client leur authenticité en présentant aussi un certificat signé par la CA que le client pourra vérifier. Ici on crée un certificat que l'on nome “medsahke” et qui pourra être utilisé au choix par OpenVPN ou Apache.

Cela se fait en deux opérations :

On commence par créer une Demande de signature de certificat (CSR) en utilisant la commande easyrsa gen-req. Cette opération se charge aussi de la création de la clé privée associée. Nous allons lui passer deux arguments :

  • medshake qui est le nom du certificat (vous pouvez le nommer comme vous voulez).
  • nopass, car nous ne voulons pas que la clé privée du serveur soit protégée par mot de passe (sans cela il nous faudrait le ressaisir à chaque fois que le service utilisant le certificat démarre).
./easyrsa gen-req medshake nopass

Puis on crée le certificat en tant que tel avec la commande easyrsa sign-req. Là encore on lui ajoute des arguments :

  • serveur pour préciser que nous voulons créer un certificat destiné à être utilisé par un serveur.
  • medshake pour préciser le nom du certificat que l'on veut signer (donc celui fourni à la création de la CSR).

À la signature du certificat, Easy-RSA va demander de fournir un “Common Name” pour le certificat serveur. Donnez-lui le domaine qui sera utilisé pour contacter le serveur (ce qui sera fourni dans la configuration Apache pour la directive ServerName). Ceci permettra d'éviter les alertes du navigateur web quand le serveur présente un certificat qui ne correspond pas au domaine utilisé (quant à la vérification de la signature du certificat fourni par le serveur web, nous fournirons le certificat la CA aux navigateurs).

On passe aussi le paramètre –days=1095 à easyrsa qui sert à préciser la durée de validité du certificat en jours. Ceci surcharge la valeur d'un an configuré dans le fichier vars via la variable EASYRSA_CERT_EXPIRE. Ainsi nous aurons besoin de renouveler notre certificat serveur moins souvent que celui des clients.

./easyrsa --days=1095 sign-req server medshake

Certificat client

Création

Comme un certificat serveur, la création d'un certificat client se déroule en deux étapes :

  • L'émission de la CSR avec easyrsa gen-req.
  • La création du certificat signé par la CA avec easyrsa sign-req.

On ajoute aussi une troisième étape : la création d'un fichier PKSC12 qui permet de distribuer le certificat de la CA, le certificat du client et sa clé privée via un seul et même fichier qui sera chiffré et protégé par mot de passe avec la commande easyrsa export-p12.

Commençons par l'émission de la CSR qui va aussi au passage créer la clé privée du client. Nous passons deux paramètres à easyrsa gen-req :

  • Dr_TOTO qui sera le nom du certificat de notre client pour cet exemple. je vous recommande de nommer vos certificats clients de manière explicite afin d'identifier facilement quel certificat appartient à quel utilisateur.
  • nopass pour ne pas protéger par mot de passe la clé privée du client. Normalement il ne faudrait pas distribuer une clé privée en clair, mais ici nous distribuerons nos certificats sous forme de fichier PKCS12 qui s’occupera du chiffrement de la clé privée. Par contre, si vous n'utilisez pas PKCS12 n'utilisez pas non plus le paramètre nopass.
./easyrsa gen-req Dr_TOTO nopass

Puis il ne reste plus qu'à générer le certificat avec easyrsa sign-req et les deux paramètres suivants :

  • client pour préciser que nous voulons créer un certificat destiné à être utilisé par un serveur.
  • Dr_TOTO qui le nom de la CSR créée précédemment.
./easyrsa sign-req client Dr_TOTO

Pour finir, créons le fichier PKCS12 avec easyrsa export-p12.

La commande demande un mot de passe, il est utilisé pour protéger le contenu du fichier. Il devra être communiqué à l'utilisateur final pour qu'il puisse accéder aux contenus du fichier PKCS12.

Un mot de passe trop faible et/ou communiqué via un canal non sûr peut compromettre le certificat et sa clé privée ce qui peut déboucher sur des accès non autorisés à l'instance MedShake EHR/EDC.

./easyrsa export-p12 Dr_TOTO
Renouvellement

Tout certificat possède une date d'expiration. Un certificat périmé ne sera plus accepté par le serveur pour authentifier le client. C'est pour cela qu'il sera nécessaire de renouveler régulièrement les certificats des clients. Pour renouveler un certificat, on utilise la commande easyrsa renew.

Si on veut renouveler le certificat Dr_TOTO il faut faire :

./easyrsa renew Dr_TOTO

Attention la commande easyrsa renew possède un problème :

Comme d'habitude, la commande demande d'entrer le mot de passe de la clé privée de la CA pour signer le nouveau certificat. Cependant, elle va déplacer l'ancien certificat avant la confirmation que le mot de passe saisi est correct. Du coup si on saisit un mauvais mot de passe il faudra aller rechercher l'ancien certificat dans ./pki/renewed/certs_by_serial/ (utiliser openssl x509 -noout -subject -in pki/renewed/certs_by_serial/XXXXXXXX.crt pour identifier le certificat) et le replacer dans dans ./pki/issued/ en lui redonnant son nom d'origine (il faudra aussi récupérer la requête dans /pki/renewed/reqs_by_serial/).

Ne pas oublier de réexporter le tout dans un nouveau fichier PKCK12 avec easyrsa export-p12 et remplacer les anciens sur les postes client par le nouveau.

Révocation

Si le certificat d'un client se trouve compromis il peut autoriser des accès à l'instance MedShake EHR/EDC à des clients qui ne le devraient pas. Dans ce cas, il faut pouvoir indiquer au serveur qu'il doit désormais refuser les accès aux clients qui le présentent.

La première étape est d'utiliser easyrsa revoke avec deux paramètres :

  • Dr_TOTO : le nom du certificat que nous voulons révoquer.
  • keyCompromise : précise la raison de la révocation (ici la clé est compromise)
./easyrsa revoke Dr_TOTO keyCompromise

La commande easyrsa revoke retire le certificat et sa clé privée des dossiers ./pki/issued/ et ./pki/private/ et les place dans le dossier ./pki/revoked/.

Une fois fait, il nous faut régénérer la CRL pour y inclure la nouvelle révocation avec easyrsq gen-crl :

./easyrsa gen-crl

Par défaut Easy-RSA place tous les fichiers dans un sous dossier ./pki/. Ici tout sera donc dans le dossier /var/local/easyrsa/medshake/pki/.

On ne va par décrire ici le contenu de tout le dossier, mais seulement les éléments qui nous intéressent. Ici le dossier ./pki/ doit contenir les éléments suivants :

pkica.crt: certificat de la CA, permet de vérifier l'authenticité des certificats clients et serveurscrl.crt: liste des certificats révoqués, contient une liste signée par la CA de certificats compromis dont l’utilisation ne doit plus être autoriséeissuedmedshake.crt: certificat pour le serveurDr_TOTO.crt: certificat pour le client Dr_TOTOprivatemedshake.key: clé privée pour le serveurDr_TOTO.key: clé privée pour le clientDr_TOTO.p12: fichier PKSC12 pour le client Dr_TOTO (contient le certificat CA, le certificat client et sa clé privée)

Les clients devront récupérer leur fichier PKCS12. Le dossier ./pki/ n'est accessible que par le propriétaire, donc dans notre cas que par root, ce qui peut poser problème pour récupérer les éléments qui s'y trouvent afin de les transférer sur les postes clients. Si on veut récupérer les éléments via scp ou sftp et que nous nous connectons au serveur via un compte non privilégié il faudra faire une copie des fichiers PKCS12 dans un endroit qui lui sera lisible et changer les droits de lecture sur le ficher PKCS12 (qui sera aussi uniquement lisible par root).

Cette partie décrit comment filtrer les accès à l'instance Medshake EHR/EDC en utilisant les certificats produits par la CA directement avec Apache.

Attention : on suppose aussi qu'aucun autre point de votre configuration Apache ne permet l'accès à l'instance MedShake EHR/EDC. Dans le cas contraire des clients sans certificat pourraient y accéder.

Il faut modifier la configuration Apache relative à l'instance Medshake EHR/EDC, voici à quoi elle doit ressembler :

/etc/apache/sites-available/medshake.conf
# Redirige automatiquement tout le trafic http vers https
# (Ne pas autoriser le trafic en claire)
<VirtualHost *:80>
    # Remplacer "mon-medshake.fr" par le domaine utilisé
    ServerName        mon-medsahke.fr
    ServerAdmin	      admin@mon-medshake.fr
    RedirectMatch     permanent ^(.*)$ https://mon-medshake.fr$1
</VirtualHost>
 
# Trafic https
<VirtualHost *:443>
    # Remplacer "mon-medshake.fr" par le domaine utilisé
    ServerName          mon-medshake.fr
    ServerAdmin		admin@mon-medshake.fr
 
    #
    # Configuration SSL
    #
 
    # Charge le Module SSL
    SSLEngine On
 
    # Certificat et clé créés par la pki pour le serveur.
    # Le certificat ayant été signé par la CA, les clients pourront aussi 
    # authentifier le serveur.
    SSLCertificateFile /var/local/easyrsa/medshake/pki/issued/medshake.crt
    SSLCertificateKeyFile /var/local/easyrsa/medshake/pki/private/medshake.key
    # Certificat de la CA. Nécessaire pour vérifier l'authenticité des certificats 
    # des clients.
    SSLCACertificateFile /var/local/easyrsa/medshake/pki/ca.crt
    # Liste des certificats révoqués, permet de refuser l'accès aux certificats 
    # déclarés comme compromis.
    SSLCARevocationFile /var/local/easyrsa/medshake/pki/crl.pem
    # Active la vérification des certificats clients optionnels (certains clients
    # du réseau local peuvent se connecter sans certificat pour utiliser des fonctionnalités 
    # comme phonecapture)
    SSLVerifyClient optional
    # Limite la vérification aux certificats du client.
    # (inutile ici de contrôler toute la chaîne on n'a qu'un niveau)
    SSLVerifyDepth 1
    # Sécurité renforcée, nous n'utiliserons que la version la plus récente de TLS
    # (rejette d'office les clients non suffisamment à jour)
    SSLProtocol -all +TLSv1.3
    # Ajoute l'entête http pour le HSTS
    Header always set Strict-Transport-Security "max-age=0; includeSubDomains"
 
    # Emplacement des fichiers html public de l'instance MedShake EHR/EDC 
    DocumentRoot /var/www/medshake/EHR/public_html/
    DirectoryIndex index.php
 
    # Fichier de log dédié avec un format compatible avec le lecteur de log intégré 
    # à Medshake
    CookieName apacheLogUserID
    # /!\ le domaine doit être préfixé d'un point
    CookieDomain .mon-medshake.fr
    Define MEDSHAKEEHRLOGFILE /var/log/apache2/access_medshake.log
    SetEnv MEDSHAKEEHRLOGFILE ${MEDSHAKEEHRLOGFILE}
    LogFormat "%{%Y-%m-%d %H:%M:%S}t %{c}a %r %{Cookie}n" usertrack
    SetEnvIf Request_URI "\.png$|\.gif$|\.jpg$|\.svg$|\.js$|\.css$|\.map$|\.ico$|\.woff2" do_not_log
    CustomLog ${MEDSHAKEEHRLOGFILE} usertrack env=!do_not_log
 
    # Des règles de réécriture d'urls sont nécessaires(voir le public_html/.htaccess)
    # On s'assure que le module est bien chargé
    RewriteEngine On
 
    # Grâce à "Require expr %{SSL_CLIENT_VERIFY} == 'SUCCESS" l'accès au fichier
    # de ce dossier n'est permis qu'aux clients disposant
    # d'un certificat signé par la CA et en cours de validité
    <Directory /var/www/medshake/>
        SetEnv MEDSHAKEEHRPATH /var/www/medshake/EHR/
        Require expr %{SSL_CLIENT_VERIFY} == 'SUCCESS'
        Options FollowSymLinks
        AllowOverride all
    </Directory>
 
    # Accès aux url commençant par /phonecapture/ et /pubic/ autorisé pour les 
    # clients du réseau local sans présenter ce certificat valide
    <Location ~ /(phonecapture|public)/>
        # /!\ Replacer l'addresse ci-dessous par celle de votre réseau local
        Require ip 192.168.1.0/24
        # client de partout avec un certificat valide
	Require expr %{SSL_CLIENT_VERIFY} == 'SUCCESS'
    </Location>
 
    # Autorise l'accès aux assets (js, css et images) et pages de maintenance 
    # autorisés pour les clients du réseau local sans présenter ce certificat valide
    <Location ~ /(components/|thirdparty/|scss/|img/|js/|favicon.ico|maintenancePublic.html|maintenance.html)>
        # Ces ressources peuvent êtres mise en cache
        Header setifempty Cache-Control "must-revalidate"
        # Fixe un bug présent dans le version de apache utilisé dans Debian 10(2.4.38)
        # qui gènère une entête http Etag mal formé et empêche un retour 304
        # quand la ressource est en cache.
        # voir https://bz.apache.org/bugzilla/show_bug.cgi?id=45023#c22
        RequestHeader edit "If-None-Match" '^"((.*)-gzip)"$' '"$1", "$2"'
        Require ip 192.168.1.0/24
        # client de partout avec un certificat valide
        Require expr %{SSL_CLIENT_VERIFY} == 'SUCCESS'
     </Location>
 
     # Bloque les accès aux fichiers composer (juste c'est plus propre)
     <Location ~ /composer.(json|lock)>
         Require all denied
     </Location>
</VirtualHost>

N'oubliez pas d'activer la nouvelle config Apache :

a2ensite medshake.conf
apache2ctl graceful

Attention en cas d'utilisation de php-fpm avec Apache via le module proxy_fcgi_module :

La directive Apache <Directoty> ne contrôle pas les accès aux fichiers lors de l'utilisation de “proxy”. Dans ce cas, placer la directive 'Require ssl-verify-client' à l'intérieur d'un bloc <location /></location> (attention cette technique pose des soucis au niveau des navigateurs web avec TLS 1.3 voir ici), ou bien en la plaçant directement à l’intérieur du bloc <VirtualHost></VirtualHost>.

Les utilisateurs de l'instance Medshake EHR/EDC doivent d’abord récupérer le fichier PKCS12 (extension .p12) qui leur a été créé (Ne pas utiliser un même PKCS12 pour plusieurs utilisateurs : un PKCS12 = un utilisateur). Puis il suffit de le charger dans leur navigateur web (le moyen de le faire change selon le navigateur utilisé, consulter la documentation relative). Pour lire le fichier il faudra fournir le mot de passe saisi à la création, bien sûr il ne fauda pas le communiquer par un canal non sûr comme par courriel.

Le PKCS12 devra aussi être installé sur le smartphone si on veut utiliser des fonctionnalités comme phonecapture ou simplement accéder l'instance via celui-ci.

Si vous voulez utiliser le certificat de la CA pour authentifier le certificat du serveur il faudra dans la liste des autorités de certification de votre navigateur web autoriser le certificat de la CA à identifier des sites web (avec Firefox le bouton Modifier la confiance). Sinon vous aurez le message comme quoi le navigateur ne peut vérifier l'authenticité du certificat serveur.

Cette partie est à effectuer sur le serveur qui héberge votre instance MedShake EHR/EDC en tant qu'utilisateur root.

Configuration OpenVPN

Il nous faut disposer du logiciel OpenVPN. Sous Debian et dérivés il s'installe avec le paquet openvpn.

apt install openvpn

OpenVPN dispose d'un système d'authentification HMAC qui en gros permet de signer les paquets lors de l'établissement d'une connexion et de renforcer la protection contre certains types d’attaques comme les attaques DoS. Nous allons créer une clé spéciale à cet effet grâce à la commande openvpn –genkey –secret <keyname>. Elle doit rester secrète au maximum c'est pour cela qu'à sa création elle n'est lisible et inscriptible que par le propriétaire (mode 600).

openvpn --genkey --secret /etc/openvpn/medshake-ta.key

Pour une meilleure sécurité, nous allons aussi créer un dossier dans lequel OpenVPN pourra chrooté une fois démarré :

mkdir -p /var/local/openvpn/chroot/medshake/tmp/

Il faut aussi que le service puisse accéder à la CRL pour vérifier la validité des certificats des clients, or la CRL doit être lisible par le service une fois que ce dernier est chrooté. De plus, le service ne tournera pas non plus avec les droits root, il faut donc que la CRL soit lisible par tout le monde. Nous ferons donc ceci :

cp /var/local/easyrsa/medshake/pki/crl.pem /var/local/openvpn/chroot/medshake/ 
chmod 644 /var/local/openvpn/chroot/medshake/crl.pem

Vu que nous faisons une copie de la CRL il faudra bien penser à actualiser la copie à chaque modification de la CRL originale. Il faut aussi que la copie soit lisible par tous, car le service une fois lancé tournera avec les droits d'un utilisateur non privilégié et que par défaut le fichier CRL n'est lisible que par son propriétaire (ici root). Le fait d'avoir la CRL lisible par tous n'est pas un problème, car le fichier n'est pas du tout sensible et peut même être publiquement distribué.

Passons maintenant à la configuration du serveur OpenVPN elle-même. Sous Debian et dérivés on dispose d'emplacements dédiés pour y placer nos configurations OpenVPN client et serveur, plusieurs peuvent fonctionner en parallèle et elles se lancent toutes avec une unité systemd dédiée. Plaçons notre configuration pour MedShake EHR/EDC dans /etc/openvpn/server/medshake.conf :

/etc/openvpn/server/medshake.conf
# Le processus serveur fonctionne avec des groupes et utilisateurs aux droits limités
user nobody
group nogroup
 
# Niveau de verbosité du service
verb 3
 
#
# Configuration du tunnel
#
proto udp
dev tun
# Par défaut c'est le port 1194 qui est utilisé.
# Le modifier au besoin.
#port 1194
# Compression lz4. Peut être remplacé par lzo
# mais doit être indiqué sur la configuration
# cliente
compress lz4
# Permet d'adapter les paquets TCP au transit au
# travers du tunnel
mssfix
fragment 1300
# Pas besoin d'appeler de script utilisateur
script-security 1
# Emplacement dans lequel le service sera chrooté
# après initialisation.
chroot /var/local/openvpn/chroot/medshake/
# Emplacement de fichier temporaire utilisé par
# par le service. Relatif au chroot.
tmp-dir tmp/
 
# Ne pas relire les fichiers clés, ni fermer le périphérique tun
# à la réception d'un signal de relecture de configuration.
# Nécessaire, car le service fonctionnera avec un utilisateur
# non privilégié une fois lancé.
persist-tun
persist-key
 
#
# Mode server
# Type sous réseau 10.32.64.0/24
# le serveur prendra l'IP 10.32.64.1
#
 
server 10.32.64.0 255.255.255.0
topology subnet
 
#
# Configuration du TLS
#
tls-server
# Uniquement la version la plus récente de TLS
# (tant pis pour les clients obsolètes)
tls-version-min 1.3
# Vu que nous utilisons TLS 1.3 et des certificats ECDSA 
# nous n'utiliserons pas de paramètre Diffie Hellman
dh none
# Certficat de la CA
ca   /var/local/easyrsa/pki/ca.crt
# Certficat du serveur
cert /var/local/easyrsa/medshake/pki/issued/medshake.crt
# Clé privée du serveur
key  /var/local/easyrsa/medshake/pki/private/medshake.key
# Fichier pour la CRL
# (l'emplacement du fichier est relatif à celui du chroot définit plus bas)
crl-verify crl.pem
# Seuls les clients possédant un certificat valide peuvent accéder au VPN
verify-client-cert require
# Emplacement de la clé pour l'authentification HMAC.
# Possède un sens d'utilisation indiqué à la fin de la ligne.
# Ici sur le serveur on a mis '0' donc sur les clients ils seront à '1'
tls-auth /etc/openvpn/medshake-ta.key 0
 
#
# Ping les clients toutes les 10 secondes
# et ferme la connexion si le client ne donne pas
# de nouvelles au bout de 60 secondes.
keepalive 10 60
# Autorise les clients à changer d'IP et de port durant la connexion
float

Pour démarrer le serveur on précise l'unité systemd qui utilisera notre fichier de configuration (@medshake) :

systemctl start openvpn-server@medshake.service 

On vérifie que le service est bien démarré :

systemctl status openvpn-server@medshake.service 

Et si c'est le cas, on l'active pour qu'il se lance à chaque démarrage :

systemctl enable openvpn-server@medshake.service 

Configuration Apache

Il faut aussi modifier la configuration Apache pour faire en sorte que l’instance MedShake EHR/EDC ne soit accessible qu'au travers de notre réseau VPN. Pour cela nous pouvons :

  • Limiter l'écoute du VirtualHost sur l'adresse du serveur à l’intérieur du réseau VPN (10.32.64.1).
  • Ajouter une directive Require IP 10.32.64.0/24 à l’intérieur du bloc <Directroy /var/www/medshake/public_html>.

Voici à quoi ressemble la configuration Apache modifié :

/etc/apache/sites-available/medshake.conf
# Redirige automatiquement tout le trafic http vers https
# (Ne pas autoriser le trafic en claire)
<VirtualHost *:80>
    # Remplacer "mon-medshake.fr" par le domaine utilisé
    ServerName        mon-medsahke.fr
    ServerAdmin	      admin@mon-medshake.fr
    RedirectMatch     permanent ^(.*)$ https://mon-medshake.fr$1
</VirtualHost>
 
<VirtualHost *:443>
 
    ServerAdmin		admin@mon-medshake.fr
 
    # Même si la connexion à l'instance ne se fait qu'au travers du VPN
    # il faut continuer d'utiliser https car certaines fonctionnalités
    # comme l'utilisation de la caméra par le navigateur web (utilisé
    # par "Phonecapture") ne fonctionneront pas sur via http (mesure
    # de sécurité implémentée dans les navigateurs web).
    SSLEngine On
    # Cet exemple utilise le certificat bidon fourni par le paquet
    # "ca-certificates" un certificat généré par Easy-RSA peut
    # avantageusement le remplacer
    SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
    SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
 
    # Emplacement des fichier html public de l'installation MedShake EHR/EDC 
    DocumentRoot /var/www/medshake/EHR/public_html/
    DirectoryIndex index.php
 
    # Fichier de log dédié avec un format compatible avec le lecteur de log intégré 
    # à Medshake
    CookieName apacheLogUserID
    # /!\ le domaine doit être préfixé d'un point
    CookieDomain .mon-medshake.fr
    Define MEDSHAKEEHRLOGFILE /var/log/apache2/access_medshake.log
    SetEnv MEDSHAKEEHRLOGFILE ${MEDSHAKEEHRLOGFILE}
    LogFormat "%{%Y-%m-%d %H:%M:%S}t %{c}a %r %{Cookie}n" usertrack
    SetEnvIf Request_URI "\.png$|\.gif$|\.jpg$|\.svg$|\.js$|\.css$|\.map$|\.ico$|\.woff2" do_not_log
    CustomLog ${MEDSHAKEEHRLOGFILE} usertrack env=!do_not_log
 
    # Des règles de réécriture d'urls sont nécessaires(voir le public_html/.htaccess)
    # On s'assure que le module est bien chargé
    RewriteEngine On
 
    # N'autorise que le membre du réseau du VPN à accéder aux fichiers se trouvant 
    # dans ce dossier
    <Directory /var/www/medshake/>
        SetEnv MEDSHAKEEHRPATH /var/www/medshake/EHR/
        Require IP 10.32.64.0/24
        Options FollowSymLinks
        AllowOverride all
    </Directory>
 
    # Accès aux url commençant par /phonecapture/ et /pubic/ autorisé aussi pour les
    # clients du réseau local (utilisation phone capture et signature des documents)
    <Location ~ /(phonecapture|public)/>
        # /!\ Replacer l'addresse ci-dessous par celle de votre réseau local
        Require ip 192.168.1.0/24
        Require IP 10.32.64.0/24
    </Location>
 
    # Autorise l'accès aux assets (js, css et images) et pages de maintenance 
    # autorisés aussi pour les clients du réseau local
    <Location ~ /(components/|thirdparty/|scss/|img/|js/|favicon.ico|maintenancePublic.html|maintenance.html)>
        # Ces ressources peuvent êtres mises en cache
        Header setifempty Cache-Control "must-revalidate"
        # Fixe un bug présent dans le version de apache utilisé dans Debian 10(2.4.38)
        # qui gènère une entête http Etag mal formée et empéche un retour 304
        # quand la ressource est en cache.
        # voir https://bz.apache.org/bugzilla/show_bug.cgi?id=45023#c22
        RequestHeader edit "If-None-Match" '^"((.*)-gzip)"$' '"$1", "$2"'
        Require ip 192.168.1.0/24
        Require IP 10.32.64.0/24
     </Location>
 
     # Bloque les accès aux fichiers composer (juste c'est plus propre)
     <Location ~ /composer.(json|lock)>
         Require all denied
     </Location>
</VirtualHost>

N'oubliez pas d'activer la nouvelle config Apache :

a2ensite medshake.conf
apache2ctl graceful

On notera aussi que notre bloc <VirtualHost *:443> ne contient pas de directive ServerName, c'est voulu. Nous ne contacterons pas notre instance MedShake EHR/EDC via un nom de domaine, mais directement via l'IP du serveur à l’intérieur du VPN (10.32.64.1) et ceci pour éviter des problèmes de résolution DNS au niveau des clients. Si nous ne le faisons pas il faudra au choix modifier le fichier hosts sur chaque client pour faire correspondre le domaine utilisé avec l'IP 10.32.64.1 ou utiliser un service de DNS propre au réseau du VPN pour effectuer la résolution du domaine utilisé. La solution la plus simple reste de contacter l'instance directement via son IP.

Cela signifie aussi qu'il faudra adapter le fichier de configuration MedShake EHR/EDC (le config/config.yml) en conséquence en modifiant les paramètres host et cookieDomain comme ceci :

host: 10.32.64.1
cookieDomain: 10.32.64.1

Il faut déjà disposer du logiciel OpenVPN sur les postes clients y compris sur les smartphones si nous voulons accéder à l'instance Medshake EHR/EDC depuis ceux-ci (ce qui sera nécessaire pour utiliser des fonctionnalités comme Phonecapture).

Les clients auront besoin de récupérer leur fichier PKCS12 créé à l'aide d'Easy-RSA ainsi que la clé pour l'authentification HMAC que nous avons créé dans /etc/openvpn/medshake-ta.key. On peut aussi fournir au client le certificat de la CA (/var/local/easyrsa/medshake/pki/ca.crt) si on a utilisé un certificat signé par celle-ci pour le ssl du serveur web. Ainsi le navigateur web pourra identifier le certificat du serveur web (pensez aussi à autoriser l'utilisation du certificat de la CA pour vérifier les certificats des serveurs dans la configuration du navigateur web).

Attention au fichier clé pour l'authentification HMAC, c'est un fichier sensible ayant son importance dans sécurisation des accès au serveur VPN. Évitez de la transmettre par des moyens non sûrs comme en pièce jointe par courriel. Le fichier PKCS12 est chiffré et protégé par un mot de passe, ce n'est pas le cas de la clé HMAC.

Voici un exemple de fichier de configuration client correspondant à la configuration serveur créé précédemment. Il est divisé en deux parties :

  • Une fixe qui ne change pas d'un client à l'autre.
  • Une à adapter sur chaque client.
client.ovpn
#
# Cette partie est commune à chacun des clients
#
 
verb 3
proto udp
dev tun
compress lz4
mssfix
fragment 1300
nobind
 
persist-key
persist-tun
script-security 2
client
tls-client
tls-version-min 1.3
 
# Remplacer xxx.xxx.xxx.xxx par l'IP ou le domaine du serveur VPN
remote xxx.xxx.xxx.xxx
# À adapter en cas d'utilisation d'un port non standard
#port 1194
 
#
# Cette partie est à adapter sur chaque client
#
 
# Uniquement sur les clients GNU/Linux
# À adapter selon la distribution
#user nobody
#group nogroup
 
# Emplacement de la clé pour l'authentification HMAC
# La clé a un sens d'utilisation précisé en bout la ligne
# s’il est de  '0' sur le serveur il sera de '1' sur le client
tls-auth /chemin/vers/ma/ta.key 1
 
# Emplacement du certificat PKCS12
# Le mot de passe utilisé lors de sa création
# sera demandé au lancement du client
pkcs12 /chemin/vers/mon/fichier.p12

Sur les clients GNU/Linux, utiliser NetworkManager avec son plugin OpenVPN est moyennement commode pour se connecter au réseau VPN. De plus Gnome Keyring pourra stocker pour nous le mot de passe de la PKCS12 pour qu'il ne soit plus demandé à chaque connexion au VPN.

La config présente ci-dessus peut s'importer dans NetwokManager. Cependant attention au point suivant : NetworkManager utilisera par défaut le réseau VPN comme passerelle ce qui n'est pas souhaitable. Pensez à désactiver ce comportement en cochant la case “N'utilisez cette connexion que pour les ressources sur ce réseau” dans l'onglet IPv4 des paramètres de la connexion VPN. On peut aussi le faire en ligne de commande via nmcli comme ceci :

nmcli connexion modify <nom de la connexion> ipv4.never-default true

Une fois connecté au VPN si le serveur est configuré comme indiqué ci-dessus, vous devriez accéder à l'instance MedShake EHR/EDC via https://10.32.64.1/.

  • doc/access_distant.txt
  • Dernière modification: 2023/11/12 22:22
  • de