Aller au contenu

Notes pour l'installation sécurisée de ELABFTW selon les consignes du CNRS

Contexte

Tout d'abord consulter la documentation officielle pour l'installation d'ELABFTW à cette adresse https://doc.elabftw.net/install.html

  • adresse publique: 1XX.XXX.XXX.XXX, cle.xyz.u-bordeaux.fr
  • reverse proxy: TRAEFIK (ou NGINX) avec certificat SSL
  • frontend ELABFTW: xyz.front.lab
  • mysql avec TLS : xyz.mysql.lab

Installation

Sur le frontend ELABFTW (xyz.front.lab)

Sur cette machine il n'y aura que le frontend ELABFTW qui est configuré dans le fichier docker-compose.yml. Télécharger la dernière version (actuellement la 4.8.6) proposée par Nicolas Carpi sur le site d'elabftw et l'adapter selon ses besoins.

Télécharger le fichier docker-compose.yml

curl -so docker-compose.yml "https://get.elabftw.net/?config"

L'avantage de cette version est qu'elle est complète et à jour. Par contre, cette version contient des conteneurs pour elabftw et mysql. Il faudra donc l'adapter pour ne garder que la partie services/web.

Autrement on peut utiliser la version ci-dessous:

version: '3'
# our first container is nginx + php-fpm + elabftw
services:
  web:
    image: elabftw/elabimg:4.8.6
    restart: always
    container_name: elabftw_cnrs
    security_opt:
        - no-new-privileges:true
    cap_drop:
        - SYS_ADMIN
        - AUDIT_WRITE
        - MKNOD
        - SYS_CHROOT
        - SETFCAP
        - NET_RAW
        - SYS_PTRACE
    environment:
        - DB_HOST=xyz.mysql.lab
        - DB_PORT=3306
        - DB_NAME=elabftw
        - DB_USER=elabftw
        - DB_PASSWORD=ZZZxxxxxxxxxxxxxxxxooOMoX
        - DB_CERT_PATH=/elabftw/mysql-cert/server-cert.pem
        - PHP_TIMEZONE=Europe/Paris
        - TZ=Europe/Paris
        - SECRET_KEY=UUUxxxxxxxxxxxxxxxx931b400a4a031a1925b1
        - SITE_URL=https://cle.xyz.u-bordeaux.fr
        - SERVER_NAME=cle.xyz.u-bordeaux.fr
        - DISABLE_HTTPS=false
        - ENABLE_LETSENCRYPT=false
    ports:
        - '443:443'
    volumes:
        - ./elabftw/web:/elabftw/uploads
        - ./certs:/elabftw/mysql-cert
    networks:
      - elabftw-net

Cette version est prévue pour fonctionner avec un serveur mysql en TLS. Le certificat du serveur est géré par le reverse proxy TRAEFIK

Deux volumes persitants sont utilisés pour le conteneur

  • un pour les fichiers qui seront télécharger dans elabFTW elabftw/web
  • un pour le certificat du serveur mysql: certs

On lance elabFTW avec la commande suivante:

docker-compose up -d

il faut ensuite installer le serveur mysql comme indiqué dans le chapître ci-dessous puis on lance l'initialisation de la base de données avec la commande suivante:

docker exec elabftw_cnrs bin/init db:install

      _          _     _____ _______        __
  ___| |    __ _| |__ |  ___|_   _\ \      / /
 / _ \ |   / _| | '_ \| |_    | |  \ \ /\ / / 
|  __/ |__| (_| | |_) |  _|   | |   \ V  V /  
 \___|_____\__,_|_.__/|_|     |_|    \_/\_/   
Welcome to the install of eLabFTW!
This program will install the MySQL structure.
Before proceeding, make sure you have an empty MySQL database for eLabFTW with a user+password to access it.
→ Initializing MySQL database...
✓ Installation successful! You can now start using your eLabFTW instance.
→ Register your Sysadmin account here: cle.rmsb.u-bordeaux.fr/register.php
→ Subscribe to the low volume newsletter to stay informed about new releases: http://eepurl.com/bTjcMj

