Mode opératoire — Lire les journaux bruts en direct avec LogAnalyzer, en lecture seule
Document autonome. Partie théorique, puis mise en œuvre telle qu’elle a été réalisée et vérifiée le 06/11/2026 sur
srv-supervision(10.0.30.15, Debian 13, zone ADM), phase 17 du suivi (SUIVI-TP.md), étape 67 de la documentation. Prérequis : les journaux de toutes les machines arrivent déjà dans la basesyslogdu cluster MariaDB/Galera (MO-15-Rsyslog-Galera.md), etsrv-supervisionatteint le cluster par son HAProxy local127.0.0.1:3306(MO-14-HAProxy-local-Galera.md).Dernière mise à jour : 06/11/2026
Sommaire
| § | Contenu |
|---|---|
| 1 | À quoi sert LogAnalyzer, à côté de Grafana |
| 2 | Les choix : vues en lecture seule, mot de passe Apache, port 8443 |
| 3 | Les vues SQL et le compte en lecture seule |
| 4 | Apache et PHP sur srv-supervision |
| 5 | Télécharger, vérifier et installer LogAnalyzer |
| 6 | S’en servir : vue en direct, recherche, et ajuster une règle |
| 7 | Le superviser |
| 8 | Pièges et checklist |
1 · À quoi sert LogAnalyzer, à côté de Grafana
| Grafana (tableau de production) | LogAnalyzer | |
|---|---|---|
| Question | « Est-ce que ça va ? » | « Que se passe-t-il, en ce moment, ligne par ligne ? » |
| Ce qu’il montre | ce que ses requêtes choisissent (connexions refusées, réussies, volume…) | tous les journaux stockés, bruts, du plus récent au plus ancien |
| Usage | surveiller, être alerté | parcourir sans rien chercher, repérer ce qui choque, rechercher simplement (machine, gravité, programme, texte) |
| Suite logique | une alerte | une règle ajustée : bruit coupé à la source, règle Wazuh, nouvelle alerte Grafana |
LogAnalyzer est une application web en PHP, écrite par Adiscon (l’éditeur de rsyslog), faite pour lire des
journaux rangés par rsyslog dans MySQL/MariaDB. Depuis 2026 elle est reprise par l’équipe rsyslog sur GitHub
(rsyslog/loganalyzer) : version 5.0.2 du 28/09/2026, avec des correctifs de sécurité (injections SQL, XSS,
sessions). L’ancien site d’Adiscon s’arrête à la 4.1.13 (2022) : prendre la version GitHub.
Principe à retenir — Grafana fait voir, LogAnalyzer fait comprendre : on ne filtre que le bruit qu’on a d’abord lu et reconnu comme inutile, jamais un échec.
Limite — Ce qui est filtré à la source (avant d’arriver en base) n’est jamais visible, ni dans Grafana ni dans LogAnalyzer.
2 · Les choix
| Choix | Décision | Pourquoi |
|---|---|---|
| Où | srv-supervision, qui reçoit déjà les journaux | pas de nouvelle machine ; accès au cluster déjà en place |
| Lecture des tables | deux vues SQL au format attendu par LogAnalyzer (« MonitorWare ») | nos tables ont un format maison (étape 48) ; les vues traduisent sans toucher aux tables, à rsyslog, à la purge ni à Grafana |
| Compte SQL | SELECT sur les vues seulement | LogAnalyzer ne peut ni écrire ni lire les tables directement |
| Identification | mot de passe Apache (Basic) devant tout le site ; pas de base d’utilisateurs LogAnalyzer | la base d’utilisateurs devrait être écrite dans le cluster et sauvegardée : inutile pour un seul administrateur |
| Port | HTTPS 8443, certificat auto-signé ; port 80 fermé | ne touche pas à Grafana (3000) ; le mot de passe ne circule jamais en clair |
| Accès réseau | zone d’administration seulement | aucune règle ajoutée : le poste d’admin arrive par Tailscale ; les autres zones n’ont aucune règle vers ADM:8443 |
3 · Les vues SQL et le compte en lecture seule
Contexte : sur un nœud du cluster (
srv-mysql-01), en root. Objectif : LogAnalyzer lit les journaux sans rien pouvoir modifier.
3.1 Vérifier le type des colonnes
mariadb -e "SHOW CREATE TABLE syslog.journaux\G"
facilite et gravite sont des nombres (tinyint) : c’est ce qu’attend LogAnalyzer (sinon, convertir dans la vue).
3.2 Créer les deux vues
Les noms de colonnes viennent du code de LogAnalyzer (src/include/constants_logstream.php, correspondance
monitorware) : ID, DeviceReportedTime, FromHost, Facility, Priority, SysLogTag, Message, InfoUnitID,
ProcessID, EventID, EventLogType, EventSource, EventCategory, EventUser, SystemID, Checksum.
CREATE OR REPLACE SQL SECURITY DEFINER VIEW syslog.la_journaux AS
SELECT id AS ID,
CONVERT_TZ(recu_le, '+00:00', 'Europe/Paris') AS ReceivedAt,
CONVERT_TZ(COALESCE(emis_le, recu_le), '+00:00', 'Europe/Paris') AS DeviceReportedTime,
hote AS FromHost, facilite AS Facility, gravite AS Priority,
programme AS SysLogTag, message AS Message,
1 AS InfoUnitID, NULL AS ProcessID, NULL AS EventID, NULL AS EventLogType,
NULL AS EventSource, NULL AS EventCategory, NULL AS EventUser, NULL AS SystemID,
CRC32(message) AS Checksum
FROM syslog.journaux;
Puis la même vue syslog.la_journaux_auth sur syslog.journaux_auth (journaux d’authentification).
| Détail | Pourquoi |
|---|---|
CONVERT_TZ(…, 'Europe/Paris') | les tables sont en UTC ; l’écran s’affiche à l’heure locale (fuseaux horaires chargés dans le cluster) |
Checksum calculé | si cette colonne est vide, LogAnalyzer peut chercher à l’écrire : avec une vue, il n’en a jamais besoin |
une vue par table, pas d’UNION | une UNION empêcherait d’utiliser les index sur plus d’un million de lignes |
Validation
mariadb -e "EXPLAIN SELECT * FROM syslog.la_journaux ORDER BY ID DESC LIMIT 50;"
key = PRIMARY, rows = 50 : la page lit 50 lignes, pas la table entière.
3.3 Le compte en lecture seule (mot de passe saisi par l’administrateur)
read -rsp "Mot de passe loganalyzer : " P; echo; printf "CREATE USER 'loganalyzer'@'10.0.30.15' IDENTIFIED BY '%s';\n" "$P" | mariadb; unset P
mariadb -e "GRANT SELECT ON syslog.la_journaux TO 'loganalyzer'@'10.0.30.15'; GRANT SELECT ON syslog.la_journaux_auth TO 'loganalyzer'@'10.0.30.15';"
Ne jamais écrire le mot de passe dans la commande elle-même : il resterait dans l’historique. read -rsp le
demande sans l’afficher ; printf est une commande interne du shell, il n’apparaît pas dans la liste des processus.
Validation (depuis srv-supervision, mot de passe demandé)
mariadb -h 127.0.0.1 -u loganalyzer -p -e "SELECT ID, DeviceReportedTime, FromHost FROM syslog.la_journaux ORDER BY ID DESC LIMIT 3;"
mariadb -h 127.0.0.1 -u loganalyzer -p -e "SELECT COUNT(*) FROM syslog.journaux;"
La première affiche 3 lignes à l’heure de Paris ; la seconde répond ERROR 1142 … SELECT command denied.
229-loganalyzer-compte-lecture-vues.png
4 · Apache et PHP sur srv-supervision
Contexte :
srv-supervision, en root. Objectif : un site HTTPS sur 8443, protégé par mot de passe.
4.1 Paquets
apt-get install -y --no-install-recommends apache2 libapache2-mod-php php-mysql php-gd php-mbstring
4.2 N’écouter que sur 8443
cp -p /etc/apache2/ports.conf /etc/apache2/ports.conf.orig
printf 'Listen 8443\n' > /etc/apache2/ports.conf
a2dissite 000-default && a2enmod ssl headers
Dans /etc/apache2/conf-available/security.conf : ServerTokens Prod et ServerSignature Off (Apache ne dit plus sa version).
4.3 Certificat et site
mkdir -p /etc/ssl/loganalyzer && openssl req -x509 -nodes -days 825 -newkey rsa:2048 -keyout /etc/ssl/loganalyzer/loganalyzer.key -out /etc/ssl/loganalyzer/loganalyzer.crt -subj "/CN=srv-supervision.sio.internal" -addext "subjectAltName=DNS:srv-supervision.sio.internal,IP:10.0.30.15"
/etc/apache2/sites-available/loganalyzer.conf (essentiel) :
<VirtualHost *:8443>
ServerName srv-supervision.sio.internal
DocumentRoot /var/www/loganalyzer
SSLEngine on
SSLCertificateFile /etc/ssl/loganalyzer/loganalyzer.crt
SSLCertificateKeyFile /etc/ssl/loganalyzer/loganalyzer.key
<Directory /var/www/loganalyzer>
Options -Indexes
AllowOverride None
AuthType Basic
AuthName "LogAnalyzer - lab"
AuthUserFile /etc/apache2/loganalyzer.htpasswd
Require valid-user
</Directory>
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
</VirtualHost>
a2ensite loganalyzer && apache2ctl configtest && systemctl restart apache2
4.4 Le mot de passe (par l’administrateur)
htpasswd -B /etc/apache2/loganalyzer.htpasswd ipfixe
-B : rangé chiffré en bcrypt. Fichier en 640 root:www-data. Mot de passe dans Bitwarden.
Validation (curl n’est pas installé : wget)
wget -qO- --no-check-certificate --user=ipfixe --ask-password https://127.0.0.1:8443/
Sans mot de passe : 401 ; avec : la page. ss -ltnp : Apache sur *:8443 seulement. 230-loganalyzer-apache-8443.png
5 · Télécharger, vérifier et installer LogAnalyzer
5.1 L’archive, et son empreinte
mkdir -p /root/telechargements/loganalyzer-5.0.2 && cd /root/telechargements/loganalyzer-5.0.2
wget https://github.com/rsyslog/loganalyzer/releases/download/v5.0.2/loganalyzer-5.0.2.tar.gz
echo "77477c075810b358241a05981cf06fe63e0138d4a68bd1d385567e9da555c293 loganalyzer-5.0.2.tar.gz" | sha256sum -c -
Réussi (6 875 678 octets). L’empreinte attendue est celle publiée sur la page de la version GitHub. Si elle
diffère : on n’installe pas.
5.2 Copier le site
mkdir extrait && tar -xzf loganalyzer-5.0.2.tar.gz -C extrait --no-same-owner
cp -a extrait/loganalyzer-5.0.2/src/. /var/www/loganalyzer/ && chown -R root:root /var/www/loganalyzer
touch /var/www/loganalyzer/config.php && chown root:www-data /var/www/loganalyzer/config.php && chmod 660 /var/www/loganalyzer/config.php
5.3 L’installeur web
Ouvrir https://10.0.30.15:8443/install.php depuis le poste d’administration ( le lien « here » de la page
d’erreur s’affiche en texte brut dans la 5.0.2 : H-88).
| Étape | Champ | Valeur |
|---|---|---|
| 3 | Message character limit for the main view | 200 |
| 3 | Automatically resolved IP Addresses (inline) | No (sinon une requête DNS par adresse lue) |
| 3 | Enable User Database | No |
| 7 | Name of the Source / Source Type | Journaux / MYSQL Native |
| 7 | Table type | MonitorWare |
| 7 | Database Host | 127.0.0.1 (pas localhost : ce serait le socket d’un MariaDB local, absent) |
| 7 | Database Name / Tablename | syslog / la_journaux |
| 7 | Database User / Password | loganalyzer / Bitwarden |
| 7 | Enable Row Counting | No (compter un million de lignes à chaque page chargerait la base) |
5.4 Seconde source, puis verrouiller
Dans config.php, recopier les lignes $CFG['Sources']['Source1'][…] en Source2, avec Name = 'Authentification'
et DBTableName = 'la_journaux_auth' (au lab, fait par un petit script, sans afficher le mot de passe). Puis :
php -l /var/www/loganalyzer/config.php
chmod 640 /var/www/loganalyzer/config.php && rm /var/www/loganalyzer/install.php
Validation — la page d’accueil affiche les derniers journaux, la liste « Select Source » propose Journaux et
Authentification. 231-loganalyzer-journaux-en-direct.png
6 · S’en servir
| Besoin | Où |
|---|---|
| Vue en direct | Set auto reload : un intervalle (30 s) |
| Recherche | champ Search : severity:warning, host:srv-mysql-01, syslogtag:sshd, ou un mot du message |
| Journaux d’authentification | Select Source → Authentification |
| Détail d’un message | l’icône à gauche du message |
Le cas du lab (06/11) — La première page était remplie par la sonde d’état Galera (Started galera-etat@… /
Deactivated successfully) : 77 % des journaux. Lu, reconnu comme du bruit, puis coupé à la source dans
[email protected] :
LogLevelMax=notice
SyslogLevel=warning
LogLevelMax=notice coupe les messages « info » de systemd sur ce service ; SyslogLevel=warning garde les erreurs du
script. Contrôle : 60 → 0 ligne par minute et par nœud, et une erreur simulée reste visible. Ensuite, la recherche
severity:warning a fait ressortir trois vrais échecs de la sonde à 05:50, jusque-là noyés dans le bruit. 232, 233
Les cas suivants (06/11 soir), repérés de la même façon (panneau « Lignes de journaux reçues » puis détail par
programme) : la recopie GLPI ouvrait une session SSH toutes les 30 s (→ une seule connexion réutilisée,
ControlPersist) ; deux tâches lancées chaque minute (→ LogLevelMax=notice) ; l’interface Wazuh en niveau « info »
(→ logging.quiet: true). Résultat : 1 270 → 70, 453 → 70, 645 → 125 lignes par heure. 242
Validation — après chaque réglage, mesurer avant / après et vérifier qu’une erreur passe toujours.
7 · Le superviser
Sur srv-metriques : un module blackbox qui attend un 401 (Apache répond et demande le mot de passe ; la
supervision n’a pas besoin du mot de passe), et un job Prometheus sonde_loganalyzer (service="loganalyzer").
http_401_insecure:
prober: http
timeout: 5s
http:
preferred_ip_protocol: "ip4"
valid_status_codes: [401]
tls_config:
insecure_skip_verify: true
wget -qO- 'http://127.0.0.1:9115/probe?module=http_401_insecure&target=https://10.0.30.15:8443/' | grep probe_success
probe_success 1. Dans Grafana, la ligne « LogAnalyzer » apparaît seule ; la règle « Service injoignable » la couvre.
234-loganalyzer-supervise.png
8 · Pièges et checklist
| Piège | Symptôme | Où c’est documenté |
|---|---|---|
| Lien de l’installeur affiché en texte brut | <a href="./install.php">here</a> visible, pas cliquable | Troubleshooting H-88 |
localhost comme hôte de base | connexion refusée (socket local absent) | §5.3 |
| Comptage des lignes activé | pages lentes, charge sur le cluster | §5.3 |
| Résolution DNS des IP activée | pages lentes, requêtes DNS inutiles | §5.3 |
config.php laissé inscriptible, install.php laissé en place | n’importe quel utilisateur authentifié peut relancer l’installation | §5.4 |
| Filtrer un message sans l’avoir lu | une erreur réelle disparaît avec le bruit | §6 |
Vues créées, EXPLAIN par la clé primaire
Compte SQL : vues lisibles, tables refusées (ERROR 1142)
Apache sur 8443 seul, port 80 fermé, 401 sans mot de passe
Empreinte SHA-256 de l'archive identique à celle publiée
Hôte de base 127.0.0.1, comptage des lignes et résolution DNS désactivés
Deux sources (Journaux, Authentification)
config.php en 640 root:www-data, install.php supprimé
Accès refusé depuis USERS et WEB
Sonde blackbox up, ligne « LogAnalyzer » dans Grafana
Mots de passe dans Bitwarden, registre des comptes à jour
La règle à retenir en une phrase : on lit d’abord tout, brut, puis on filtre à la source ce qu’on a reconnu comme du bruit — jamais un échec.
