Collecter les journaux de sécurité ServiceNow
Ce document explique comment envoyer des événements de sécurité ServiceNow à Google Security Operations à l'aide d'un flux de webhook. L'analyseur de sécurité ServiceNow est conçu pour les événements de sécurité ServiceNow Instance Security Center, tels que les échecs de connexion, les connexions SNC, les connexions administrateur, l'usurpation d'identité et l'élévation de sécurité (voir Événements de sécurité ServiceNow Instance Security Center). Une intégration ServiceNow publie chaque événement au format JSON sur un point de terminaison de webhook Google SecOps, où l'analyseur le normalise au modèle de données unifié (UDM).
L'analyseur reconnaît cinq valeurs d'événement : Failed Login, Admin Login, SNC Login, Impersonation et Security Elevation. Chaque valeur correspond à un événement ServiceNow enregistré dans la file d'attente sysevent. Ce document crée un flux de webhook, un Script Include qui publie sur le flux et quatre actions de script qui se déclenchent sur les enregistrements sysevent correspondants et appellent le Script Include.
Une fois cette configuration unique effectuée, ServiceNow transfère automatiquement chaque nouvel événement de sécurité à Google SecOps. Aucune autre action n'est requise de la part de l'administrateur.
Avant de commencer
Assurez-vous de remplir les conditions préalables suivantes :
- Une instance Google SecOps.
- Une instance ServiceNow avec un compte utilisateur disposant du rôle
adminou des droits d'accès à Définition du système > Inclure des scripts, Propriétés du système, Politique système > Événements > Actions de script et Registre. - Une instance ServiceNow existante avec Security Center activé. ISC n'est plus disponible à la vente et ne peut pas être activé sur de nouvelles instances.
- Accès privilégié à la console Google Google Cloud (pour la création de clés API).
Créer un flux de webhook dans Google SecOps
Les sections suivantes expliquent comment créer un flux de webhook dans Google SecOps.
Créer le flux
- Accédez à Paramètres SIEM> Flux.
- Cliquez sur Add New Feed (Ajouter un flux).
- Sur la page suivante, cliquez sur Configurer un seul flux.
- Dans le champ Nom du flux, saisissez un nom pour le flux (par exemple,
ServiceNow Security Events). - Sélectionnez Webhook comme type de source.
- Sélectionnez ServiceNow Security comme type de journal.
- Cliquez sur Suivant.
Spécifiez les valeurs des paramètres d'entrée suivants :
- Délimiteur de fractionnement : saisissez
\nlorsque l'intégration envoie plusieurs événements JSON par requête. Laissez ce champ vide si chaque requête contient un seul événement. - Espace de noms de l'élément : espace de noms de l'élément.
- Libellés d'ingestion : libellé appliqué aux événements de ce flux.
- Délimiteur de fractionnement : saisissez
Cliquez sur Suivant.
Vérifiez la configuration de votre nouveau flux sur l'écran Finaliser, puis cliquez sur Envoyer.
Générer et enregistrer la clé secrète
- Sur la page d'informations sur le flux, cliquez sur Générer une clé secrète.
Copiez et enregistrez la clé secrète dans un emplacement sécurisé.
Obtenir l'URL du point de terminaison du flux
- Accédez à l'onglet Détails du flux.
Dans la section Endpoint Information (Informations sur le point de terminaison), copiez l'URL du point de terminaison du flux. Le format d'URL est le suivant :
https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreateou, pour un point de terminaison régional :
https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreateEnregistrez cette URL pour une étape ultérieure.
Cliquez sur OK.
Créer une clé API Google Cloud
- Accédez à la page Identifiants de la console Google Google Cloud .
- Sélectionnez le projet associé à votre instance Google SecOps.
- Cliquez sur Créer des identifiants> Clé API.
- Cliquez sur Modifier la clé API pour la restreindre.
- Dans le champ Nom, saisissez un nom descriptif (par exemple,
ServiceNow Webhook API Key). Sous Restrictions relatives aux API :
- Sélectionnez Restreindre la clé.
- Dans la liste Sélectionner des API, sélectionnez API Google SecOps.
Cliquez sur Enregistrer.
Copiez la clé API et enregistrez-la dans un endroit sûr.
Stocker les identifiants Google SecOps dans ServiceNow
Stockez l'URL du point de terminaison et les identifiants en tant que propriétés système ServiceNow afin que le code d'intégration ne contienne pas de secrets.
- Dans ServiceNow, accédez à Propriétés système > sys_properties.list.
Cliquez sur Nouveau et fournissez les informations de configuration suivantes :
- Nom :
x_chronicle.endpoint_url - Valeur : collez l'URL du point de terminaison du flux.
- Type :
string
- Nom :
Cliquez sur Envoyer.
Cliquez sur Nouveau et fournissez les informations de configuration suivantes :
- Nom :
x_chronicle.api_key - Valeur : collez la clé API Google Cloud .
- Type :
password2
- Nom :
Cliquez sur Envoyer.
Cliquez sur Nouveau et fournissez les informations de configuration suivantes :
- Nom :
x_chronicle.secret_key - Valeur : collez la clé secrète du flux Google SecOps.
- Type :
password2
- Nom :
Cliquez sur Envoyer.
Créer l'inclusion de script utilitaire de webhook
Cette inclusion de script publie une charge utile JSON sur le point de terminaison du webhook Google SecOps à l'aide de l'API à portée sn_ws.RESTMessageV2 de ServiceNow. La clé API et la clé secrète sont envoyées en tant qu'en-têtes HTTP.
- Accédez à Définition du système> Inclure les scripts.
- Cliquez sur New (Nouveau).
Fournissez les informations de configuration suivantes :
- Nom :
ChronicleWebhookUtil - Nom de l'API :
ChronicleWebhookUtil - Client callable (Appelable par le client) : décochez la case
- Actif : coché
- Nom :
Dans le champ Script, saisissez le code suivant :
var ChronicleWebhookUtil = Class.create(); ChronicleWebhookUtil.prototype = { initialize: function() { this.endpointURL = gs.getProperty('x_chronicle.endpoint_url'); this.apiKey = gs.getProperty('x_chronicle.api_key'); this.secretKey = gs.getProperty('x_chronicle.secret_key'); }, // payload: a plain object whose keys match the required JSON contract. sendEvent: function(payload) { try { if (!this.endpointURL || !this.apiKey || !this.secretKey) { gs.error('[Chronicle] Missing configuration. Check System Properties: x_chronicle.*'); return false; } var request = new sn_ws.RESTMessageV2(); request.setEndpoint(this.endpointURL); request.setHttpMethod('POST'); request.setRequestHeader('Content-Type', 'application/json'); request.setRequestHeader('X-goog-api-key', this.apiKey); request.setRequestHeader('X-Webhook-Access-Key', this.secretKey); request.setRequestBody(JSON.stringify(payload)); var response = request.execute(); var statusCode = response.getStatusCode(); if (statusCode == 200 || statusCode == 201 || statusCode == 204) { gs.info('[Chronicle] Event sent: ' + payload.event + ' | Status: ' + statusCode); return true; } gs.error('[Chronicle] Failed to send event: ' + payload.event + ' | Status: ' + statusCode + ' | Response: ' + response.getBody()); return false; } catch (ex) { gs.error('[Chronicle] Exception sending event: ' + ex.message); return false; } }, type: 'ChronicleWebhookUtil' };Cliquez sur Envoyer.
Vérifier le registre des événements
Une action de script ne se déclenche que si son nom d'événement existe dans la table Event Registry (sysevent_register). ServiceNow fournit les cinq événements utilisés par cette intégration prêts à l'emploi. Toutefois, il est préférable de vérifier, car une entrée manquante ne génère aucune erreur et l'action de script ne s'exécute jamais.
- Dans ServiceNow, accédez à System Policy> Events> Registry (
sysevent_register.list). Filtrez la colonne Nom de l'événement pour chacune des entrées suivantes et vérifiez qu'un enregistrement existe :
loginlogin.failedimpersonation.startsecurity.elevated_role.enabled
Si une entrée est manquante, cliquez sur Nouveau, définissez le champ Nom de l'événement sur la valeur manquante, définissez Table sur
Global [global], puis cliquez sur Envoyer.
Créer les actions de script
Chaque action de script s'abonne à un nom d'événement ServiceNow. Lorsque ServiceNow insère un enregistrement correspondant dans la file d'attente sysevent, l'action de script s'exécute, lit les paramètres d'événement et appelle ChronicleWebhookUtil pour publier la charge utile.
L'analyseur est associé aux événements ServiceNow suivants :
Valeur event de l'analyseur |
Nom de l'événement ServiceNow | Déclencheur |
|---|---|---|
Failed Login |
login.failed |
Échec de la tentative de connexion (quelle que soit la méthode d'authentification). |
Admin Login |
login |
Connexion réussie d'un utilisateur disposant du rôle admin. |
SNC Login |
login |
Connexion réussie d'un utilisateur disposant du rôle snc_external. |
Impersonation |
impersonation.start |
Un administrateur commence à se faire passer pour un autre utilisateur. |
Security Elevation |
security.elevated_role.enabled |
Un utilisateur passe au rôle security_admin ou à un autre rôle à privilèges élevés. |
login et login.failed définissent parm1 sur le nom d'utilisateur et parm2 sur l'adresse IP source. Les autres événements suivent la même convention parm1/parm2, mais leur contenu exact dépend de votre version de ServiceNow. Ouvrez l'entrée de registre de chaque événement et vérifiez que la description des paramètres correspond au script décrit plus loin. Ajustez les références parm1 ou parm2 si votre registre est différent.
Créer l'action de script d'échec de connexion
- Accédez à System Policy > Events > Script Actions (Règles système > Événements > Actions de script).
- Cliquez sur New (Nouveau).
Fournissez les informations de configuration suivantes :
- Nom :
Chronicle - Failed Login - Nom de l'événement :
login.failed - Actif : coché
- Nom :
Dans le champ Script, saisissez le code suivant :
(function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) { new ChronicleWebhookUtil().sendEvent({ event: 'Failed Login', event_created: event.sys_created_on.getValue(), user: event.parm1.toString(), ip_address: event.parm2.toString() }); })(current, event);Cliquez sur Envoyer.
Créer l'action de script de connexion
Cette action de script se déclenche à chaque connexion réussie et transmet l'enregistrement uniquement lorsque l'utilisateur connecté possède le rôle admin ou snc_external. Le champ event est défini en conséquence.
- Accédez à System Policy > Events > Script Actions (Règles système > Événements > Actions de script).
- Cliquez sur New (Nouveau).
Fournissez les informations de configuration suivantes :
- Nom :
Chronicle - Login - Nom de l'événement :
login - Actif : coché
- Nom :
Dans le champ Script, saisissez le code suivant :
(function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) { var userName = event.parm1.toString(); var ipAddress = event.parm2.toString(); var user = new GlideRecord('sys_user'); if (!user.get('user_name', userName)) { return; } function hasRole(roleName) { var role = new GlideRecord('sys_user_has_role'); role.addQuery('user', user.sys_id); role.addQuery('role.name', roleName); role.query(); return role.next(); } var eventValue; if (hasRole('snc_external')) { eventValue = 'SNC Login'; } else if (hasRole('admin')) { eventValue = 'Admin Login'; } else { return; } new ChronicleWebhookUtil().sendEvent({ event: eventValue, event_created: event.sys_created_on.getValue(), user: userName, ip_address: ipAddress }); })(current, event);Cliquez sur Envoyer.
Créer l'action de script d'emprunt d'identité
- Accédez à System Policy > Events > Script Actions (Règles système > Événements > Actions de script).
- Cliquez sur New (Nouveau).
Fournissez les informations de configuration suivantes :
- Nom :
Chronicle - Impersonation - Nom de l'événement :
impersonation.start - Actif : coché
- Nom :
Dans le champ Script, saisissez le code suivant :
(function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) { new ChronicleWebhookUtil().sendEvent({ event: 'Impersonation', event_created: event.sys_created_on.getValue(), user: event.parm1.toString(), // impersonator snc_user: event.parm2.toString() // impersonated user }); })(current, event);Cliquez sur Envoyer.
Créer l'action de script d'élévation de sécurité
- Accédez à System Policy > Events > Script Actions (Règles système > Événements > Actions de script).
- Cliquez sur New (Nouveau).
Fournissez les informations de configuration suivantes :
- Nom :
Chronicle - Security Elevation - Nom de l'événement :
security.elevated_role.enabled - Actif : coché
- Nom :
Dans le champ Script, saisissez le code suivant :
(function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) { new ChronicleWebhookUtil().sendEvent({ event: 'Security Elevation', event_created: event.sys_created_on.getValue(), user: event.parm1.toString() }); })(current, event);Cliquez sur Envoyer.
Valider l'intégration
Utilisez l'une des approches suivantes.
Valider à l'aide d'un événement synthétique
Pour tester chaque action de script immédiatement sans attendre un véritable événement de sécurité, procédez comme suit pour mettre l'événement en file d'attente à partir d'un script d'arrière-plan :
- Dans ServiceNow, accédez à System Definition > Scripts - Background (Définition du système > Scripts - Arrière-plan).
Dans le champ Exécuter le script, saisissez l'une des lignes suivantes, puis cliquez sur Exécuter le script :
gs.eventQueue('login.failed', null, 'test.user', '203.0.113.45'); gs.eventQueue('login', null, 'admin', '203.0.113.45'); gs.eventQueue('impersonation.start', null, 'admin', 'test.user'); gs.eventQueue('security.elevated_role.enabled', null, 'admin', 'security_admin');Patientez jusqu'à une minute pour que le job Event Manager traite la file d'attente.
Valider à l'aide d'un événement réel
Pour vérifier l'intégration, générez l'un des événements de sécurité mappés suivants dans ServiceNow :
- Échec de la connexion : ouvrez
/login.dodans une fenêtre de navigation privée et saisissez un mot de passe incorrect. - Connexion administrateur : connectez-vous avec un utilisateur disposant du rôle
adminà partir d'une adresse IP différente de celle que vous utilisez habituellement. - Usurpation d'identité : empruntez l'identité d'un autre utilisateur depuis un compte administrateur.
- Élévation de sécurité : passez au rôle
security_adminà partir d'un utilisateur disposant du rôleadmin.
Confirmer le transfert
- Dans ServiceNow, accédez à Stratégie système> Événements> Journal des événements (
sysevent.list), puis vérifiez qu'un enregistrement portant le nom d'événement correspondant s'affiche. - Dans ServiceNow, accédez à Journaux système > Journal système > Tous et vérifiez qu'un message d'information
[Chronicle] Event sent: ...s'affiche avec l'état 200, 201 ou 204. Un message[Chronicle] Failed to send eventou[Chronicle] Exception sending eventindique un problème d'identifiants ou de connectivité. - Dans Google SecOps, exécutez une recherche UDM pour
metadata.vendor_name = "SERVICENOW"etmetadata.product_name = "SERVICENOW_SECURITY". - Vérifiez que l'événement s'affiche avec
metadata.event_typedéfini surUSER_LOGINouUSER_CHANGE_PERMISSIONS, et queprincipal.user.useridest renseigné.
Référence des méthodes d'authentification
Les flux de webhook Google SecOps acceptent la clé API et la clé secrète en tant qu'en-têtes HTTP ou paramètres de requête d'URL. Ce guide utilise la méthode des en-têtes, car sn_ws.RESTMessageV2 est compatible avec les en-têtes personnalisés, ce qui permet de conserver les identifiants en dehors des URL et des journaux d'accès au serveur.
En-têtes utilisés dans ce guide :
X-goog-api-key: clé API Google Cloud pour l'API Google SecOps.X-Webhook-Access-Key: clé secrète du flux générée par Google SecOps.
Si une intégration ne peut pas envoyer d'en-têtes personnalisés, ajoutez plutôt les identifiants à l'URL du point de terminaison :
<ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>
Limites et bonnes pratiques concernant les webhooks
| Limite | Valeur |
|---|---|
| Taille maximale de la requête | 4 Mo |
| RPS (requêtes par seconde) max. | 15 000 |
| Délai avant expiration de la requête | 30 seconds |
| Comportement de nouvelle tentative | Automatique avec intervalle exponentiel entre les tentatives |
Pour contrôler le volume, n'envoyez que les événements de sécurité dont vos détections ont besoin et regroupez plusieurs événements par requête avec le délimiteur de fractionnement \n lorsque la source produit des événements par rafales.
Pour en savoir plus sur les flux Google SecOps, consultez la documentation sur les flux Google SecOps. Pour en savoir plus sur les exigences associées à chaque type de flux, consultez Configuration des flux par type.
Si vous rencontrez des problèmes lors de la création de flux, contactez l'assistance Google SecOps.
Table de mappage UDM
| Champ du journal | Mappage UDM | Logique |
|---|---|---|
event |
extensions.auth.type |
Mappé : "Failed Login", "SNC Login", "Admin Login", "Impersonation" → MACHINE |
event_created |
metadata.event_timestamp |
Analysé en tant que yyyy-MM-dd HH:mm:ss |
event_type |
metadata.event_type |
Renommé/Mappé |
event |
metadata.product_event_type |
Mappé lorsque event != `` |
ip_address |
principal.ip |
Fusionné |
user |
principal.user.userid |
Mappé lorsque user != `` |
created_by |
target.user.userid |
Mappé lorsque created_by != `` |
snc_user |
target.user.userid |
Mappé lorsque snc_user != `` |
timestamp |
event1.idm.read_only_udm.metadata.event_timestamp |
Mappé à partir du journal des modifications |
data.sys_id |
event1.idm.read_only_udm.metadata.product_log_id |
Mappé à partir du journal des modifications |
data.message_data |
event1.idm.read_only_udm.metadata.description |
Mappé à partir du journal des modifications |
data.source |
event1.idm.read_only_udm.principal.resource.name |
Mappé à partir du journal des modifications |
source |
event1.idm.read_only_udm.additional.fields |
Mappé à partir du journal des modifications |
data.sys_created_on |
event1.idm.read_only_udm.metadata.collected_timestamp |
Mappé à partir du journal des modifications |
data.sys_created_by |
event1.idm.read_only_udm.principal.user.userid |
Mappé à partir du journal des modifications |
data.user |
event1.idm.read_only_udm.principal.user.userid |
Mappé à partir du journal des modifications |
source_instance |
event1.idm.read_only_udm.principal.namespace |
Mappé à partir du journal des modifications |
data.role |
event1.idm.read_only_udm.target.resource.attribute.roles |
Mappé à partir du journal des modifications |
data.granted_by |
event1.idm.read_only_udm.target.user.userid |
Mappé à partir du journal des modifications |
data.level |
event1.idm.read_only_udm.security_result.severity |
Mappé à partir du journal des modifications |
data.state |
event1.idm.read_only_udm.security_result.action_details |
Mappé à partir du journal des modifications |
Journal des modifications
Afficher le journal des modifications pour ce parseur
Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.