blog-image

Installation du bot go-neb pour Synapse-Matrix (arm64)

  • dHENRY
  • 25/04/2019
  • (Durée de lecture : 9 mn)

Update du 19/05/2019 - Cette procédure fonctionne aussi pour un Raspberry PI3 (armhf)

Ce bot permet l’intégration de nombreuses fonctionnalités, dont Giphy (Gifs animés) et l’extension du système d’alerte de l’application de monitoring Prometheus. Cette instruction peut aussi être appliqués à des plateformes amd64 (PC).

Le projet “go-neb” est hébergé ici https://github.com/matrix-org/go-neb, la documentation explique clairement comment installer le service. Cependant, la compilation ne s’est pas déroulée comme indiqué.

Compilation

J’ai rencontré deux problèmes : le package inclus dans la distribution “mattn/go-sqlite3” est impossible à compiler et indique ce type d’erreur :

github.com/matrix-org/go-neb/api/handlers
sqlite3-binding.c: In function ‘wherePathSolver’:
sqlite3-binding.c:130692:1: internal compiler error: in schedule_block, at haifa-sched.c:6593
 }

j’ai donc installé le paquet DEBIAN golang-github-mattn-go-sqlite3-dev en remplacement.
Le second problème est situé au niveau d’un “include” que le builder “go” ne trouve pas (détecté en lançant la commande :

go build /opt/go-neb/vendor/src/github.com/mattn/go-sqlite3/sqlite3.go

et présente l’erreur :

tmp/go-build020128959/command-line-arguments/_obj/sqlite3.cgo2.o: In function `_sqlite3_bind_blob': vendor/src/github.com/mattn/go-sqlite3/sqlite3.go:44: undefined reference to`sqlite3_bind_blob'
/tmp/go-build020128959/command-line-arguments/_obj/sqlite3.cgo2.o: In function `_sqlite3_bind_text': vendor/src/github.com/mattn/go-sqlite3/sqlite3.go:39: undefined reference to`sqlite3_bind_text'

En regardant le code, celui-ci fait mention d’un include

#include  <sqlite3-binding.h>

qui fait également appel à l’include :

#include <sqlite3.h>

non présent dans le package, mais disponible au travers du package DEBIAN libsqlite3-dev. Je pense qu’il s’agit simplement d’un problème de paramétrage du chemin de recherche des includes. Par facilité, j’ai choisi de copier le fichier manquant dans le package de distribution.

Préparation

apt install go-lang libsqlite3-dev golang-github-mattn-go-sqlite3-dev git
cd /opt
git clone https://github.com/matrix-org/go-neb
export GOPATH=/usr/lib/go-1.7/
export PATH=$PATH:$GOPATH/bin
go get github.com/constabulary/gb/...
cd go-neb
rm -r vendor/src/github.com/mattn/go-sqlite3
cp -R /usr/share/gocode/src/github.com/mattn/go-sqlite3 vendor/src/github.com/mattn/
cp /usr/include/sqlite3.h ./vendor/src/github.com/mattn/go-sqlite3/

Compilation du projet

gb build github.com/matrix-org/go-neb

Le binaire go-neb a été créé dans le répertoire “bin” du projet.

Répertoire la base de données sqlite3

Créer le répertoire db

mkdir db

Créer un installateur sous forme d’archive (tar.gz)

cd /opt/go-neb
tar cfz /root/go-neb.tgz /opt/go-neb/bin /opt/go-neb/db
Vous pouvez maintenant installer cette archive sur n'importe quel serveur arm64 :
Copier l'archive dans le répertoire** /root/** du serveur
cd /
tar xfz /root/go-neb.tgz
rm /root/go-neb.tgz

Fichier pour le service systemd

Ce service va communiquer avec le service Synapse-Matrix. Pour faire simple, j’ai installé le service sur le serveur qui héberge le service Synapse-Matrix.
Il écoute sur le port : TCP/4050 à l’adresse IP : localhost.
La base de données utilisée par ce service est de type sqlite3 et stockée dans le répertoire /opt/go-neb/db. Ces paramètres sont personnalisables dans le fichier qui suit.
Après mise en place, si vous devez modifier ce fichier, pensez toujours à exécuter la commande :

systemctl daemon-relaod
#Créer le groupe et user d'éxécution
addgroup go-neb

adduser --system --home /opt/go-neb/ --no-create-home --disabled-password  --shell /bin/nologin --ingroup go-neb go-neb

#Modification du propriétaire du répertoire d'installation
chown -R go-neb:go-neb /opt/go-neb

#Créer le fichier pour systemd
vi /etc/systemd/system/go-neb.service

et insérer ces instructions :

[Unit]
Description=Go-neb Bot For Synapse-Matrix server
After=network.target
[Service]
WorkingDirectory=/opt/go-neb
ExecStart=/opt/go-neb/bin/go-neb
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=go-neb
User=go-neb
Group=go-neb
Environment=BIND_ADDRESS=localhost:4050 DATABASE_TYPE=sqlite3 DATABASE_URL=db/go-neb.db?_busy_timeout=5000 BASE_URL=http://localhost:4050
Restart=always
RestartSec=10
StartLimitInterval=900
StartLimitBurst=3
[Install]
WantedBy=multi-user.target

Démarrage du service

systemctl start go-neb

# Vérifiez le lancement
tail -f /var/log/syslog

Exemple de réponse :

Apr 25 10:03:40 localhost systemd[1]: Started Go-neb Bot For Synapse-Matrix server.
Apr 25 10:03:40 localhost go-neb[5662]: time="2019-04-25T10:03:40+05:30" level=info msg="Go-NEB ({BindAddress:localhost:4050 DatabaseType:sqlite3 DatabaseURL:db/go-neb.db?_busy_timeout=5000 BaseURL:http://localhost:4050 LogDir: ConfigFile:})"

Le service est démarré et écoute sur le port 4050 de l’interface localhost :

#Vérification
netstat -ant|grep 4050

Activation du service au boot du serveur

systemctl enable go-neb

Paramétrage du Bot

Le bot doit pouvoir se connecter au serveur Synapse-Matrix. Créer un compte d’accès au service Synapse-Matrix, en adaptant les paramètres à votre configuration :

/opt/synapse/env/bin/register_new_matrix_user -c /opt/synapse/homeserver.yaml http://matrix.mondomaine.com

J’ai utilisé le compte “botgoneb” avec un mot de passe fort, et non admin.

Pour obtenir le token de ce nouvel utilisateur, utilisez la commande suivant en l’adaptant à votre configuration :

curl -X POST "http://matrix.mondomaine.com/_matrix/client/r0/login" -d '{"type":"m.login.password", "user":"botgoneb", "password":"[Mot de passe entré précédemment]"}'

Réponse de la commande si elle aboutit :

{
"access_token": "[TOKEN UTILISATEUR]",
"device_id": "XXXXXX",
"home_server": "matrix.mondomaine.com",
"user_id": "@botgoneb:matrix.mondomaine.com"
}

Le TOKEN de ce nouvel utilisateur est la valeur correspondant à la clé “access_token” de la réponse.

Connectez-vous au serveur Synapse-Matrix et exécutez la commande suivante, elle permet d’indiquer au service “go-neb” la manière de se connecter au service Synapse-Matrix

curl -X POST localhost:4050/admin/configureClient --data-binary '{
    "UserID": "@botgoneb:matrix.mondomaine.com",
    "HomeserverURL": "http://matrix.mondomaine.com",
    "AccessToken": "<TOKEN obtenu précédemment>",
    "Sync": true,
    "AutoJoinRooms": true,
    "DisplayName": "Bot goneb"
}'