Sur le serveur mySQL (raisin-cle-4-umr5107.lab)

On installe le serveur mysql avec ssl et docker

Le plus simple est de repartir du docker-compose.yml téléchargé précédement et l'adapter à ses besoins. Ci-dessous celui que j'utilise:

version: '3.8'

services:
  mysql:
    container_name: mysql_cnrs_ssl
    image: mysql:8.0
    ports:
      - "3306:3306"
    environment:
        MYSQL_DATABASE: elabftw
        MYSQL_USER: elabftw
        MYSQL_PASSWORD: ZZZxxxxxxxxooOMoX
        MYSQL_ROOT_PASSWORD: VVVxxxxxOVYu3Svs
    volumes:
      - ./mysql:/var/lib/mysql
      - ./certs:/etc/certs/
    command: [ "mysqld",
               "--character-set-server=utf8mb4",
               "--collation-server=utf8mb4_unicode_ci",
               "--bind-address=0.0.0.0",
               "--require_secure_transport=ON",
               "--ssl-ca=/etc/certs/ca-cert.pem",
               "--ssl-cert=/etc/certs/server-cert.pem",
               "--ssl-key=/etc/certs/server-key.pem",
               "--default_authentication_plugin=mysql_native_password" ]
    restart: always

Deux volumes persistants sont utilisés pour le conteneur:

  • un pour les fichiers de mysql : ./mysql
  • un pour les certificats utilisés par le serveur mysql : ./certs

Avant le lancer le conteneur docker de mysql il faut générer les certificats.

Source configuration mysql avec ssl : https://techsparx.com/software-development/docker/damp/mysql-ssl-connection.html

Ce mettre dans le répertoire ./certs

Commandes utilisées, on peut se servir du script gencert.sh qui reprend toutes les commandes ci-dessus:

  • Créer la clé du CA:
openssl genrsa 2048 > ca-key.pem
  • Créer le certificat avec la clé précédente:
openssl req -new -x509 -nodes -days 365000 -key ca-key.pem -out ca-cert.pem

avec un exemple de sortie

Country Name (2 letter code) [AU]:FR
State or Province Name (full name) [Some-State]:Aquitaine
Locality Name (eg, city) []:Bordeaux
Organization Name (eg, company) [Internet Widgits Pty Ltd]:CNRS
Organizational Unit Name (eg, section) []:NOM_DE_SON_LABO
Common Name (e.g. server FQDN or YOUR name) []:xyz.mysql.lab
Email Address []:

il est important de mettre pour le Common Name ou CN le nom du serveur mysql qui est utilisé pour la configuration d'elabFTW pour que cela fonctionne. Dans cet exemple c'est xyz.mysql.lab

A ce stade on a 2 fichiers :

  • ca-cert.pem – Fichier de certificat Certificate Authority (CA).
  • ca-key.pem – Fichier de clé Certificate Authority (CA).

On utilise ces 2 clés pour générer les certificats serveur et client.

  • Pour le serveur, on crée la clé et le certificat :
openssl req -newkey rsa:2048 -days 365000 -nodes -keyout server-key.pem -out server-req.pem

Utiliser le même Common Name que ci-dessus

On convertit la clé en RSA:

openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -req -in server-req.pem -days 365000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem
Signature ok
subject=C = FR, ST = Aquitaine, L = Bordeaux, O = CNRS, OU = RMSB, CN = xyz.mysql.lab
Getting CA Private Key

On a donc 2 fichiers :

  • server-cert.pem – Fichier certificat SSL du serveur mySQL
  • server-key.pem – Fichier de clé SSL pour le serveur mySQL

On génère le certificat pour le client de la même manière :

ATTENTION Pour le client utiliser le COMMON NAME (CN) du serveur eLabFTW (zozo.dmz.fr)

