Collecter les journaux GitLab
Présentation
Cet analyseur extrait des champs des journaux JSON GitLab, les normalise dans le modèle de données unifié (UDM) et enrichit les données avec un contexte supplémentaire. Il gère différents types d'événements GitLab, en se concentrant sur les actions des utilisateurs, l'accès aux ressources et les résultats de sécurité, tout en traitant les informations liées au réseau et à l'application. L'analyseur effectue également une logique basée sur les rôles et les actions dans GitLab, en catégorisant les événements et en leur attribuant des niveaux de gravité appropriés.
Avant de commencer
- Assurez-vous de disposer d'une instance Google SecOps.
- Assurez-vous de disposer d'un accès privilégié à GitLab.
Configurer un flux dans Google SecOps pour ingérer les journaux GitLab
- Accédez à Paramètres du SIEM > Flux.
- Cliquez sur Ajouter.
- Dans le champ Nom du flux, saisissez un nom pour le flux (par exemple, Journaux GitLab).
- Sélectionnez Webhook comme type de source.
- Sélectionnez Gitlab comme Type de journal.
- Cliquez sur Suivant.
- Facultatif: spécifiez des valeurs pour les paramètres d'entrée suivants :
- Délimiteur de fractionnement: délimiteur utilisé pour séparer les lignes de journal, par exemple
\n
. - Espace de noms des éléments: espace de noms des éléments.
- Libellés d'ingestion: libellé appliqué aux événements de ce flux.
- Délimiteur de fractionnement: délimiteur utilisé pour séparer les lignes de journal, par exemple
- Cliquez sur Suivant.
- Vérifiez la configuration du flux dans l'écran Finaliser, puis cliquez sur Envoyer.
- Cliquez sur Générer une clé secrète pour générer une clé secrète permettant d'authentifier ce flux.
- Copiez et stockez la clé secrète. Vous ne pourrez plus afficher cette clé secrète. Si nécessaire, vous pouvez générer une nouvelle clé secrète, mais cette action rend l'ancienne clé secrète obsolète.
- Dans l'onglet Détails, copiez l'URL du point de terminaison du flux dans le champ Informations sur le point de terminaison. Vous devez spécifier cette URL de point de terminaison dans votre application cliente.
- Cliquez sur OK.
Créer une clé API pour le flux webhook
Accédez à la console Google Cloud > Identifiants.
Cliquez sur Créer des identifiants, puis sélectionnez Clé API.
Limitez l'accès de la clé API à l'API Google Security Operations.
Spécifier l'URL du point de terminaison
- Dans votre application cliente, spécifiez l'URL du point de terminaison HTTPS fournie dans le flux de webhook.
Activez l'authentification en spécifiant la clé API et la clé secrète dans l'en-tête personnalisé au format suivant:
X-goog-api-key = API_KEY X-Webhook-Access-Key = SECRET
Recommandation: Spécifiez la clé API en tant qu'en-tête plutôt que dans l'URL. Si votre client webhook n'est pas compatible avec les en-têtes personnalisés, vous pouvez spécifier la clé API et la clé secrète à l'aide de paramètres de requête au format suivant:
ENDPOINT_URL?key=API_KEY&secret=SECRET
Remplacez les éléments suivants :
ENDPOINT_URL
: URL du point de terminaison du flux.API_KEY
: clé API permettant de s'authentifier auprès de Google Security Operations.SECRET
: clé secrète que vous avez générée pour authentifier le flux.
Configurer un webhook dans GitLab pour Google SecOps
- Ouvrez votre navigateur Web et accédez au projet GitLab pour lequel vous souhaitez configurer le webhook.
- Dans votre projet, accédez à Paramètres > Webhooks.
- Cliquez sur Ajouter un webhook.
- Dans le champ URL, collez l'URL du point de terminaison Google SecOps.
- Cliquez sur Ajouter un en-tête personnalisé.
- Saisissez X-Webhook-Access-Key dans le champ Nom de l'en-tête.
- Dans le champ Valeur d'en-tête, copiez la clé secrète générée lors de la configuration du flux Google SecOps.
- Cliquez sur Ajouter un en-tête personnalisé.
- Saisissez X-goog-api-key dans le champ Nom de l'en-tête.
- Pour le champ Header Value (Valeur de l'en-tête), copiez la clé API générée lors de la configuration du flux Google SecOps. Remarque: Pour renforcer la sécurité, générez un jeton secret et ajoutez-le à la configuration du webhook GitLab et à la configuration du flux Google SecOps correspondante. Cela permet de vérifier l'authenticité des webhooks entrants.
- Choisissez les événements GitLab qui doivent déclencher le webhook. Par exemple, vous pouvez sélectionner Événements push pour envoyer des données à Google SecOps chaque fois qu'un code est transmis au dépôt. Réfléchissez attentivement aux événements qui correspondent à vos besoins de surveillance de la sécurité. Un trop grand nombre d'événements peut entraîner une charge inutile.
- Pour mieux comprendre l'objectif des webhooks, attribuez-leur un nom explicite, par exemple Webhook Google SecOps.
- Assurez-vous que la case Enable SSL verification (Activer la validation SSL) est cochée. C'est essentiel pour la communication sécurisée.
- Cliquez sur Ajouter un webhook pour enregistrer votre configuration.
Tableau de mappage UDM
Champ de journal | Mappage UDM | Logique |
---|---|---|
author_id |
principal.user.userid |
Converti en chaîne. |
author_name |
principal.user.email_addresses |
Si la valeur correspond à une expression régulière d'adresse e-mail. |
author_name |
principal.user.user_display_name |
Si la valeur ne correspond pas à une expression régulière d'adresse e-mail. |
details.as |
principal.resource.attribute.labels |
Ajouté en tant que libellé avec la clé "as". |
details.add |
principal.resource.attribute.labels |
Ajouté en tant que libellé avec la clé "add". |
details.as |
principal.user.role_name |
Valeur brute du champ de journal. |
details.as |
principal.user.attribute.roles.type |
Défini sur "ADMINISTRATOR" si details.as est "Owner" (Propriétaire), "SERVICE_ACCOUNT" si details.as est "Developer" (Développeur), "Maintainer" (Gestionnaire) ou "Reporter" (Rapporteur), et "TYPE_UNSPECIFIED" si details.as est "Guest" (Invité). |
details.custom_message |
security_result.description |
Valeur brute du champ de journal. |
details.custom_message.action |
security_result.summary |
Valeur brute du champ de journal. |
details.entity_path |
target.file.full_path |
Valeur brute du champ de journal. |
details.target_id |
target.resource.id |
Converti en chaîne. |
entity_path |
target.file.full_path |
Valeur brute du champ de journal. |
entity_type |
target.resource.attribute.labels |
Ajouté en tant que libellé avec la clé "Type d'entité". |
event_type |
metadata.product_event_type |
Valeur du champ de journal brut. |
insertId |
metadata.product_log_id |
Valeur brute du champ de journal. |
ip_address |
principal.ip , principal.asset.ip |
Valeur du champ de journal brut. |
jsonPayload.action |
additional.fields |
Ajouté en tant que champ avec la clé "action" et la valeur de chaîne. |
jsonPayload.controller |
additional.fields |
Ajouté en tant que champ avec la clé "controller" et la valeur de chaîne. |
jsonPayload.correlation_id |
principal.asset_id |
Préfixé par "id: ". |
jsonPayload.cpu_s |
additional.fields |
Ajouté en tant que champ avec la clé "cpu_s" et la valeur de chaîne. |
jsonPayload.details.custom_message.protocol |
network.application_protocol |
Défini sur "UNKNOWN_APPLICATION_PROTOCOL" si la valeur est "web", sinon converti en majuscules. Ajouté également en tant que champ supplémentaire avec la clé "Protocole d'application" si la valeur est "web". |
jsonPayload.mem_total_bytes |
additional.fields |
Ajouté en tant que champ avec la clé "mem_total_bytes" et la valeur de chaîne. |
jsonPayload.meta_caller_id |
additional.fields |
Ajouté en tant que champ avec la clé "ID de l'appelant" et la valeur de chaîne. |
jsonPayload.meta_client_id |
target.user.userid |
Valeur du champ de journal brut. |
jsonPayload.meta_feature_category |
additional.fields |
Ajouté en tant que champ avec la clé "Catégorie d'éléments géographiques" et la valeur de chaîne. |
jsonPayload.meta_remote_ip |
principal.ip , principal.asset.ip |
Valeur brute du champ de journal, analysée en tant que tableau JSON et fusionnée dans les champs d'adresse IP. |
jsonPayload.meta_user |
principal.user.userid |
Utilisé comme solution de remplacement si jsonPayload.username est vide. |
jsonPayload.method |
network.http.method |
Valeur du champ de journal brut. |
jsonPayload.path |
target.process.file.full_path |
Valeur brute du champ de journal. |
jsonPayload.pid |
target.process.pid |
Converti en chaîne. |
jsonPayload.remote_ip |
principal.ip , principal.asset.ip |
Valeur brute du champ de journal. |
jsonPayload.request_urgency |
additional.fields |
Ajouté en tant que champ avec la clé "Urgency of request" (Urgence de la demande) et la valeur de chaîne. |
jsonPayload.severity |
security_result.severity |
Définissez cette valeur sur "INFORMATIONAL" si la valeur est "INFO", sur "ERROR" si la valeur est "ERROR" et sur "MEDIUM" si la valeur est "NOTICE". |
jsonPayload.status |
network.http.response_code |
Converti en entier si la valeur n'est pas "ACTIVE". |
jsonPayload.ua |
network.http.user_agent |
Valeur brute du champ de journal. |
jsonPayload.username |
principal.user.userid |
Valeur brute du champ de journal. |
jsonPayload.worker_id |
principal.application |
Valeur du champ de journal brut. |
labels.instance_name |
principal.hostname , principal.asset.hostname |
Valeur du champ de journal brut, utilisée si le message contient "Suppression de l'utilisateur". |
logName |
security_result.category_details |
Valeur brute du champ de journal. |
message |
security_result.summary |
Valeur du champ de journal brut, utilisée si jsonPayload.severity est "ERROR". |
protoPayload.@type |
additional.fields |
Ajouté en tant que champ avec la clé "protoPayload type" et la valeur de chaîne. |
protoPayload.authenticationInfo.principalEmail |
principal.user.email_addresses , principal.user.userid |
Valeur brute du champ de journal. |
protoPayload.authenticationInfo.principalSubject |
additional.fields |
Ajouté en tant que champ avec la clé "authenticationInfo principalSubject" et la valeur de chaîne. |
protoPayload.authenticationInfo.serviceAccountKeyName |
additional.fields |
Ajouté en tant que champ avec la clé "authenticationInfo serviceAccountKeyName" et la valeur de chaîne. |
protoPayload.authorizationInfo |
target.resource.attribute.labels , security_result.action |
Les valeurs de ce champ sont ajoutées en tant que libellés avec des clés précédées du préfixe "authenticationInfo". security_result.action est défini sur "ALLOW" si une valeur dans granted est définie sur "true", et sur "BLOCK" si elle est définie sur "false". Les champs imbriqués tels que resourceAttributes sont également ajoutés en tant que libellés avec des clés commençant par "authenticationInfo_resourceAttributes". |
protoPayload.methodName |
additional.fields |
Ajouté en tant que champ avec la clé "protoPayload methodName" et la valeur de chaîne. |
protoPayload.request.@type |
additional.fields |
Ajouté en tant que champ avec la clé "Request Type" (Type de requête) et la valeur de chaîne. |
protoPayload.request.resource |
target.resource.attribute.labels |
Ajouté en tant que libellé avec la clé "Ressource de requête". |
protoPayload.requestMetadata.callerIp |
additional.fields |
Ajouté en tant que champ avec la clé "requestMetadata callerIp" et la valeur de chaîne. |
protoPayload.requestMetadata.callerSuppliedUserAgent |
additional.fields |
Ajouté en tant que champ avec la clé "requestMetadata callerSuppliedUserAgent" et la valeur de chaîne. |
protoPayload.serviceName |
additional.fields |
Ajouté en tant que champ avec la clé "serviceName" et la valeur de chaîne. |
protoPayload.status.code |
additional.fields |
Ajouté en tant que champ avec la clé "code d'état protoPayload" et la valeur de chaîne. |
protoPayload.status.message |
additional.fields , target.user.email_addresses , target.user.userid |
Ajouté en tant que champ avec la clé "protoPayload status message" et la valeur de chaîne. Si une adresse e-mail peut être extraite du message, elle est ajoutée à target.user.email_addresses et target.user.userid . |
receiveTimestamp |
metadata.event_timestamp , timestamp |
Interprété comme code temporel de l'événement. |
resource.labels.project_id |
target.resource.attribute.labels |
Ajouté en tant que libellé avec la clé "ID du projet". |
resource.labels.zone |
target.cloud.availability_zone |
Valeur brute du champ de journal. |
resource.type |
target.cloud.environment |
Définissez la valeur sur "GOOGLE_CLOUD_PLATFORM" si elle correspond à "gce". |
security_result.action |
security_result.action |
Dérivé de protoPayload.authorizationInfo.granted . |
security_result.category_details |
security_result.category_details |
Fusionné avec logName . |
security_result.description |
security_result.description |
Dérivé de jsonPayload.details.custom_message . |
security_result.severity |
security_result.severity |
Dérivé de severity ou jsonPayload.severity . |
security_result.summary |
security_result.summary |
Dérivé de jsonPayload.details.custom_message.action ou jsonPayload.message . |
severity |
security_result.severity |
Définissez cette valeur sur "INFORMATIONAL" si la valeur est "INFO", sur "ERROR" si la valeur est "ERROR" et sur "MEDIUM" si la valeur est "NOTICE". |
sourceLocation |
principal.resource.attribute.labels |
Les valeurs de ce champ sont ajoutées en tant que libellés. |
target_details |
target.resource.attribute.labels |
Ajouté en tant que libellé avec la clé "Détails de la cible". |
target_type |
target.resource.attribute.labels |
Ajouté en tant que libellé avec la clé "type de cible". |
timestamp |
timestamp |
Valeur du champ de journal brut. Défini en fonction de la présence des champs principal et cible. La valeur par défaut est "GENERIC_EVENT" si aucune condition spécifique n'est remplie. Les valeurs possibles sont "USER_RESOURCE_UPDATE_CONTENT", "USER_RESOURCE_ACCESS" et "USER_UNCATEGORIZED". Défini sur "GITLAB". Défini sur "GITLAB". |
Modifications
2024-04-08
- Mappage de "custom_message.action" sur "security_result.summary".
- Mappage de "ip_address" sur "principal.ip".
- Mappage de "applicationProtocol" sur "network.application_protocol".
- Mappage de "details.author_name"" sur "principal.user.email_addresses"
- Mappage de "author_id" sur "principal.user.userid".
- "target_id" a été mappé sur "target.resource.id".
- "details.entity_path" a été mappé sur "target.file.full_path".
- "event_type" a été mappé sur "product_event_type".
- Mappage de "target_type", "entity_type" et "target_details" sur "resource.attribute.labels".
2023-10-20
- Les champs commençant par "db_" ont été mappés sur "additional_fields".
- Les champs commençant par "redis_" ont été mappés sur "additional_fields".
- "severity" ou "jsonPayload.severity" a été mappé sur "security_result.severity" lorsque la valeur est "ERROR" ou "NOTICE".
- Mappage de "jsonPayload.correlation_id" sur "principal.asset_id".
- Mappage des "champs non mappés de jsonPayload" sur "additional_fields".
- Mappage de "jsonPayload.worker_id" sur "principal.application".
- Mappage de "jsonPayload.method" sur "network.http.method".
- Mappage de "jsonPayload.pid" sur "target.process.pid".
- "jsonPayload.status" a été mappé sur "network.http.response_code".
- "resource.labels.zone" a été mappé sur "target.cloud.availability_zone".
- "resource.type" a été mappé sur "target.cloud.environment".
- Mappage de "jsonPayload.meta_user" sur "target.user.userid".
- Mappage de "jsonPayload.username" sur "principal.user.userid".
- Mappage de "jsonPayload.remote_ip" sur "principal.ip".
- Mappage de "jsonPayload.ua" sur "network.http.user_agent".
- Mappage de "jsonPayload.meta_client_id" sur "target.user.userid".
- Mappage de "jsonPayload.path" sur "target.process.file.full_path".
- Mappage de "protoPayload.authenticationInfo.principalEmail" sur "principal.user.email_addresses".
- Mappage des champs supplémentaires de "protoPayload" sur "additional.fields".
- Ajout d'une vérification conditionnelle pour vérifier que la mise en correspondance requise est présente avant de mapper "metadata.event_type".
2023-10-10
- Mappage de "jsonPayload.details.as" sur "principal.resource.attribute.labels" et "principal.user.role_name".
- Définissez "principal_role.type" sur "ADMINISTRATOR" pour les journaux dont "jsonPayload.details.as" est égal à "Propriétaire".
- Définissez "principal_role.type" sur "SERVICE_ACCOUNT" pour les journaux dont "jsonPayload.details.as" est défini sur "Developer", "Maintainer" ou "Reporter".
- Définissez "principal_role.type" sur "TYPE_UNSPECIFIED" pour les journaux dont "jsonPayload.details.as" est égal à "Invité".
- Mappage de "jsonPayload.details.add" sur "principal.resource.attribute.labels".
- "jsonPayload.entity_type" a été mappé sur "target.resource.attribute.labels".
2023-08-31
- Analyseur nouvellement créé.