Créer un connecteur personnalisé

Compatible avec :

Utilisez ce document pour découvrir comment le SDK SOAR crée des intégrations personnalisées pour les outils tiers qui ne sont peut-être pas disponibles dans le Hub de contenu. Les connecteurs sont utilisés pour ingérer des données provenant de sources de données qui, généralement, mais pas toujours, disposent d'une file d'attente d'alertes. Les demandes, les alertes et les événements sont créés dans la plate-forme à l'aide de l'interaction du connecteur avec l'application Google SecOps. Un connecteur ingère les données d'événement de base, les attribue à une alerte, puis envoie l'alerte à l'application Google SecOps et à son pipeline de traitement des données.

Pour créer un connecteur personnalisé, suivez ces étapes générales :

  1. Créez une classe Manager qui contient la logique d'API pour l'outil tiers.
  2. Créez le connecteur à l'aide de l'IDE.

Créer le gestionnaire

Pour créer un connecteur, la première étape consiste à créer une classe Manager qui contient toute la logique d'API requise pour la technologie que vous intégrez. Par exemple, l'intégration Netskope dans Google SecOps inclut un gestionnaire prédéfini. Ce gestionnaire contient toute la logique nécessaire pour interagir avec l'API Netskope et peut être utilisé comme modèle pour votre propre implémentation.

Créer le connecteur

Dans l'IDE, créez un connecteur en suivant les instructions de la section Créer une intégration personnalisée. L'IDE génère un modèle générique qui inclut des commentaires de code décrivant la structure et les exigences de base d'un script de connecteur.

Bien que la logique du connecteur puisse varier, le processus comprend généralement les étapes de base suivantes :

  1. Utilisez l'API de l'outil tiers pour récupérer les alertes, les détections ou les événements. Dans le cas de Netskope, cette opération est gérée par la méthode get_alerts(). Pour éviter les doublons d'alertes, envoyez une requête par code temporel et mettez-la à jour après chaque exécution.
  2. Créez une alerte à l'aide de la classe AlertInfo (anciennement CaseInfo), en attribuant tous les champs obligatoires.
  3. Récupérez et aplatissez les données d'événement associées pour éviter les problèmes liés aux listes et aux dictionnaires imbriqués, puis ajoutez les événements aplatis à l'alerte.
  4. Triez les alertes par heure et stockez le dernier code temporel à utiliser dans la requête suivante.

Importations et SDK

Chaque connecteur doit effectuer les opérations suivantes :

  • Importez la classe SiemplifyConnectorExecution depuis SiemplifyConnectors. Cette classe est généralement instanciée dans la fonction main() du connecteur. Le script se termine lorsque cet objet transmet une liste d'alertes à l'application Google SecOps à l'aide de la méthode return_package().
  • Importez la classe AlertInfo depuis SiemplifyConnectorsDataModel. L'instanciation de cette classe crée l'objet d'alerte. Dans cet exemple, il est renommé SiemplifyAlertInfo pour éviter toute confusion avec les objets d'alerte intégrés du système source (Netskope), où ce renommage est facultatif.

Le module SiemplifyUtils fournit des méthodes couramment utilisées pour la journalisation, la gestion des formats de données, les conversions de temps, etc. Nous vous recommandons d'importer output_handler, dict_to_flat et unix_now, car ils sont essentiels pour les fonctionnalités de base, y compris la gestion du temps.

La plupart des connecteurs importent également la classe Manager de l'intégration. Certaines intégrations incluent plusieurs responsables. D'autres bibliothèques Python standards peuvent également être importées, en fonction de votre cas d'utilisation.

Variables constantes

Il est recommandé de déclarer quelques variables constantes pour une utilisation ultérieure.

custconnector2
Figure 1 : Variables constantes

Exemple de script permettant de créer l'alerte Google SecOps

Une alerte est créée en instanciant un objet de la classe AlertInfo, comme indiqué précédemment. Dans cet exemple, il est renommé SiemplifyAlertInfo() pour éviter toute confusion avec le système source. L'objet alert_info inclut plusieurs propriétés requises qui doivent être définies pour que l'application traite correctement l'alerte. La fonction build_alert_info reçoit une alerte Netskope (au format JSON brut, reçue de l'API) et l'objet Siemplify comme entrées. Il analyse ensuite l'alerte Netskope et attribue les valeurs pertinentes aux champs `alert_info`.

