CAW1 2018 Projet de Nicolas Pamart et Loïc Wisniewski

De Ensiwiki
Aller à : navigation, rechercher
Project schedule.png
Titre du projet LeSurveilleur
Cadre Projets de spécialité
Page principale Test

Équipe Nicolas Pamart, Loïc Wisniewski
Encadrants Sébastien Viardot


Ce projet fournit aux administrateurs systèmes un outil simple mais efficace de monitoring de serveur. Appelé "Le Surveilleur", cette application Web permet de voir plus loin, tout en regardant de très près. A vous le 100% d'uptime. Le dépôt git est disponible à cette adresse: https://gitlab.com/metaheavens/projet-web

Cahier des charges

L'objectif de ce projet est de développer un application web permettant d'enregistrer ses serveurs afin de les surveiller sur internet, avec son téléphone ou son ordinateur.

  • Se connecter pour afficher la liste des ses serveurs
  • Différents rôles (admin, peut monitorer et modifier tous les serveurs de l'instance, utilisateur, peut gérer ses serveurs)
  • Ajout d'un serveur a la liste des serveurs
  • Affichage de la liste des serveurs
  • Affichage de l'etat du serveur (up ou down selon résultat du ping)

Scénari et cas d'usage

Scénari 1 : L'utilisateur arrive sur le site pour la première fois. Il créé un compte en cliquant sur le bouton inscription, rempli les champs d'un formulaire qui s'affiche et s'inscrit. Il peut ensuite se connecter à l'aide des ses identifiants précedemment créé.

Scénari 2 : L'utilisateur vient de se connecter, la liste de ses serveurs d'affiche. Il ajoute un serveur à l'aide d'un formulaire qu'il remplit (surnom, adresse IP, port, login et mot de passe). Il peut maintenant cliquer sur son serveur pour afficher les informations de celui-ci.

Cas d'usages :

Usecase 1.jpg

Usecase 2.jpg

Choix techniques et architecture de l'application

Différents choix techniques ont été effectués pour optimiser notre temps de développement afin de sortir une application la plus fonctionnelle et maintenable possible. Le site à été pensé sous forme d'application web, avec un client riche ne faisant appel à une API que pour la récupération de donnée.

Frontend

Etant un client riche, cette partie de l'application nécessite d'être décomposé dans une architecture MVC. Le framework Vue.js est utilisé pour la vue, Vuex.js est utilisé pour la partie modèle et controlleur. Les framework orienté composant comme Vue.js permettent la mise à disposition de composant préfait, où seul le contenu et les bindings vers les controlleurs sont à changer. Dans un souci de réduire le temps passé sur le style et le responsive design, nous avons utilisé une librairie mettant à disposition des composant respectant le material design de Google. Ce choix technologique ne nous permettra pas d'obtenir une mise en page sémantiquement correcte étant donné que les templates HTML sont à la discrétion des développeurs de ces composants. Pour les rendre génériques ils n'ont pas pu respecter une certaine sémantique.

Vue.js

Nous avons utilisé ce framwork pour le front-end. Les fichiers relatifs à Vue.js sont dans le dossier de l'application le-surveillant-front/src/components, le-surveillant-front/src/main.js. L'application est décomposée en 2 sous applications, une pour le login, l'autre pour le monitoring. Chacune de ces deux applications sont composées en composants, dont le composant App.vue, toujours affiché une fois que les utilisateurs sont connectés. Dans ce composants, il y a plusieurs pages (ListServer.vue, ListServerAdmin.vue...) qui peuvent apparaitre. Ces pages changent en fonction de l'adresse accèdées (http://monurl/#/dashboard pour la ListServer.vue par example). Cette répartition en routes est possible grâce au paquet vue-router, qui permet de gérer les routes dans le front-end.

Chaque composant n'est là que pour l'affichage. Toute la gestion de la donnée est faite par des "stores" Vuex, une librairie décrite ci-dessous, grâce à des bindings vuex -> vue.js (dans le code, voir 'mapMutations' et 'mapState') .

Vuex

Pour la gestion de la donnée côté front-end, notre modèle, et la gestion des évènement, tel que les click, nous avons décidé de nous reposer sur Vuex qui permet, avec Vue.js, de décoreller la définition des vues, des modèles et des controleurs. La donnée est donc stocké sous forme de 'stores', leur code source est disponible dans le dossier le-surveillant-front/src/store. Les modifications possibles sur la donnée à travers des actions sont décrites dans le même fichier que la donnée, sous forme de mutation, seules fonction autorisée à modifier les store. Toutes les modifications passent par ces méthodes, elles font office de controleurs, appelable dans vue.js grâce aux 'mapMutation'.

Communication

La communication entre les deux morceaux de l'application se fait au travers d'une websocket. Ce choix à été fait pour permettre au serveur d'envoyer ses mises à jour au client. Ainsi l'utilisateur à toujours la version la plus à jour de l'information pour monitorer (surveiller) efficacement ses serveurs. Ainsi, l'ajout, la suppression ou la modification des serveurs passent aussi par cette websocket, nous avons donc établi un protocole de communication décris ci-dessous.

/!\ INSERER ICI LE PROTOCOLE

Actions

Voici la liste des messages possible pour agir sur le serveur:


Demander au serveur la liste des serveurs pour l'utilisateur actuel:

 {
   "type": "servers/getAll"
 }


Ajouter un nouveau serveur:

 {
   "type": "servers/add",
   "payload":
   {
     "url":"machine1",
     "name":"serveur",
     "username":"root",
     "password":"root",
     "port":22
   }
 }


Editer un serveur:

 {
   "type": "servers/edit",
   "payload":
   {
     "id":1,
     "url":"machine1",
     "name":"serveur",
     "username":"root",
     "password":"root",
     "port":22
   }
 }


Supprimer un serveur:

 {
   "type": "servers/remove",
   "payload":
   {
     "id":1
   }
 }

Informations

Voici la liste des messages possible de recevoir:


Information arrivant d'un serveur, ce message arrive toutes les 2 secondes par serveur:

{
  "type":"serverInfo",
   "payload":
   {
     "server": //SERVER INFOS,
     "data":
     {
       "cpu_info": //Beaucoup de trucs,
       "mem": //Beaucoup de trucs,
       "os_info": //Beaucoup de trucs,
       "fs": //Beaucoup de trucs
     }
   }
 }


Actualisation de la liste de serveur, ce message est envoyé après que chaque action de modification ai été effectué:

 {
   "type":"serverList",
   "payload": des serveurs
 }


Exception HTTP

L'authentification se fait en HTTP, voici les routes disponibles:

Pour s'enregistrer:

POST: http://localhost:3000/register BODY: {"username":"toto","password":"toto"}


Pour se connecter:

POST: http://localhost:3000/login BODY: {"username":"toto","password":"toto"}


Pour vérifier si l'on est connecté, et quel niveau d'autorisation nous avons:

GET: http://localhost:3000/authorized RETURN:

- 200 {"isAdmin":false/true} en cas de succès
- 401 si nous ne sommes pas identifiés


Pour se déconnecter:

GET: http://localhost:3000/logout

Backend

Ayant un client riche, le back-end fourni seulement une API pour éditer ou récupérer de l'information, aucun système de templating n'a été nécessaire. Nous avons utilisé node.js avec le framework express pour gérer notre serveur web. Une base de donnée Postgres avec l'ORM Sequelize ont été utilisés pour la persitance de la donnée.

Gestion de l'authentification et de l'autorisation

L'authentification est la seule partie de l'application à communiquer en HTTP avec le front-end. Une fois l'authentification établie, une websocket est ouverte par le front et toute la communication y passe. Un package node.js, appelé passport, nous a permis de mettre en place un système d'authentification facilement. Une gestion rapide des sessions et de la connexion des utilisateurs à été faite. (le code se trouve dans le fichier le-surveilleur-back/index.mjs). Les autorisation sont gérées côté back, une fois la websocket connecté, la session connait le niveau d'autorisation de l'utilisateur (administrateur/utilisateur) et empêche où non les requêtes. Ainsi seul l'administrateur peut récupérer la liste de tous les serveurs enregistrés sur l'application.

Persistance de la donnée

La persistance de la donnée est effectuée grâce à Postgres et Sequelize. Le modèle de donnée est entièrement défini dans Sequelize et est généré dans Postgres au démarrage de l'application. Grâce à l'ORM, la gestion de notre de donnée se fait sous la forme d'objets et de collections d'objets, facile à éditier et requêter. Voici un schéma du modèle de donnée:

Model-data.jpg


Connexion du front-end au front

Des websockets sont utilisées pour communiquer avec l'outil de monitor (voir plus bas pour plus d'information sur le monitor), et avec les différents clients. Pour que les clients reçoivent l'information des serveurs monitorés, il fallait relier ces websockets entre elle. Plusieurs clients peuvent vouloir l'information du même serveur. Il fallait donc un système d'abonnement, d'observable/observeurs pour résoudre se problème, ainsi, des websockets clients s'abonneraient aux informations des websockets de monitoring. Pour gérer ce problème, nous avons utilisé la librairie rxjs. Elle implémente la logique d'observable/observeurs. Ainsi nos websockets clients sont transformé en observeurs qui seront entrain d'attendre l'information des observables, les websockets de monitoring.

Rxjs.png

Monitor

Une troisième partie applicative à été développée afin de récupérer la donnée des serveurs à surveiller. Cette partie n'est pas déployée au démarrage de l'application, mais est exécutée à la demande, lors de l'ajout d'un serveur au sein du Surveilleur. Cette partie à été développée en Node.js et récupère la donnée grâce à la librairie https://github.com/sebhildebrandt/systeminformation. L'information est envoyée au back-end grâce à une websocket. Cette donnée est envoyé aux clients intéressé par l'information par le même moyen. Pour identifier la provenance de la donnée, l'application monitor s'identifie auprès du serveur grâce à un système de token. Ces tokens sont enregistrés dans la base de donnée et sont passé au lancement du script de monitor pour qu'il puisse s'identifier par la suite. Ce système permet d'éviter qu'un intrus ne vienne renseigner de la donnée en se faisant passer pour un serveur.

Tests

Afin de s'assurer que l'application fonctionne correctement tout au long du développement, nous avons réalisé des jeux de tests :

Des tests Selenium :

  • Inscription de l'utilisateur
  • Connexion de l'utilisateur

Nous avons mis une importance particulière sur la "bonne" utilisation de Selenium (aucune utilisation de la fonction sleep qui ne créé pas de tests déterministes). Nous avons utilisé Mocha comme framework de test au dessus de Selenium. Les ressources utilisées : tutoriel simple bonnes manières

Des tests Cucumber (requêtes au serveur via Super Agent) :

  • Ajout d'un serveur
  • Suppression d'un serveur

Screencast

Voici le lien vers la vidéo youtube présentant le projet: https://www.youtube.com/watch?v=A6eKOu7ACGU&feature=youtu.be