La commande s’exécute normalement et renvoi une valeur au format JSON.

J’active pour le test la fonction “echo” du service “go-neb”

curl -X POST localhost:4050/admin/configureService --data-binary '{"Type": "echo","Id": "00001","UserID": "@botgoneb:matrix.mondomaine.com","Config": {} }'

La commande renvoi une valeur au format JSON, la fonction est activée.

Connectez-vous à un client Element, créer un salon et invitez le bot : @botgoneb:matrix.mondomaine.com**, sa réaction est immédiate, il est connecté. Tapez dans ce salon le message :

!echo hello world

Le bot répond en indiquant le texte saisi après la commande “!echo”.

Intégration Giphy - Serveur Synapse-Matrix

Activation de la fonction : Se connecter à la console du serveur disposant du service “go-neb”, et tapez la commande :

curl -X POST localhost:4050/admin/configureService --data-binary '{
    "Type": "giphy",
    "Id": "00002",
    "UserID": "@botgoneb:matrix.mondomaine.com",
    "Config": {"api_key":"dc6zaTOxFJmzC"}
}'

Je vous conseille de vous enregistrer chez Giphy (https://developers.giphy.com/) en créant une application (“Create app”). Ceci permet d’obtenir une clé API. La clé indiquée ci-avant est la clé publique Giphy, disposant d’un quota d’utilisation quotidien. Quand le quota est atteint, le serveur Giphy ne renvoit rien.

Inviter le bot dans le salon de votre choix, il se connecte immédiatement, et utilisez tapez le message : !giphy [mot recherché] Exemple : !giphy test
le bot renvoi la première image Gif retournée par Giphy.
Element.io permet de désactiver le démarrage automatique des Gifs, regardez dans les paramètres de votre compte.

Intégration AlertManager/Prometheus monitoring - Serveur Synapse-Matrix

Cette fonction permet au service AlertManager (partie du projet Prometheus - Système de monitoring développé par Soundcloud - installation cliquez-ici ), d’envoyer les alertes au système Synapse-Matrix. Cette partie n’est pas documentée sur le web, après plusieurs heures d’analyses du code source concernant le bot, et d’exécution de tests, cette partie est maintenant fonctionnelle.

Flux de communications Prometheus / Alertmanager / go-neb / Synapse-Matrix / Utilsateur Element.io

Pour séparer les fonctions de chaque bot, je crée un nouvel utilisateur sur Synapse-Matrix :@botPrometheus:matrix.mondomaine.com. Je récupère son token d’accès et l’ajoute au système go-neb (voir ci-avant).

Je crée le salon “Monitoring”, destiné à recevoir les message du bot : “#Monitoring:matrix.mondomaine.com”.
Récupérer l’ID interne de ce salon, en utilisant le client Element.io : Sélectionnez le salon, entrez sur “Setting”, “Advanced”, l’ID interne apparaît sous la forme : !qmElAGdFYCHoCJuaNt:matrix.mondomaine.com

Modification de l’adresse d’écoute du service go-neb

Le paramétrage original du service “go-neb”, indique une écoute à l’adresse “localhost”. Le service “Alertmanager”, situé sur un autre serveur, ne peut par conséquent pas joindre le service “go-neb”. Je vais donc changer la configuration du service “go-neb” afin que celui-ci écoute sur l’interface réseau connectée au réseau local.

vi /etc/systemd/system/go-neb.service
#Modifier la valeur des variables d'environnement : Environment=BIND_ADDRESS=localhost:4050 DATABASE_TYPE=sqlite3 DATABASE_URL=db/go-neb.db?_busy_timeout=5000 BASE_URL=http://localhost:4050

Remplacer “localhost” par l’adresse IP de ce serveur :

Environment=BIND_ADDRESS=192.168.1.12:4050 DATABASE_TYPE=sqlite3 DATABASE_URL=db/go-neb.db?_busy_timeout=5000 BASE_URL=http://192.168.1.12:4050

Enregistrer et quitter vi
Actualisez systemd et redémarrer go-neb :

systemctl daemon-reload
systemctl restart go-neb

Vérifiez avec :

netstat -ant|grep 4050

Ajouter les règles Firewall sur l’interface concernée : INPUT TCP/4050 et filtrer uniquement le serveur disposant du service Alertmanager.
Le service “Alertmanager” peut maintenant joindre le service “go-neb”.

Activation de la fonction alertmanager de go-neb

Cette fonction s’active en utilisant la commande curl suivante :

curl -X POST http://192.168.1.12:4050/admin/configureService --data-binary '{
"Type": "alertmanager",
"Id": "00003",
"UserID": "@botprometheus:matrix.mondomaine.com",
"Config": {"rooms":
            {"!qmElAGdFYCHoCJuaNt:matrix.mondomaine.com":
                {
"text_template":"Notification Prometheus [{{.Status}}]",
"html_template":"<h1>Notification Prometheus [{{.Status}}]</h1><hr/>{{- range .Alerts}}<div>Alerte : {{.Labels.alertname}}<br/>Instance : {{.Labels.instance}}<br/>Résumé : {{.Annotations.summary}}<br/>Sévérité : {{.Annotations.severity}}<br/>Description : {{.Annotations.description}}<br/>Date/heure de détection : {{.StartsAt}}<br/>{{if ne .EndsAt \"0001-01-01T00:00:00Z\" -}}Date/heure résolution: {{.EndsAt}}<br/>{{- end }}Url : {{.GeneratorUrl}}</div>{{- end}}","msg_type":"m.text"}}}}'