Cette fonction utilise également des constantes définies précédemment. Toutes les propriétés définies sur l'objet alert_info font partie de l'objet d'alerte dans l'application Google SecOps.

La ligne 35 (dans la figure 2) met en évidence une partie importante de ce processus : l'alerte est aplatie à l'aide de la méthode dict_to_flat, puis ajoutée à la propriété events.

custconnector3
Figure 2 : Exemple de script pour créer une alerte
 

Une alerte peut contenir plusieurs événements. Dans ce cas, vous devez inclure une logique pour gérer chaque événement de manière appropriée. Dans cet exemple, chaque alerte ne contient qu'un seul événement. L'implémentation par défaut est donc suffisante.

La méthode dict_to_flat est utilisée pour aplatir la structure JSON brute. Cela permet d'éviter les problèmes liés aux listes et aux dictionnaires imbriqués. Les paires clé-valeur aplaties sont des versions légèrement modifiées des paires d'origine.

Examinez la logique suivante dans la figure 2 :

  • display_id se voit attribuer une valeur générée aléatoirement à l'aide de la bibliothèque uuid. Les alertes Netskope ne fournissent pas de champ UUID, mais si l'un était disponible, il pourrait être utilisé à la place.
  • ticket_id est défini pour correspondre à display_id. Les deux champs doivent être uniques par alerte dans le système. Cette unicité est assurée par la génération d'un UUID aléatoire.
  • name correspond au nom de l'alerte et s'affiche dans l'interface utilisateur graphique.
  • rule_generator fait référence à la règle qui a généré l'alerte dans le système source. Ce champ n'est pas toujours présent dans les données brutes. Si elle est manquante, vous pouvez attribuer n'importe quelle valeur de chaîne, mais elle ne doit pas être laissée vide.
  • start_time et end_time représentent les codes temporels de l'alerte. Dans cet exemple, l'alerte Netskope fournit un code temporel d'epoch Unix, qui doit être multiplié par 1 000 pour être converti en millisecondes. Il s'agit du format attendu pour Google SecOps. Si la source utilise un autre format, vous devez la convertir. Consultez le module SiemplifyUtils.py pour obtenir des méthodes utiles de conversion du temps.
  • priority : l'application Google SecOps attribue une priorité à chaque cas en fonction de la priorité de son alerte. L'API Google SecOps mappe les valeurs numériques aux libellés visuels à l'aide du schéma suivant, où la valeur entière est transmise dans le connecteur : {"Informative": -1, "Low": 40, "Medium": 60, "High": 80, "Critical": 100} où la valeur entière est celle transmise dans le connecteur. Par exemple, si vous transmettez la valeur 100, l'alerte est marquée comme critique dans l'interface utilisateur graphique. Dans ce connecteur, une fonction d'assistance supplémentaire mappe les valeurs de gravité de Netskope à cette échelle de priorité à l'aide de la constante `SEVERITY_MAP`. Toutefois, comme les champs de gravité de Netskope sont incohérents, le mappage nécessite une logique supplémentaire pour évaluer plusieurs champs.
  • device_vendor et device_product se voient attribuer des valeurs à partir de constantes définies plus tôt dans le script.
  • environment est essentiel lorsque vous utilisez plusieurs environnements dans Google SecOps. Dans ce cas, il provient de l'objet siemplify et correspond à l'environnement sélectionné pour le connecteur dans la plate-forme.
  • À la ligne 37 (figure 3), le connecteur modifie le dictionnaire d'événements de base en ajoutant une nouvelle clé, product_name, avec la valeur "Netskope". Cela est nécessaire, car les données brutes n'incluent pas de champ de produit cohérent pouvant être utilisé pour le mappage et la modélisation dans l'ontologie de la plate-forme.
    custconnector4
    Figure 3 : Modifier l'événement de base

Exemple de script pour exécuter le connecteur

La fonction main contient la logique d'exécution principale du connecteur :

  • Le décorateur output_handler est utilisé à des fins de débogage et n'est pas abordé dans ce document.
  • La fonction main inclut un paramètre facultatif, is_test_run, qui est défini par défaut sur False. Comme son nom l'indique, ce paramètre détermine si le connecteur doit ingérer des alertes en production ou s'exécuter en mode test à partir de l'onglet Test du connecteur de l'application.

