- Objectifs du dispositif
- Schéma fonctionnel
- goup
- opensignauxfaibles
- datapi
- signauxfaibles-web
- Briques extérieures
- récolter les données brutes en provenance des partenaires (goup + stockage POSIX)
- traiter/importer les données brutes (prepare-import + opensignauxfaibles + mongodb)
- raffiner les données pour obtenir les variables nécessaires à la bonne marche de l'algorithme (opensignauxfaibles + mongodb)
- exécuter la détection algorithmique (opensignauxfaibles + mongodb)
- publier les données à destination des agents (datapi + postgresql + signauxfaibles-web)
Plus de détails sont disponibles ici
goup permet aux partenaires de déposer les fichiers de données brutes sur la plateforme.
goup est basé sur tusd et lui ajoute des fonctionnalités:
- authentification par JWT
- espaces privatifs par utilisateurs (gestion des droits et des chemins)
- supprime la possibilité de télécharger les fichiers
En l'absence d'un JWT valide, le service refuse les sollicitations.
Ce token devra en plus fournir dans son chargement une propriété goup-path
correspondant au nom d'utilisateur posix ciblé par le versement.
- Lors de l'envoi, le fichier n'est accessible qu'au serveur
- La métadonnée
private
associée à l'upload permettra au serveur de décider quel traitement effectuer sur le fichier pour sa mise à disposition. - Une fois l'envoi complété, le fichier reste disponible dans l'espace du serveur de sorte qu'il pourra naturellement détecté que le fichier est déjà complet et éviter un deuxième envoi.
- Les droits sont fixés sur le fichier pour limiter l'accès aux utilisateurs souhaités (grace à la propriété
goup-path
) - Un lien est créé dans l'espace de stockage ad-hoc.
Le fichiers uploadés sont matérialisés sur le disque dur par deux fichiers nommés d'après le hash de l'upload généré par TUS:
- un fichier .bin qui contient les données du fichier
- un fichier .info qui contient les métadonnées
Le stockage est organisé dans 2 répertoires permanents:
- tusd: espace de traitement des upload par le serveur et accessible uniquement par ce dernier
- public: espace commun à tous les utilisateurs
1 répertoire privé pour chaque utilisateur (voir exemple ci-dessous)
Voici l'état du stockage après l'upload de 4 fichiers par deux utilisateurs:
- file1: user1, envoi public
- file2: user1, envoi privé
- file3: user2, envoi public
- file4: user2, envoie privé
chemin user:group mode
.
+-- tusd goup:goup 770
| +-- file1.bin user1:users 660
| +-- file1.info user1:users 660
| +-- file2.bin user1:goup 660
| +-- file2.info user1:goup 660
| +-- file3.bin user2:users 660
| +-- file3.info user2:users 660
| +-- file4.bin user2:goup 660
| +-- file4.info user2:goup 660
+-- public user1:users 770
| +-- file1.bin user1:users 660
| +-- file1.info user1:users 660
| +-- file3.bin user2:users 660
| +-- file3.info user2:users 660
+-- user1 user1:goup 770
| +-- file2.bin user1:goup 660
| +-- file2.info user1:goup 660
+-- user2 user2:goup 770
| +-- file4.bin user2:goup 660
| +-- file4.info user2:goup 660
goup est développé en go (v1.10) et exploite les packages suivants:
- https://github.com/tus/tusd
- https://github.com/tus/tusd/filestore
- https://github.com/appleboy/gin-jwt
- https://github.com/gin-contrib/cors
- https://github.com/gin-gonic/gin
- https://github.com/spf13/viper
opensignauxfaibles se charge du traitement des données:
- import des fichiers bruts (avec l'aide de prepare-import)
- calcul des données d'entrée de l'algorithme
- stockage des résultats
Cette brique intègre le stockage de l'historique des données brutes, mais aussi calculées, ainsi que des résultats de façon à permettre l'audit des calculs a posteriori.
Écrit en Go, ce module centralise les fonctions de traitement des données suivantes:
- analyse des fichiers bruts
- conversion/insert dans mongodb
- ordonnancement des traitements mapreduce/aggregations mongodb
- publication vers datapi
- https://github.com/appleboy/gin-jwt
- https://github.com/gin-contrib/cors
- https://github.com/gin-contrib/static
- https://github.com/gin-gonic/gin
- https://github.com/gorilla/websocket
- https://github.com/spf13/viper
- https://github.com/swaggo/gin-swagger
- https://github.com/swaggo/gin-swagger/swaggerFiles
- https://github.com/globalsign/mgo
- https://github.com/globalsign/mgo/bson
- https://github.com/spf13/viper
- https://github.com/tealeg/xlsx
- https://github.com/chrnin/gournal
- MongoDB 4.2
Note: Les dépendances et versions sont tenues à jour dans README.md et go.mod.
sfdata
est une commande (CLI) pour ordonner les traitements. Une documentation openapi est disponible ici
Ce module permet le traitement algorithmique. (à écrire)
- Lecture des fichiers bruts (sfdata)
- Les données brutes sont converties et insérées dans mongodb (sfdata)
- Les données sont compactées dans mongodb par un traitement map-reduce (sfdata)
- Les variables sont calculées dans mongodb par un traitement map-reduce (sfdata)
- Le traitement algorithmique est effectué par le module R/H2O
- Les résultats sont injectés dans mongodb par le module R/H2O
- Les données nécessaires au frontend sont exportées dans un format destiné à datapi par le module (sfdata)
Pour plus de détail sur le traitement des données et les transformations qui leur sont appliquées, voir ici.
opensignauxfaibles dispose d'un identifiant lui ouvrant la possibilité de publier des données sur datapi. Il lui incombe de fournir à datapi:
- des données détaillées sur les établissements et les entreprises (niveau A)
- des données synthétiques sur les établissements et les entreprises (niveau B)
- les listes de détection (niveau A)
- les badges de sécurité pour tous les objets exportés afin d'appliquer les niveaux de sécurité.
Ce traitement est écrit en dur dans le code de sfdata ici
Le détail sur le fonctionnement de Datapi est disponible ici
datapi est écrit en go (1.10) et se base sur postgresql (10).
Dans cette infrastructure, datapi est la brique permettant la diffusion contrôlée des données produites dans le projet et sert notamment de back-end pour le signauxfaibles-web.
Parmi les fonctionnalités notables:
- stockage arbitraire d'objets JSON
- gestion dynamique des permissions en lecture/écriture
- journalisation des requêtes
- programmation de la péremption des données
- les insertions et lectures de données sont effectuées au sein de transactions postgres.
- la prise en compte de l'ajout de données et de politiques de sécurité est intégrée dans le système transactionnel de façon à présenter un comportement synchrone
- les permissions accordées aux utilisateurs sont véhiculées dans le token JWT et reposent sur la sécurité de keycloak, on les retrouve dans les rôles clients communiqués dans le token.
Un object datapi est identifié par une clé et de multiples feuillets composés d'un scope de sécurité (ensemble des badges nécessaires) et d'un objet contenant les données souhaitées.
datapi propose par ailleurs un système de paniers d'objets (buckets) qui permet de faciliter l'encodage des politiques de sécurité. Les politiques de sécurité sont stockées dans le bucket system
.
Avec l'exemple ci-dessous, nous avons un objet qui pourra-être vu de 3 façons différentes selon le niveau d'accéditation:
- un utilisateur disposant d'un scope vide verra:
{
raisonSociale: "TEST";
}
- un utilisateur disposant du scope [bfc]:
{
raisonSociale: "TEST",
activitePartielle: [..., ..., ...]
}
- un utilisateur disposant du scope [bfc, crp]:
{
raisonSociale: "TEST",
activitePartielle: [..., ..., ...],
debitUrssaf: [..., ..., ...],
bilanBDF: [..., ..., ...]
}
Une requête consiste à demander au serveur d'assembler les feuillets de tous les objets contenant la clé fournie dans la requête. Ce principe est appuyé sur l'opérateur @>
du type hstore fourni par postgres, et comme on peut le voir ci-dessus, seuls les feuillets visibles par l'utilisateur sont utilisés dans l'assemblage.
Seul le premier niveau de clé de l'objet contenu dans la valeur d'un objet sont confrontés, ce qui expose le système à des risques de collision, et dans ce cas, c'est la valeur insérée en dernier qui remplace les valeurs précédentes.
Il est possible de fournir à datapi une date de publication à un feuillet de données, et dans ce cas, ce feuillet sera ignoré tant que la date système n'aura pas atteint cette valeur.
La péremption des données est obtenue en publiant une version vide écrasant la donnée que l'on souhaite oblitérer avec une date de publication correspondant à la date de péremption.
Ce principe seul ne permet pas de supprimer les données de la base de données, il ne fait qu'en contenir la diffusion, toutefois il est envisagé d'avoir un traitement planifié pour retrouver toutes ces valeurs les oblitérer.
Une politique de sécurité permet d'intéragir avec les permissions accordées aux utilisateurs. Le périmètre d'application d'une politique de sécurité est définie par une clé d'objet, un scope, un ensemble de buckets (définis par une expression régulière).
- en ajoutant des badges aux utilisateurs
- en ajoutant des badges aux objets
- Une ressource comporte des «badges» de sécurité (une liste de tags), les utilisateurs disposent dans leurs attributions de badges.
- Une ressource n'est disponible à un utilisateur que si il dispose de l'ensemble des badges demandés par la ressource.
- Des politiques de sécurités permettent de fixer des règles ajoutant des badges aux ressources (renforcement de la contrainte de sécurité) ou aux utilisateurs (promotion)
- Les politiques de sécurité peuvent s'appliquer à un ensemble d'objets
- postgresql v10
- https://github.com/gin-contrib/cors
- https://github.com/gin-gonic/gin
- https://github.com/appleboy/gin-jwt
- https://github.com/swaggo/gin-swagger
- https://github.com/swaggo/gin-swagger/swaggerFiles
- https://github.com/gin-gonic/gin
- https://github.com/lib/pq
- https://github.com/lib/pq/hstore
- https://golang.org/x/crypto/bcrypt
Il s'agit de l'interface web utilisée par les agents. Elle communique avec datapi.
Les tokens JWT (long terme et session) contiennent notamment dans leur payload l'adresse email de l'agent auquel il est adressé et un contrôle est effectué pour empêcher une connexion avec un autre profil.
signauxfaibles-web est une application Vue.js écrite en TypeScript qui fait principalement usage des bibliothèques suivantes :
- Vuetify comme bibliothèque d'interface utilisateur
- Vuex pour centraliser la gestion des états de l'application
- axios pour faire des appels Ajax notamment à datapi
- ApexCharts comme bibliothèque de graphique
Elle est architecturée de la manière suivante :
Vue | Description | Vues parentes |
---|---|---|
Browse | Consultation d'un établissement | |
Etablissement | Fiche établissement | Browse, PredictionWidget |
Etablissement/Commentaire | Commentaires sur un établissement | Etablissement |
Etablissement/Effectif | Effectifs de l'établissement (dont activité partielle) | Etablissement |
Etablissement/Finance | Non utilisé | Etablissement |
Etablissement/Historique | Historique des alertes issues des listes de détection passées | Etablissement/Identite |
Etablissement/Identite | Identité de l'établissement (raison sociale, SIRET, coordonnées et activité) | Etablissement |
Etablissement/Map | Carte dynamique | Etablissement |
Etablissement/NewComment | Saisie d'un nouveau commentaire | Etablissement/Commentaire, Etablissement/Thread |
Etablissement/OldFinance | Informations financières (dont CA, REX, etc.) | Etablissement |
Etablissement/Thread | Fil de commentaires | Etablissement/Commentaire, Etablissement/Thread |
Etablissement/Urssaf | Cotisations et dettes Urssaf | Etablissement |
Goup | Envoi de données manuel | |
Help | Menu d'aide contextuelle | Etablissement, Goup |
Login | Non utilisé | |
NavigationDrawer | Menu latéral de navigation | App |
News | Changelog | NavigationDrawer |
PageNotFound | Page non trouvée | |
Prediction | Liste de détection des établissements | |
PredictionWidget | Élément de la liste | Prediction |
PredictionWidgetScore | Non utilisé | |
ScoreWidget | Niveau d'alerte détecté | PredictionWidget, Historique |
Security | Boîte de dialogue sur la confidentialité | App |
Spinner | En cours de chargement | Prediction |
Toolbar | Barre supérieure | Browse, Goup |
Upload | Upload de fichier | Goup |
Veuillez consulter la documentation de l'interface graphique pour en savoir plus sur les aspects fonctionnels.
Les dépendances logicielles sont gérées par yarn.
Voici les paquets requis par le projet par ordre alphabétique :
- @babel/core (7.4.3) : Babel compiler core
- @dsb-norge/vue-keycloak-js (1.1.1) : A Keycloak plugin for Vue >= 2.x
- @types/jwt-decode (2.2.1) : TypeScript definitions for jwt-decode
- apexcharts (3.8.6)
- axios (0.18.0) : Promise based HTTP client
- core-js (2.6.5) : Modular standard library for JavaScript including polyfills for ECMAScript up to 2019
- filesize (4.1.2) : JavaScript library to generate a human readable String describing the file size
- identicon.js (2.3.3) : GitHub-style identicons as PNGs or SVGs in JS
- jest (>=22 <24) : Delightful JavaScript Testing
- js-md5 (0.7.3) : A simple MD5 hash function for JavaScript supports UTF-8 encoding
- jwt-decode (2.2.0) : Decode JWT tokens which are Base64Url encoded
- mapbox-gl (1.4.1) : A WebGL interactive maps librar
- tiptap (1.26.5) : A rich-text editor for Vue.js
- tiptap-extensions (1.28.5) : Extensions for tiptap
- tus-js-client (1.8.0-1) : A pure JavaScript client for the tus resumable upload protocol
- uuid (3.3.3) : RFC4122 (v1, v4, and v5) UUIDs
- vue (2.6.10)
- vue-apexcharts (1.5.0)
- vue-class-component (7.0.2) : ES201X/TypeScript class decorator for Vue components
- vue-mapbox (0.4.1) : Combine powers of Vue.js and Mapbox Gl JS
- vue-native-websocket (2.0.13) : Native websocket implemantation for Vue.js and Vuex
- vue-property-decorator (8.1.0) : Property decorators for Vue Component
- vue-router (3.0.3) : Official router for Vue.js 2
- vuetify (1.5.5)
- vuex (3.0.1)
- vuex-persistedstate (2.5.4) : Persist and rehydrate your Vuex state between page reloads
- webpack (4.30.0) : The module bundler
Voici les paquets spécifiques au développement par ordre alphabétique :
- @types/jest (23.1.4) : TypeScript definitions for Jest
- @vue/cli-plugin-babel (3.6.0) : Babel plugin for vue-cli
- @vue/cli-plugin-e2e-nightwatch (3.6.0) : e2e-nightwatch plugin for vue-cli
- @vue/cli-plugin-typescript (3.6.0) : Typescript plugin for vue-cli
- @vue/cli-plugin-unit-jest (3.6.0) : unit-jest plugin for vue-cli
- @vue/cli-service (3.6.0) : Local service for vue-cli projects
- @vue/test-utils (1.0.0-beta.29) : Utilities for testing Vue components.
- babel-core (7.0.0-bridge.0) : Babel compiler core
- stylus (0.54.5) : Robust, expressive, and feature-rich CSS superset
- stylus-loader (3.0.1) : Stylus loader for webpack
- ts-jest (23.0.0) : A preprocessor with source maps support to help use TypeScript with Jest
- typescript (3.4.3) : TypeScript is a language for application scale JavaScript development
- vue-cli-plugin-vuetify (0.5.0) : Vuetify Framework Plugin for Vue CLI 3
- vue-template-compiler (2.5.21) : Template compiler for Vue 2.0
- vuetify-loader (1.0.5) : A Webpack plugin for treeshaking Vuetify components
La version de MongoDB utilisée est la 4.2.
Note: Les dépendances et versions sont tenues à jour dans README.md et go.mod.
Il s'agit du produit officiel développé par Red Hat.
Keycloak fournit les services d'authentification pour goup
et datapi
en forgeant les JWT des utilisateurs.
Ce produit est utilisé en version 6.0.1.
Le chargement du token est effectué par Keycloak à l'aide du modèle utilisateur.
Un attribut utilisateur goup-path
fixé dans Keycloak sera utilisé pour fixer le nom d'utilisateur à utiliser sur l'infrastructure pour l'enregistrement des fichiers.
Le scope utilisé par datapi sera accessible au travers des rôles clients configurés également dans Keycloak et fixés par utilisateur.
La version utilisée est la 10.8. Le module hstore du packages contrib est utilisé.
Un exemple de client tus (protocole de téléchargement résumable) est fourni ici et permet de voir une implémentation JavaScript basée sur le client officiel.
On trouve toutefois des clients dans de nombreux langages qui permettront aux utilisateurs d'intégrer l'upload de fichier dans leurs plateformes.