Les paramètres “text_template” et “html_template” sont de type “texte” dont la forme doit respecter la syntaxe concernant les templates “Golang”.
J’ai créé ces templates en me basant sur le code source Javascript utilisé pour l’intégration “Alertmanager” du service de messagerie instantanée “Rocketchat” (Voir l’installation ici).

Le système de templating “Golang” permet de créer des boucles, l’inclusion de conditions, etc, à l’image d’autre systèmes comme “Ejs pour Javascript”, ou “Twig” pour PHP.
Attention, je n’ai pas réussi à insérer le paramètres “style” dans les balises HTML, si quelqu’un souhaite se lancer… Le formatage des données n’est pas supporté ( Ex : .StartsAt | formatAsDate ).
Ce tuto m’a bien aidé : http://goinbigdata.com/example-of-using-templates-in-golang/

Deux templates “go-neb” pour Alermanager/Prometheus sont nécessaires :

  • Le template “text_template” est utilisé pour la notification système, le petit popup qui s’affiche quand l’application Element.io reçoit un message.
  • Le template “html_template” est utilisé pour construire le corps du message tel que vous le voyez apparaître dans le salon.

Attention le serveur va nous retourner l’adresse du webhook, qui sera utilisée par Alertmanager.
Exemple de données obtenues (format JSON) :

