L'analyse des journaux avec regex est une technique précieuse pour extraire des informations essentielles à partir de gros volumes de données de journaux. En utilisant cette méthode, on peut identifier efficacement les modèles, les erreurs et d'autres informations clés, rationalisant ainsi l'analyse des journaux et améliorant les performances du système.
BindPlane OP et un agent BindPlane (collecteur OpenTelemetry personnalisé)
Un fichier journal complexe nécessitant une analyse personnalisée
Connaissance de Regex
Une sélection d'échantillons de grumes qui correspondent à toutes les variations possibles.
(Facultatif) Un bon outil de test de regex tel que regex101.com
Dans cet article, nous examinerons les entrées de journal qui ressemblent aux exemples fournis ci-dessous. En utilisant un script pour écrire ces entrées dans un fichier avec les horodatages actuels, nous pouvons travailler efficacement avec des données en temps réel.
May 01 14:31:11 loggen-app10 test-system[712]: Mon May 01 14:31:11 UTC 2023|TEST_PROC|[result=Service Access Granted,service=https://portal.fakeuni.edu/uPortal/Login?...,requiredAttributes={}]|SERVICE_ACCESS_ENFORCEMENT_TRIGGERED|camillec1997|172.13.49.165|172.16.156.55 May 01 14:31:11 loggen-app10 test-system[712]: Mon May 01 14:31:11 UTC 2023|TEST_PROC|[result=Service Access Granted,service=https://portal.fakeuni.edu/uPortal/Login?...,requiredAttributes={}]|SERVICE_ACCESS_ENFORCEMENT_TRIGGERED|camillec1997|172.13.49.165|172.16.156.55 May 01 14:31:11 loggen-app10 test-system[712]: Mon May 01 14:31:11 UTC 2023|TEST_PROC|[event=success,timestamp=May 01 14:31:11 UTC 2023,source=RankedMultifactorAuthenticationProviderWebflowEventResolver]|AUTHENTICATION_EVENT_TRIGGERED|audit:unknown|172.25.178.6|172.16.156.55 May 01 14:31:11 loggen-app08 test-system[780]: Mon May 01 14:31:11 UTC 2023|TEST_PROC|Supplied credentials: [UsernamePasswordCredential(username=dawsonb, source=null, customFields={})]|AUTHENTICATION_SUCCESS|dawsonb|172.12.154.117|172.16.156.53 May 01 14:31:11 loggen-app10 test-system[712]: Mon May 01 14:31:11 UTC 2023|TEST_PROC|[event=success,timestamp=May 01 14:31:11 UTC 2023,source=RankedMultifactorAuthenticationProviderWebflowEventResolver]|AUTHENTICATION_EVENT_TRIGGERED|audit:unknown|172.25.178.6|172.16.156.55
Nous pouvons maintenant prendre la première entrée de journal ci-dessus et commencer à la disséquer en sections que nous souhaitons analyser.
Tout d'abord, nous remarquerons que nous avons deux horodatages :
**May 01 14:31:11** loggen-app10 test-system[712]: **Mon May 01 14:31:11 UTC 2023**|TEST_PROC|[result=Service Access Granted,service=https://portal.fakeuni.edu/uPortal/Login?...,requiredAttributes={}]|SERVICE_ACCESS_ENFORCEMENT_TRIGGERED|camillec1997|172.13.49.165|172.16.156.55
Le deuxième horodatage est celui que nous conserverons pour devenir notre horodatage officiel car il contient plus d'informations (le fuseau horaire et l'année sont utiles, alors que le jour de la semaine ne l'est pas vraiment) que nous pouvons utiliser pour atteindre la plus grande précision.
En décomposant cela, nous écrirons un modèle sans capture pour correspondre au premier horodatage.
^\w{3}\s\d{2}\s\d{2}:\d{2}:\d{2}\s+The caret “^”
au début de la ligne. Ceci est suivi de " \w{3}
", qui capture l'abréviation du mois à 3 lettres. Après le mois, se trouve « \s\d{2}\s
», qui consiste à saisir un espace ; les 2 chiffres, 0 rembourré jours du mois; et un autre espace. Enfin, nous avons " \d{2}:\d{2}:\d{2}\s+
» - pour une heure à 2 chiffres, une minute à 2 chiffres, une seconde à 2 chiffres et 1 espace ou plus.
Pour le deuxième horodatage, nous voulons un groupe de capture nommé. Cela deviendra un champ nommé dans le blob JSON des champs analysés.
(?P<timestamp>\w{3}\s\w{3}\s\d{2}\s\d{2}:\d{2}:\d{2}\s\w{3}\s\d{4})
Nous avons nommé ce groupe de capture "timestamp". Il contient la même expression régulière de base que l'autre horodatage, avec l'ajout de « \w{3}\s
» au début pour capturer le jour abrégé de la semaine, et « \s\w{3}\s\d{4}
» en remplaçant le « \s+
» à la fin afin de saisir le fuseau horaire à 3 caractères et l'année à 4 chiffres.
En allant plus loin dans le message de journal, nous voudrons analyser le nom d'hôte et le système :
May 01 14:31:11 **loggen-app10 test-system[712]**: Mon May 01 14:31:11 UTC 2023|TEST_PROC|[result=Service Access Granted,service=https://portal.fakeuni.edu/uPortal/Login?...,requiredAttributes={}]|SERVICE_ACCESS_ENFORCEMENT_TRIGGERED|camillec1997|172.13.49.165|172.16.156.55
Dans ce message, notre nom d'hôte est **loggen-app10**
et notre système est **test-system[712]**
. On ne m'a pas dit ce qu'était le [712] lorsque j'ai reçu ces journaux. J'ai supposé qu'il s'agissait du PID (ID de processus), mais j'ai choisi de ne pas l'analyser séparément pour le moment. L'analyse de ces champs est assez simple, et nous nous retrouvons avec : " (?P<hostname>[^\s]+)\s+(?P<system>.*?):\s+
". Nous avons une paire de groupes de capture nommés, nom d'hôte et système.
Le modèle pour le nom d'hôte est " [^\s]+
", ce qui signifie capturer n'importe quel caractère non-espace et en capturer autant que vous le pouvez (gourmand). Ceci est suivi de « \s+
», qui capture au moins un, mais autant que possible (encore une fois gourmand) espace(s).
Le groupe de capture pour le système est encore plus facile car après le ou les espaces, nous capturons tout jusqu'au caractère deux-points. Pour ce faire, nous utilisons « .*?
”. Ce que dit ce modèle, c'est capturer n'importe quel caractère 0 fois ou plus, mais ne soyez pas gourmand.
Après cela, nous avons le caractère deux-points et un autre 1 ou plusieurs espaces gourmands. Ceux-ci ne sont pas capturés mais sont nécessaires pour compléter entre cette section et la section d'horodatage que nous avons écrite ci-dessus.
Cela se traduit par le modèle de départ suivant :
^\w{3}\s*\d{2}\s*\d{2}:\d{2}:\d{2}\s+(?P<hostname>[^\s]+)\s+(?P<system>.*?):\s+(?P<timestamp>\w{3}\s\w{3}\s\d{2}\s\d{2}:\d{2}:\d{2}\s\w{3}\s\d{4})
Je ne vais pas passer par tout le processus de création de modèle, mais je continue à le fragmenter comme je l'ai fait ci-dessus.
Le motif final obtenu est :
^\w{3}\s*\d{2}\s*\d{2}:\d{2}:\d{2}\s+(?P<hostname>[^\s]+)\s+(?P<system>.*?):\s+(?P<timestamp>\w{3}\s\w{3}\s\d{2}\s\d{2}:\d{2}:\d{2}\s\w{3}\s\d{4})\|(?P<app_name>\w*)\|((?P<message_type>.*?):\s+)?\[?(?P<message>.*)\]?\|(?P<event_message>.*?)\|(?P<username>.*?)\|(?P<external_ip>[\d\.:]*)\|(?P<internal_ip>[\d\.:]*)
Ce modèle final inclut les groupes de capture nommés suivants, qui deviennent des champs dans notre blob JSON de données analysées :
Dans BindPlane, je crée une source de fichier. Cela regarde mon fichier journal généré dans /root/complex.log. J'ai sélectionné regex sous Parse Format. Sous le motif Regex, j'ai mis le motif final ci-dessus. J'ai coché la case Parse Timestamp, choisi Manual pour le format et mis les codes d'analyse temporelle pour le modèle de mon horodatage.
Une fois fait, ça ressemble à ça :
Pour terminer les tests, je dois créer une destination et y vérifier les données. Pour mon cas d'utilisation, j'ai choisi une destination Google Cloud Logging.
Une fois la configuration de mon pipeline terminée, je l'attache à un agent. Après avoir fonctionné pendant quelques instants, je clique sur le bouton "Afficher la télémétrie récente" sur la page de l'agent
La vue de télémétrie me montre le journal analysé suivant :
Enfin, je le vérifie également sur la console Google Cloud Logging :
Cela affiche la même entrée de journal et contient une charge utile JSON de l'objet de carte JSON de notre corps à partir de la vue de télémétrie récente.
Pour les prochaines étapes, je voudrais examiner l'analyse de cette valeur de message. Il s'agit souvent d'un ensemble clé/valeur ; comme dans les captures d'écran et les exemples ci-dessus. Je pourrais transmettre les données à un processeur qui analyse ces entrées clé/valeur dans une autre couche de JSON. Dans l'exemple ci-dessus, body.message
serait analysé en lui-même et vous pourriez avoir des champs tels que :
body.message.result=Service Access Granted body.message.service=https://innosoftfusiongo.com/sso/logi… body.message.principal=SimplePrincipal(id=dawsonb, attributes={mail=[[email protected]], eduPersonAffiliation=[Staff], ou=[Recreation/Student Rec Center], givenName=[Dawson], cn=[Dawson Branden], title=[Asst. Director], employeeNumber=[5000000], o=[Vice ChancellorStudent Affairs], fakeuniOrg=[Vice ChancellorStudent Affairs], casMFARequired=[YES], uid=[dawsonb], eduPersonPrimaryAffiliation=[Staff], fakeuniCid=[5000000], fakeuniSeparationDate=[99991231000000Z], UDC_IDENTIFIER=[dawsonb], sn=[Branden], organizationalStatus=[Staff]}) body.message.requiredAttributes=””
Même cela pourrait être analysé davantage, en plaçant body.message.principle également dans un analyseur clé/valeur.
Maintenant, quelqu'un est obligé de se demander: "Pourquoi n'avez-vous pas simplement utilisé l'analyse regex des sous-champs body.message également?" La réponse : c'est trop incohérent. L'expression régulière serait incroyablement et déraisonnablement complexe lorsque nous avons déjà la capacité d'analyser les paires clé/valeur.
De nombreuses formes de données peuvent être trouvées dans les fichiers journaux. Ces données doivent souvent être analysées pour les rendre à la fois plus lisibles pour les humains et plus faciles à utiliser pour l'automatisation et les outils plus tard dans la chaîne.
Alors que l'exemple avec lequel j'ai travaillé a été exécuté sur un simple fichier journal, les techniques décrites ici peuvent être utilisées sur n'importe quel flux de journal. En plus de l'analyse regex, BindPlane prend également en charge JSON ,XML , les paires clé/valeur et les valeurs séparées par des caractères. Avec l'utilisation de processeurs, ces analyseurs peuvent être enchaînés pour analyser les données intégrées et les manipuler dans un format utilisable.
Également publié ici.