[belenios] Ajout de Bélénios

Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
ceph
Yohann D'ANELLO 2021-11-11 16:18:10 +01:00
parent 64d649ee28
commit c267a127e9
Signed by: _ynerant
GPG Key ID: 3A75C55819C8CF85
2 changed files with 233 additions and 1 deletions

View File

@ -41,7 +41,7 @@
│ │ └── prefix-delegation.md [DONE]
│ └── owncloud.md [erdnaxe]
└── services
├── belenios.md [ÿnérant]
├── belenios.md [DONE]
├── ethercalc.md [erdnaxe]
├── etherpad.md [erdnaxe]
├── framadate.md [DONE]

View File

@ -0,0 +1,232 @@
# Belenios
Belenios est un service développé par l'Inria recréant un bureau de vote complet en ligne avec autant voire plus de sécurité grâce à des bulletins chiffrés. Il a été mis en place pour l'assemblée générale du Crans en 2020, alors que la pandémie de Covid-19 empêchait toute réunion physique.
## Installation
On considère que l'on dispose d'une machine virtuelle neuve installée sous Debian Bullseye.
Belenios n'est malheureusement pas encore packagé dans Debian. Par chance, toutes ses dépendances le sont. On installe donc toutes les dépendances via APT, puis on compile Belenios manuellement.
### Dépendances
Belenios est intégrallement écrit en OcamL. On installe toutes ses dépendances Debian, comme indiqué dans le README :
```bash
$ sudo apt update
$ sudo apt install --no-install-recommends bubblewrap build-essential ca-certificates cracklib-runtime jq libgd-securityimage-perl libgmp-dev libncurses-dev libpcre3-dev libssl-dev libsqlite3-dev m4 pkg-config unzip wget zip zlib1g-dev
```
On installe ensuite toutes les dépendances OCamL depuis les paquets Debian, ce qui est plus économe par rapport à compiler toutes les bibliothèques avec Opam :
```bash
$ sudo apt install --no-install-recommends dune eliom libatdgen-ocaml-dev libcalendar-ocaml-dev libcmdliner-ocaml-dev libcryptokit-ocaml-dev libcsv-ocaml-dev libgettext-ocaml-dev libzarith-ocaml-dev
```
On doit enfin installer ``ocsigenserver``, qui sert de serveur web tel Nginx ou Apache adapté pour les projets OcamL :
```bash
$ sudo apt install --no-install-recommends ocsigenserver
```
### Compilation de Belenios
On commence par cloner le dépôt dans un endroit adapté :
```bash
$ sudo git clone https://gitlab.inria.fr/belenios/belenios.git /opt/belenios -b 1.14
```
Il suffit ensuite dans le dossier ``/opt/belenios`` de lancer ``make build-release-server``.
### Liens symboliques
Pour avoir des binaires à des endroits cohérents avec la distribution Debian, on ajoute des liens symboliques à des endroits pertinents :
```bash
$ sudo ln -s /opt/belenios/_run/usr/lib/belenios /usr/lib/ocaml/belenios
$ sudo ln -s /opt/belenios/_run/usr/lib/belenios-platform /usr/lib/ocaml/belenios-platform
$ sudo ln -s /opt/belenios/_run/usr/lib/belenios-platform-js /usr/lib/ocaml/belenios-platform-js
$ sudo ln -s /opt/belenios/_run/usr/lib/belenios-platform-native /usr/lib/ocaml/belenios-platform-native
$ sudo ln -s /opt/belenios/_run/usr/lib/belenios-server /usr/lib/ocaml/belenios-server
$ sudo ln -s /opt/belenios/_run/usr/lib/belenios-tool /usr/lib/ocaml/belenios-tool
$ sudo ln -s /opt/belenios/_run/usr/share/belenios-server /usr/share/belenios-server
```
### Configuration de ocsigenserver
On commence par créer les dossiers de données qui nous intéressent, avec les bonnes permissions :
```bash
$ sudo -u ocsigen mkdir -p /etc/ocsigenserver/conf.d /var/lib/belenios /var/lib/belenios/data /var/lib/belenios/upload /var/lib/belenios/spool /var/log/belenios
```
On ajoute enfin le fichier de configuration fourni par Belenios dans ``/etc/ocsigenserver/conf.d/belenios.conf``, en remplaçant les bonnes variables :
```xml
<!-- -*- Mode: Xml -*- -->
<ocsigen>
<server>
<port>8001</port>
<logdir>/var/log/belenios</logdir>
<datadir>/var/lib/belenios/data</datadir>
<uploaddir>/var/lib/belenios/upload</uploaddir>
<!--
The following limits are there to avoid flooding the server.
<maxuploadfilesize> might need to be increased for handling large
elections.
<maxconnected> is related to the number of simultaneous voters
visiting the server.
-->
<maxuploadfilesize>1024kB</maxuploadfilesize>
<maxconnected>500</maxconnected>
<commandpipe>/var/run/ocsigenserver_command</commandpipe>
<charset>utf-8</charset>
<findlib path="/usr/lib/ocaml"/>
<extension findlib-package="ocsigenserver.ext.staticmod"/>
<extension findlib-package="ocsigenserver.ext.redirectmod"/>
<extension findlib-package="ocsigenserver.ext.ocsipersist-sqlite">
<database file="/var/lib/belenios/data/ocsidb"/>
</extension>
<extension findlib-package="eliom.server"/>
<extension findlib-package="belenios-platform-native"/>
<host charset="utf-8" hostfilter="*" defaulthostname="{{ belenios.domain }}">
<!-- <redirect suburl="^$" dest="http://www.example.org"/> -->
<site path="static" charset="utf-8">
<static dir="/usr/share/belenios-server" cache="0"/>
</site>
<site path="monitor">
<eliom findlib-package="eliom.server.monitor.start"/>
</site>
<eliom findlib-package="belenios-server">
<!-- Domain name used in Message-ID -->
<domain name="https://{{ belenios.domain }}/"/>
<!--
The following can be adjusted to the capacity of your system.
If <maxrequestbodysizeinmemory> is too small, large elections
might fail, in particular with so-called alternative questions
with many voters.
<maxmailsatonce> depends heavily on how sending emails is
handled by your system.
-->
<maxrequestbodysizeinmemory value="1048576"/>
<maxmailsatonce value="1000"/>
<uuid length="14"/>
<gdpr uri="https://www.belenios.org/rgpd.html"/>
<contact uri="mailto:{{ belenios.email_contact }}"/>
<server mail="{{ belenios.email_from }}"/>
<auth name="{{ belenios.cas.name }}"><cas server="{{ belenios.cas.server }}"/></auth>
<source file="/usr/share/belenios-server/belenios.tar.gz"/>
<default-group file="/usr/share/belenios-server/groups/default.json"/>
<nh-group file="/usr/share/belenios-server/groups/rfc3526-2048.json"/>
<log file="/var/log/belenios/security.log"/>
<locales dir="/usr/share/belenios-server/locales"/>
<spool dir="/var/lib/belenios/spool"/>
<!-- <warning file="/opt/belenios/belenios/_run/warning.html"/> -->
</eliom>
</host>
</server>
</ocsigen>
```
Il faut noter que ``ocsigenserver`` n'est pas lancé au démarrage par défaut et un ``systemctl start ocsigenserver`` ne fonctionne pas, un ``service ocsigenserver start`` en revanche si. Pour autoriser ``ocsigenserver`` à se lancer au démarrage, il faut modifier le fichier ``/etc/default/ocsigenserver`` pour écrire ``LAUNCH_AT_STARTUP=true``. Il sera ensuite possible de démarrer le serveur grâce à systemd.
En redémarrant ``ocsigenserver``, Belenios sera accessible sur son port 80. Après une configuration de reverse-proxy près, Belenios est déjà accessible :)
Pour modifier le logo, il faut regarder autour de ``/usr/share/belenios-server/logo.png``.
### Déployer avec Ansible
L'ensemble des opérations décrites sont déployées par le rôle Ansible du Crans : `<https://gitlab.crans.org/nounous/ansible/-/tree/newinfra/roles/belenios>`
Il prend en configuration le nom de domaine utilisé (``belenios.domain``), des adresses mails de contact (``belenios.email_contact`` et ``belenios.email_from``) ainsi que les paramètres du CAS (``belenios.cas.name`` et ``belenios.cas.server``, voir ci-dessous).
## Utilisation
Toute personne ayant un compte Crans peut créer une élection sur Belenios en se connectant via le CAS du Crans. Cela se configure sur la ligne du fichier de configuration ocsigenserver :
```xml
<auth name="{{ belenios.cas.name }}"><cas server="{{ belenios.cas.server }}"/></auth>
```
On peut remplacer le nom par ``CAS Cr@ns`` et le serveur par `<https://cas.crans.org/>`.
Une fois connecté, on peut créer et administrer une élection.
### Gestion des mots de passe
Belenios propose deux modes pour gérer les mots de passe :
* Automatique (mode dégradé : les codes de vote seront générés par le serveur)
* Manuel (mode sécurisé : un tiers se chargera des codes de vote)
Dans le premier mode, Belenios se charge de générer les codes de vote et les envoie lui-même par mail.
Dans le second mode, recommandé, c'est vous qui envoyez vous même les codes de vote aux électeurs.
Le code de vote ne servant qu'à débuter l'élection pour une personne, la sécurité ne réside pas ici. C'est plus ou moins l'équivalent de donner son nom au bureau de vote. Ce n'est pas une information sensible. À la fin du vote on demande aux votants de réellement s'identifier avant de glisser les bulletins dans l'urne. On dispose de deux moyens d'authentification :
* Générer des mots de passe confidentiels (hashés sur le serveur) par personne, géré par Belenios ;
* Utiliser un CAS.
Il va de soi qu'on vous recommande la deuxième option. Cela peut être n'importe quel serveur CAS, pas nécessairement celui du Crans. Par exemple, on utilisera `<https://cas.crans.org/>` pour le Crans, `<https://note.crans.org/cas>` pour la Note Kfet, ou `<https://cas.inria.fr/cas>` pour celui de l'Inria.
Pensez bien à autoriser Belenios à utiliser votre serveur CAS, et à faire attention à ce que les pseudos renvoyés soient en ASCII !
Plus d'informations ici : `<https://www.belenios.org/setup.html>`
### Inscription des électeurs
La liste des électeurs doit être arrêtée avant la création de l'élection. La liste doit être donnée sous la forme ``ADRESSE@EMAIL,PSEUDO``.
Depuis la dernière version, il est également définir un poids par électeur.
**Atention :**
Belenios ne supporte pas l'UTF-8 dans les pseudos. Assurez-vous de garder des pseudos ASCII. Et dans les adresses e-mail, mais cela va de soi.
#### Générer la liste des adhérents avec Re2o
Pas besoin de plus d'une ligne :
```python
"\n".join(map(lambda user: f"{user.get_mail},{user.pseudo}", utils.all_adherent(including_asso=False).filter(adherent__isnull=False)))
```
C'est faux : il faut importer ```utils``` et sans doute écrire dans un fichier.
### Déclaration des autorités de déchiffrement
Il s'agit de l'équivalent des assesseurs qui vont contrôler et dépouiller l'élection. Il peut y en avoir plusieurs. Chacun aura sa clé, et la clé sera nécessaire pour le dépouillement. Dans tous les cas, Belenios lui-même est une autorité de déchiffrement mais il est recommandé d'avoir une autorité extérieure.
**IMPORTANT :**
Cela tient plus du mauvais pressentiment que de l'expérience, mais pensez bien à VRAIMENT conserver la clé privée en lieu sûr, elle n'est pas récupérable. Jeter sa clé privée, c'est comme acheter une urne en verre incassable avec une serrure qui tient le coup et jeter le trousseau dans les égouts, en veillant à la fondre et la broyer avant. Vous pourrez ajouter des bulletins dans l'urne mais jamais la dépouiller.
### Élection
Une fois l'élection créée, il n'est plus possible de la modifier, ce qui est normal. Il est possible de définir les horaires d'ouverture de l'élection (attention : les horaires sont sur le fuseau UTC !).
Pour voter, chaque participant doit présenter son code d'élection, voter pour chacune des questions, puis soumettre son bulletin en s'authentifiant via le moyen défini. Son bulletin est ensuite chiffré et enregistré. Il est possible de revoter autant de fois que nécessaire, chaque vote annulant le précédent.
### Dépouillement
Après l'élection, et pas avant (ce qui n'est de toute façon pas possible), chaque autorité de déchiffrement doit soumettre sa clé privée pour ouvrir l'urne. Une fois cela fait, les résultats sont publics sur la page de l'élection.