{"ID":"00003","Type":"alertmanager","OldConfig":{},"NewConfig":{"webhook_url":"http://localhost:4050/services/hooks/EDFEERdDM","rooms":....

L’adresse à fournir aux système de webhook de Alertmanager sera dans ce cas précis : http://localhost:4050/services/hooks/EDFEERdD

Modification de la configuration Alertmanager

J’indique à Alertmanager l’adresse du webhook à atteindre (url donnée par l’activation du service “alertmanager” de go-neb. Editer le fichier de configuration Alertmanager (/opt/alertmanager-[version]/alertmanager.yml), en ajoutant dans le bloc “receiver”, le bloc “webhook_config” :

Attention fichier YAML, n’utilisez pas les tabulations mais des espaces, pour indenter les lignes.

[..]
receivers:
- name: 'email'
email_configs:
- send_resolved: true
to:
[..]
webhook_configs:
- send_resolved: true
url: '**http://localhost:4050/services/hooks/EDFEERdDM**'

Recharger la configuration Alertmanager :

systemctl reload prometheus-alertmanager

Tester la notification

Exécuter les commandes qui suivent, en les adaptant à vos paramètres, et à partir du serveur qui héberge le service AlertManager (à cause des règles de Firewall).
Vous recevrez immédiatement un message dans la salon “#Monitoring:matrix.mondomaine.com”.

Test : Détection d’un défaut

curl -X POST http://192.168.1.12:4050/services/hooks/EDFEERdD --data-binary '{
"status": "firing",
"alerts": [{"labels" : {"alertname":"InstanceDown","instance" : "localhost:9100"},
"annotations": {"summary" : "Le service ne répond plus","severity":"Elevé","description":"Le service node_exporter est arrêté ou bien le serveur est éteint"},
"startsAt" : "2019-04-26T06:28:39.456891295+05:30",
"endsAt" : "0001-01-01T00:00:00Z",
"GeneratorUrl" : "http://test"}
]}'

L’heure de résolution n’apparaît pas dans l’alerte

Test : Défaut résolu (dispose d’une date réelle de fin - endsAt)

curl -X POST http://192.168.1.12:4050/services/hooks/EDFEERdD --data-binary '{
"status": "firing",
"alerts": [{"labels" : {"alertname":"InstanceDown","instance" : "localhost:9100"},
 "annotations": {"summary" : "Le service ne répond  plus","severity":"Elevé","description":"Le service node_exporter est  arrêté ou bien le serveur est éteint"},
"startsAt" : "2019-04-26T06:28:39.456891295+05:30",
"endsAt" : "2019-04-26T07:28:39.456891295+05:30",
"GeneratorUrl" : "http://test"}
]}'

L’heure de résolution apparaît dans l’alerte

Enjoy!!!

Compléments pour la production

Si vous démarrer plusieurs services go-neb pour une même instance Matrix, vous constaterez que chaque appel au service Go-neb, sera exécuté autant de fois que vous disposez de service go-neb actif. Si vous souhaitez mettre en place de la haute disponibilité pour ce service, mettez en place un système heartbeat, avec ipfailover.

Licence de ce document : Creative Commons (CC BY-NC-ND 4.0)

CETTE DOCUMENTATION EST LIVRÉE “EN L’ÉTAT”, SANS GARANTIE D’AUCUNE SORTE ET DISTRIBUÉE DANS UN BUT ÉDUCATIF EXCLUSIVEMENT. L’AUTEUR, CONTRIBUTEURS DE CETTE DOCUMENTATION OU ©MYTINYDC.COM NE SAURAIENT EN AUCUN CAS ÊTRE TENUS RESPONSABLES DES DOMMAGES DIRECTS OU INDIRECTS POUVANT RÉSULTER DE L’APPLICATION DES PROCÉDURES MISES EN ŒUVRE DANS CETTE DOCUMENTATION, OU DE LA MAUVAISE INTERPRÉTATION DE CE DOCUMENT.