openssl req -newkey rsa:2048 -days 365000 -nodes -keyout client-key.pem -out client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -req -in client-req.pem -days 365000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem

On vérifie les certificats :

openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem
server-cert.pem: OK
client-cert.pem: OK

on peut avoir cette erreur:

C = FR, ST = Aquitaine, L = Bordeaux, O = CNRS, OU = CRMSB, CN = xyz.mysql.lab
error 18 at 0 depth lookup: self signed certificate
error server-cert.pem: verification failed
client-cert.pem: OK

C'est parce que nous avons utilisé le même CN pour le ca-cert.pem et le server-cert.pem. Cela fonctionne quand même (TODO: trouver unmoyen d'éviter l'erreur)

TIPS: Il faut que le fichier server-key.pem ai l'uid: 999 pour que le serveur se lance avec ssl.

sudo chown 999 certs/server-key.pem 

On peut vérifier que la liason entre elabftw et le serveur mysql fonctionne correctement avec la commande suivante:

docker exec -ti elabftw_cnrs php bin/console db:check

Si cela retourne:

Database check
==============
Current version: 111
Required version: 111
No upgrade required.

Tout est OK, par contre si on a:

In Db.php line 52:
  SQLSTATE[HY000] [2002]  (trying to connect via (null))
In Db.php line 52:
  PDO::__construct(): Peer certificate CN=`server-cert' did not match expected CN=`xyz.mysql.lab'   

Le problème est du à un certificat avec le mauvais Common Name

In Db.php line 52:
  SQLSTATE[HY000] [2002]  (trying to connect via (null))  
In Db.php line 52:
  PDO::__construct(): SSL operation failed with code 1. OpenSSL Error messages:         
  error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed  
db:check

Ce n'est pas le même certificat entre le serveur mysql et elabftw

Sur le reverse proxy

Traefik est utilisé Traefik mais il possible d'utiliser également Nginx Nginx.

Voici le fichier pour rediriger vers le serveur:

elabftw_cle_rmsb.yml

http:
  routers:
    elabftw_cnrs:
      tls: {}
      entryPoints: ["secure", "insecure"]
      service: "service-cle"
      priority: 50
      rule: "Host(`cle.xyz.u-bordeaux.fr`)"

  services:
    service-cle:
      loadBalancer:
        servers:
          - url: "https://1XX.XXX.XXX.XXX:9444/"

Sur mon parefeu toutes les requêtes sur les ports 80 (http) et 443 (https) sont redirigés vers TRAEFIK qui ensuite fait le tri des requêtes et dans ce cas si l'URL contient cle.xyz.u-bordeaux.fr elle est redirigée vers le serveur elabftw https://1XX.XXX.XXX.XXX:9444.

Pour configurer le certificat du serveur il faut ajouter dans le fichier de configuration de TRAEFIK

traefik.yml

tls:
  certificates:
    - certFile: /etc/ssl/my_certs/xyzzzz.fr.all.cert
      keyFile: /etc/ssl/my_certs/xyzzzz.cnrs.fr.key
      stores:
        - default
    - certFile: /etc/ssl/my_certs/cle.xyz.u-bordeaux.fr.cert
      keyFile: /etc/ssl/my_certs/cle.xyz.u-bordeaux.fr.key
      stores:
        - default
  stores:
    default:
  defaultCertificate:
      certFile: /etc/ssl/my_certs/2022-2023/www.rcle.xyz.u-bordeaux.fr.all.2022.cert
      keyFile:  /etc/ssl/my_certs/2022-2023/www.cle.xyz.u-bordeaux.fr.2022.key

Document généré avec:
pandoc -s -o installation_elabftw_cnrs.pdf -f "gfm"
--template /usr/share/pandoc/data/templates/eisvogel.latex
--listings --number-section -V subparagraph --toc
--dpi=300 -Vlang=fr-FR
--pdf-engine=xelatex header-elabftw.yml installation_elabftw_cnrs.md