Examinez la répartition de la logique d'exécution principale par ligne de script :

custconnector4
Figure 3 : Modifier l'événement de base
  • Les lignes 56 et 57 initialisent deux listes vides utilisées lors de l'exécution.
  • À la ligne 58, la classe SiemplifyConnectorExecution instancie l'objet siemplify. Cet objet gère la plupart du comportement d'exécution du connecteur.
  • À la ligne 61, une instance de Connector Allowlist est créée. Bien qu'il ne soit pas utilisé dans ce connecteur, il est couramment utilisé dans d'autres connecteurs et n'est pas abordé dans ce guide.
  • Aux lignes 67 à 69, des variables sont définies pour les paramètres du connecteur, tels que les identifiants d'authentification ou les paramètres de configuration.
  • La ligne 71 instancie l'objet NetskopeManager et transmet les paramètres appropriés pour permettre une authentification réussie. La logique interne du gestionnaire qui gère l'authentification n'est pas présentée dans cet exemple.
  • À la ligne 73, il récupère un code temporel à partir d'un fichier local créé lors des exécutions précédentes du connecteur. Ce code temporel permet d'éviter de retraiter les mêmes alertes.
  • Aux lignes 74 et 75, il gère le cas où le connecteur s'exécute pour la première fois et où le code temporel n'est pas encore défini (par exemple, lorsqu'il est défini par défaut sur "0"). Étant donné que Netskope nécessite un code temporel epoch Unix et n'accepte pas "0" comme heure de début valide, la fonction `unix_now` est utilisée pour récupérer l'heure actuelle en millisecondes. Cette valeur est divisée par `1 000` pour être convertie en secondes epoch Unix. Les heures de début et de fin obtenues sont ensuite transmises à la méthode `get_alerts` du gestionnaire. Alors que de nombreuses API n'acceptent qu'une heure de début, l'API Netskope exige à la fois une heure de début et une heure de fin pour les requêtes d'alertes basées sur le temps.
  • La ligne 77 récupère une liste d'alertes de Netskope. Si le connecteur est en mode test, seule la dernière alerte de la liste est sélectionnée (lignes 79 à 80).

Logique de dépassement

Le connecteur parcourt ensuite les alertes récupérées et crée une alerte à partir de chacune d'elles à l'aide de la fonction build_alert_info définie précédemment. Il ajoute chaque alerte à la liste all_alerts, initialisée précédemment. La partie suivante de la logique du connecteur gère le dépassement de capacité.
Le dépassement est un mécanisme de seuil qui empêche l'ingestion d'un trop grand nombre d'alertes sur une courte période, en particulier lorsque les alertes partagent le même environnement, le même produit et le même générateur de règles. Bien que cela ne soit pas obligatoire, nous vous recommandons d'implémenter une logique de dépassement en tant que bonne pratique pour éviter la dégradation des performances.

Examinez la répartition de la logique de débordement par ligne de script dans la figure 4 :

  • Aux lignes 104 à 105, si un alert n'est pas classé comme un dépassement, il est ajouté à la liste des alertes à ingérer.
  • custconnector5
    Figure 4 : Mécanisme de dépassement de capacité.

Mettre fin à l'exécution du connecteur

Si le connecteur n'est pas en mode test, l'horodatage doit être mis à jour pour refléter la dernière alerte récupérée. Cela permet de s'assurer que les mêmes alertes ne sont pas réingérées lors du prochain cycle d'exécution. La liste all_alerts est triée par code temporel. Ainsi, même les alertes en trop contribuent à déterminer le code temporel le plus récent.

Examinez la répartition de la logique d'exécution du connecteur par ligne de script dans la figure 5 :

  • À la ligne 126, la liste des alertes non dépassées est envoyée à l'application, où les alertes sont ensuite créées et affichées dans l'interface utilisateur graphique.
  • Aux lignes 128 à 131, ils déterminent si le connecteur est en mode test. Les arguments système transmis par l'application, par exemple lorsque vous cliquez sur Exécuter le connecteur une fois dans l'onglet Test, sont utilisés pour prendre cette décision.
    custconnector6
    Figure 5 : Mettre fin à l'exécution du connecteur

Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.