Module Horizon - Documentation

  • Rédacteurs :
  • Date de modification : 08/10/20

1. Description

L'installation du module Horizon nécessite d'installer également des logiciels tiers. En effet, l'écosystème d'Horizon se compose:

  • du runtime node.js (qui héberge le code Horizon - et qui est le composant principal)
  • d'une base de données PostgreSql, pour le stockage des messages et de la configuration
  • d'un éventuel reverse proxy pour gérer les flux entrants des utilisateurs et la terminaison SSL
  • d'un plugin JPlatform pour l'intégration du système de chat au site (partage de l'authentification, des photos des membres, etc)

 

mceclip0 - 2020-09-30 15h12m48s

 

A noter
Le fonctionnement nécessite d'avoir au préalable correctement configuré l'entrepôt PKI. Voir la documentation Configuration de l'authentification par JWT.
Penser à valider son fonctionnement avant de poursuivre.

Horizon se base sur le protocole Websocket: WebSocket - Wikipedia. En cas d'impossibilité d'ouvrir une connexion websocket, il existe un mode dégradé en https (long pooling). Vérifier que les pare-feux et autres équipements réseaux autorisent ce protocole.

Si votre installation de JPlatform est inférieure au Service Pack 4 (JPlatform Evolution 10SP4 ou JReady 4SP9) alors vous devez installer également un plugin qui apporte les fichiers requis pour la gestion des notifications avec Firebase.

Horizon a besoin, au premier démarrage, de créer un Membre (utilisé pour le canal d'alerte Horizon Bot) ainsi qu'un espace de travail (appelé Horizon,) pour le dépôt de document. Ceci est fait automatiquement mais il convient de surveiller que ces créations n'engendrent pas un dépassement des limites de votre license.

Attention également à la limite d'espace disque affecté à l'espace de travail Horizon (quota de l'espace) car les dépots de documents des utilisateurs peuvent rapidement demander un espace disque important. Même si un mécanisme de purge permet de nettoyer les fichiers les plus anciens (90 jours par défaut, configurable), cet espace est à surveiller. Une première estimation de l'espace requis, basée sur un usage interne et assez intensif,  est d'environ 40 mo par utilisateur (avec une purge à 90 jours).

2. Choix d'architecture

Selon l'environnement JPlatform déjà en place, plusieurs possibilités se présentent. Les questions à se poser:

  • Est ce que les flux (messages) en provenance du navigateurs des utilisateurs doivent ils nécessairement passer par un frontal web (reverse proxy) ?
  • Si une base Postgres est déjà en place, pouvons nous l'utiliser pour y stocker les données d'Horizon ou faut-il procéder à l'installation d'un nouveau serveur ?

Ces réponses dépendent de la politique de sécurité, des SLA, du coût de mise en oeuvre, etc.

Ci-dessous 3 exemples d'architecture possibles qui permettent d'appréhender les différentes possibilités:

 

2.1 Option 1

mceclip1 - 2020-09-30 15h17m48s

 

Cette première possibilité utilise un frontal web mutualisé : pour JPlatform et pour les nouveaux flux liés à Horizon.

Les utilisateurs vont devoir maintenant accéder de manière sécurisé (https):

  • à des resources statiques (javascript, css) délivrées par le serveur Horizon, elles sont déployées sur /static
  • au websocket utilisé pour les échanges de messages: sur l'url /socket.io

Le serveur JPlatform va accéder au serveur Horizon:

  • uniquement via des api, afin d'intéragir avec les données et fonctionnalités de la messagerie instantanée (partage de l'authentification, photos des membres, etc.)
  • ces échanges sont établis de serveur à serveur uniquement et il est possible de configurer dans les proprietés du module Horizon une url précise
  • dans notre exemple ces échanges sont en http

Le serveur Horizon va accéder à JPlatform, au démarrage du serveur Horizon:

  • afin de récupérer des éléments de validation de l'authentification des utilisateurs
  • ces échanges sont également de nature serveur à serveur, ici en http
  • le serveur Horizon utilise un token JWT pour communiquer avec JPLatform via les Open Api JPlatform

 

2.2 Option 2

 

mceclip2 - 2020-09-30 15h18m28s

L'option 2 diffère dans la méthode d'accès aux ressources d'Horizon, ici les utilisateurs accèdent directement au serveur Horizon.

Afin de sécurisez les flux, il est possible dans ce cas de faire porter la terminaison SSL au serveur Horizon lui même et de se passer d'un reverse proxy.

 

 

2.3 Option 3

mceclip3 - 2020-09-30 15h19m15s

 

Ce dernier exemple propose de dédier un reverse proxy aux échanges Horizon, accèdé au travers d'un nom de sous domaine réservé "horizon.intranet.fr". Cette configuration est à privilégier lors des nouvelles installations.

Il est également possible de réaliser l'installation des 3 logiciels (reverse proxy, serveur Horizon et base de donnée) sur la même VM.

3. Procédure d'installation

3.1 Livrables

Pour installer et configurer la VM JPlatform

Pour installer et configurer le serveur Horizon

 

3.2 Principes généraux

Nous proposons de suivre les recommandations de normalisation des installations :

  • Linux: (Lien en accès restreint)
  • Windows: (Lien en accès restreint)

 

L'installation se réalise en 4 étapes :

  1. installation du plugin Horizon sur la vm JPlatform (sur vm-jpfm-prod)
  2. installation de la vm de base de données postgres pour Horizon (vm-hrzdb-prod)
  3. installation de la vm du logiciel Horizon (vm-hrz-prod)
  4. installation du reverse proxy pour les flux Horizon (vm-proxy-hrz-prod)

 

3.3 Configuration et installation sur le serveur JPlatform (vm-jpfm-prod)

Installation de module

 

  1. Installation du module PatchHorizonPlugin 10.0.3-20200731 si vous êtes < 10SP4
  2. Installation du Module Horizon
  3. Redémarrez le site.

 

Configurez le module:

mceclip4 - 2020-09-30 15h21m24s

 

Espace de travail des fichiers déposés dans Horizon: Cet espace est automatiquement créé, le bot Horizon est admin de cet espace. Si vous changez l'ID de cet espace, le bot Horizon doit être configuré comme admin du nouvel espace

Nombre de jours avant suppression des anciens messages: Les messages seront automatiquement supprimés lorsque le nombre de jours parametré sera dépassé. Une valeur vide ou égale à 0 aura pour effet de désactiver cette fonctionnalité.

URL du serveur pour accès aux API Horizon: Facultatif, à renseigner si vous voulez une url différente pour les communications entre JPlatform et le serveur Horizon

URL du serveur Horizon: Url qui sera utilisée par les utilisateurs pour accéder aux ressources du serveur Horizon

 

Activation des OpenApi

Vérifier que les OpenApi sont activés:

 

mceclip5 - 2020-09-30 15h21m52s

3.4 Installation de la base de données Postgres (vm-hrzdb-prod)

La procédure d'installation de demande pas d'action particulière, par rapport à une installation standard de Postgres pour JPlatform. A ce stade vous avez deux possibilités:

  • un serveur Postgres existe déjà dans votre infra, vous pouvez donc réutiliser cette installation pour y ajouter une nouvelle base et un nouvel utilisateur pour Horizon
  • vous réinstallez un nouveau serveur Postgres

Horizon est compatible avec PostgreSQL 9, 10, 11 et 12

Vous pouvez vous inspirer des fiches d'installation JPlatform déjà disponibles:
Debian / Ubuntu: (Lien en accès restreint)
RedHat / CentOs: (Lien en accès restreint)
Windows: (Lien en accès restreint)

Script de création d'une base et d'un utilisateur pour Horizon:

  
# CREATE USER horizondbuser;
# ALTER ROLE horizondbuser WITH CREATEDB;
# ALTER USER horizondbuser WITH ENCRYPTED PASSWORD 'horizondbpwd';
# CREATE DATABASE horizondb WITH OWNER horizondbuser ENCODING 'UTF8';
# \quit

 

3.5 Installation du logiciel Horizon (vm-hrz-prod)

Horizon est basé sur le runtime Node.js: https://nodejs.org/en/about/
Nous utiliserons la version LTS (Latest LTS Version: 12.18.4)

 

Génération d'un jeton JWT

Comme évoqué précedemment, un jeton JWT est nécessaire afin de permettre à Horizon de solliciter JPlatform. Créer un jeton via l'interface d'administration technique:

URL: http://vm-jpfm-prod:8080/rest/

 

mceclip6 - 2020-09-30 15h22m30s

Installation du serveur Horizon

Cf. Module Horizon - Fiche d'installation - Installation du serveur Horizon sous Linux

Note: les fiches d'installation pour Windows Server et Docker seront bientôt disponibles

3.6 Installation du reverse proxy pour les flux Horizon (vm-proxy-hrz-prod)

 

Avec Nginx

 

Ajouter un fichier de configuration /etc/nginx/conf.d/horizon-reverse.conf

server {
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/horizon.intranet.fr.cert;
ssl_certificate_key /etc/nginx/ssl/horizon.intranet.fr.key;

server_name horizon.intranet.fr;

access_log /var/log/nginx/horizon.access.log;
error_log /var/log/nginx/horizon.error.log;

location / {
proxy_pass http://vm-hrz-prod:5000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /socket.io/ {
proxy_pass http://vm-hrz-prod:5000/socket.io/;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

}

Avec Apache Httpd

 

Il faut au préalable activer les modules suivants:

LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule rewrite_module modules/mod_rewrite.so

 

Puis ajouter le virtualhost (pour les options 2 et 3)

<VirtualHost *:443>

# General setup for the virtual host
DocumentRoot "/usr/local/apache2/htdocs"
ServerName horizon.intranet.fr
ServerAdmin you@example.com

# SSL Engine Switch:
SSLEngine on

# Server Certificate:
SSLCertificateFile "/usr/local/apache2/conf/ssl/horizon.intranet.fr.cert"
SSLCertificateKeyFile "/usr/local/apache2/conf/ssl/horizon.intranet.fr.key"

# Horizon static files Proxy
ProxyPass /static/ http://vm-hrz-prod:5000/static/
ProxyPassReverse /static/ http://vm-hrz-prod:5000/static/

# Horizon WebSocket Proxy
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /(.*) ws://vm-hrz-prod:5000/$1 [P,L]
ProxyPass /socket.io/ http://vm-hrz-prod:5000/socket.io/
ProxyPassReverse /socket.io/ http://vm-hrz-prod:5000/socket.io/

</VirtualHost>

 

Et pour l'option 1, il faut ajouter cette configuration au virtualhost JPlatform existant:

<Location /static/>
ProxyPass http://vm-hrz-prod:5000/static/
ProxyPassReverse http://vm-hrz-prod:5000/static/
</Location>

<Location /socket.io/>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /(.*) ws://vm-hrz-prod:5000/$1 [P,L]
ProxyPass http://vm-hrz-prod:5000/socket.io/
ProxyPassReverse http://vm-hrz-prod:5000/socket.io/
</Location>

 

4. Exploitation

4.1 Démarrage du service

Horizon doit être démarré lorsque JPlatform est présent sinon Horizon ne démarre pas (un log d'erreur apparait en indiquant un timeout lors de la récupération du token jwt).

Il n'y a pas besoin de redémarrer Horizon lorsqu'on redémarre JPlatform. Horizon récupère les informations dont il a besoin au démarrage, ensuite il n'a plus besoin de JPlatform pour fonctionner.

4.2 Monitoring du service

Le service Horizon expose une api de vérification de l'état du service: /api/isAlive

L'appel à cet api retourne un code 200 si le service est opérationnel.

Il est également possible d'aciver l'exposition de métriques pour Prométheus. Voir [https://www.npmjs.com/package/socket.io-prometheus-metrics]

Voici la liste des métriques disponibles:

Name Help Labels
socket_io_connected Number of currently connected sockets  
socket_io_connect_total Total count of socket.io connection requests  
socket_io_disconnect_total Total count of socket.io disconnections  
socket_io_events_received_total Total count of socket.io recieved events event
socket_io_events_sent_total Total count of socket.io sent events event
socket_io_recieve_bytes Total socket.io bytes recieved event
socket_io_transmit_bytes Total socket.io bytes transmitted

event

 

Exemple du nombre de sockets connectés

 

 

5. Dépannage

Nous allons vérifier que les principaux flux sont opérationnels (bulles rouges de 1 à 5) :

 

mceclip7 - 2020-09-30 15h23m31s

5.1 Erreur lors du démarrage d'Horizon

Flux numéro 1 : Horizon ne peut se connecter à la base de données

  1. Vérifier que le serveur de base est atteignable
  2. Vérifier que Postgres autorise les connexions entrantes depuis le serveur Horizon (par défaut postgres est configuré uniquement pour écouter sur localhost)
  3. Vérifier que le user / mot de passe du user de la base de données sont valides

En cas d'impossibilité pour Horizon de se connecter à Postgres, un message dans les logs en indique la cause.

Exemples:

  • HostNotFoundError: impossible de trouver le serveur de bdd
  • ConnectionError : password authentication failed for user "horizondbuser"

 

Exemple de log:

 

Flux numéro 2 : Horizon ne peut se connecter aux api rest JPlatform

  1. Vérifier que la configuration JWT est correcte
  2. Vérifier que les OpenApi de JPlatform sont activés
  3. Vérifier que le token JWT est valable

Voici un exemple d'erreur:

Pour vérifier que le token généré permette d'accèder aux api rest :

  1. Connecter vous sur la Vm hébergeant le serveur Horizon (vm-hrz-prod)
  2. Exécuter la commande suivante:
curl -v -H 'Accept: application/json' -H "Authorization: Bearer TOKEN_JWT" http://vm-jpfm-prod:8080/rest/plugins/horizon/jwt/publickey

Résultat attendu:

 

5.2 Erreur dans les logs JPlatform

Flux numéro 3 : JPlatform ne peut pas se connecter aux api d'Horizon

  1. Vérifier que le serveur Horizon est atteignable depuis JPlatform
curl -v http://vm-hrz-prod:5000/api/isAlive
>> HTTP 200 OK

 

 

5.3 Erreur lors du lancement de l'application Horizon depuis le navigateur web

Le lancement de l'application Horizon revient à se rendre sur la page:

https://intranet.fr/plugins/HorizonPlugin/jsp/horizon.jsp

Deux flux doivent être en place: un premier (4) pour télécharger des fichiers statiques et un second (5) pour la connexion via le protocole websocket et donc l'échange des messages.

 

Flux numéro 4 : Le navigateur du client ne peut pas accéder aux ressources statiques d'Horizon. Ces ressources statiques (js et css) sont utilisées pour afficher l'application.

Problème constaté en cas d'échec de téléchargement des fichiers: la page blanche:

 

mceclip8 - 2020-09-30 15h24m51s

Ci-dessus un exemple de fichiers statiques qui ne sont pas téléchargés sur le poste client

 

Exemple de fichier requis :  https://horizon.intranet.fr/static/css/0.chunk.css

Vérifier que les fichiers sont accessibles, que le certificats SSL utilisé soit valide.

 

 

Flux numéro 5 : Le navigateur du client ne peut pas démarrer une connexion websocket ni long pooling

Problème 1: page noire avec le sablier qui tourne à l'infini:

mceclip9 - 2020-09-30 15h25m27s

Cause: l'accès à l'url /socket.io ne fonctionne pas (erreur http 404)

Vérifier la configuration du reverse proxy

 

Problème 2: le protocole websocket ne fonctionne pas. Cette erreur n'est pas directement visible de la part des utilisateurs car le mode dégradé (long pooling) est utilisé. Il convient cependant de vérifier lors de l'installation si le protocole websocket est en place et d'investiguer dans le cas contraire. 

Exemple d'utilisation du mode dégradé en http (long pooling). L'initialisation du protocol websocket a échoué (code http 400) et donc le reste des échanges :

mceclip0 - 2020-09-30 15h26m12s

 

Pour information, voici un exemple de connexion Websocket qui a fonctionné (passage vers le protocole websocket identifié avec le code http 101 cf https://developer.mozilla.org/fr/docs/Web/HTTP/Status/101) :

 

mceclip1 - 2020-09-30 15h26m36s

6. Ressources annexes

Tester le protocole Websocket
websocket.org Echo Test - Powered by Kaazing : https://www.websocket.org/echo.html

Protocole socket io
GitHub - socketio/socket.io-protocol: Socket.IO 1.0 Protocol specification and parser component / node.js module : https://github.com/socketio/socket.io-protocol

Protocole engine io
GitHub - socketio/engine.io-protocol : https://github.com/socketio/engine.io-protocol

Passer en debug socket.io
https://rethinkdb.com/blog/websocket-debugging