Collecter les journaux de ressources Microsoft Azure
Ce document explique comment collecter les journaux de ressources Microsoft Azure en configurant un flux Google Security Operations à l'aide de Microsoft Azure Blob Storage V2.
Les journaux de ressources Azure fournissent des informations sur les opérations effectuées dans les ressources Azure. Ces journaux enregistrent des informations détaillées sur les opérations, l'état et les métriques de performances des ressources. Le contenu varie en fonction du type de ressource et inclut des données telles que les événements d'authentification, les modifications de configuration, les tentatives d'accès et les métriques opérationnelles.
Avant de commencer
Assurez-vous de remplir les conditions préalables suivantes :
- Une instance Google SecOps
Accès privilégié au portail Microsoft Azure avec les autorisations suivantes :
- Créer des comptes de stockage
- Configurer les paramètres de diagnostic pour les ressources Azure
- Gérer les clés d'accès
Configurer un compte de stockage Azure
Créer un compte de stockage
- Dans le portail Azure, recherchez Comptes de stockage.
- Cliquez sur + Créer.
Fournissez les informations de configuration suivantes :
Paramètre Valeur Abonnement Sélectionnez votre abonnement Azure. Groupe de ressources Sélectionner une base de données existante ou en créer une Nom du compte de stockage Saisissez un nom unique (par exemple, azureresourcelogs).Région Sélectionnez la région (par exemple, East US).Performances Standard (recommandé) Redondance GRS (stockage géoredondant) ou LRS (stockage local redondant) Cliquez sur Examiner et créer.
Passez en revue l'aperçu du compte, puis cliquez sur Créer.
Attendez la fin du déploiement.
Obtenir les identifiants du compte de stockage
- Accédez au compte de stockage que vous venez de créer.
- Dans le volet de navigation de gauche, sélectionnez Clés d'accès sous Sécurité et mise en réseau.
- Cliquez sur Afficher les clés.
Copiez et enregistrez les éléments suivants pour une utilisation ultérieure :
- Nom du compte de stockage :
azureresourcelogs - Clé 1 ou Clé 2 : clé d'accès partagée (chaîne aléatoire de 512 bits encodée en base64)
- Nom du compte de stockage :
Obtenir le point de terminaison du service Blob
- Dans le même compte de stockage, sélectionnez Points de terminaison dans le panneau de navigation de gauche.
- Copiez et enregistrez l'URL du point de terminaison Blob service.
- Exemple :
https://azureresourcelogs.blob.core.windows.net/
- Exemple :
Configurer les paramètres de diagnostic des ressources Azure
Les journaux de ressources Azure ne sont pas collectés par défaut. Vous devez créer un paramètre de diagnostic pour chaque ressource Azure afin de router les journaux vers le compte de stockage.
- Dans le portail Azure, accédez à la ressource Azure que vous souhaitez surveiller.
- Dans le panneau de navigation de gauche, sélectionnez Paramètres de diagnostic sous Surveillance.
- Cliquez sur + Ajouter un paramètre de diagnostic.
- Fournissez les informations de configuration suivantes :
- Nom du paramètre de diagnostic : saisissez un nom descriptif (par exemple,
export-to-secops). - Dans la section Journaux, sélectionnez les catégories de journaux que vous souhaitez collecter. Les catégories disponibles varient selon le type de ressource. Voici quelques catégories courantes :
- Administration (pour les journaux d'activité)
- Sécurité (pour les journaux d'activité)
- AuditEvent (pour Key Vault)
- ApplicationGatewayAccessLog (pour Application Gateway)
- ApplicationGatewayFirewallLog (pour Application Gateway)
- NetworkSecurityGroupEvent (pour les groupes de sécurité réseau)
- Dans la section Métriques (facultatif), sélectionnez AllMetrics pour envoyer les métriques de la plate-forme au compte de stockage.
- Dans la section Détails de la destination, cochez la case Archiver dans un compte de stockage.
- Abonnement : sélectionnez l'abonnement contenant votre compte de stockage.
- Compte de stockage : sélectionnez le compte de stockage que vous avez créé (par exemple,
azureresourcelogs).
- Nom du paramètre de diagnostic : saisissez un nom descriptif (par exemple,
- Cliquez sur Enregistrer.
Une fois la configuration effectuée, les journaux sont automatiquement exportés vers les conteneurs du compte de stockage. Azure crée des conteneurs en utilisant le modèle de dénomination insights-logs-<log-category-name>. Exemple :
- Journaux d'audit Key Vault :
insights-logs-auditevent - Journaux d'accès Application Gateway :
insights-logs-applicationgatewayaccesslog - Journaux de pare-feu Application Gateway :
insights-logs-applicationgatewayfirewalllog Événements du groupe de sécurité réseau :
insights-logs-networksecuritygroupevent
Configurer un flux dans Google SecOps pour ingérer les journaux de ressources Azure
- 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,
Azure Resource Logs - Key Vault). - Sélectionnez Microsoft Azure Blob Storage V2 comme Type de source.
- Sélectionnez Ressource Microsoft Azure comme Type de journal.
- Cliquez sur Suivant.
Spécifiez les valeurs des paramètres d'entrée suivants :
- URI Azure : saisissez l'URL du point de terminaison du service Blob avec le chemin d'accès au conteneur :
https://azureresourcelogs.blob.core.windows.net/insights-logs-auditevent/- Remplacez l'élément suivant :
azureresourcelogs: nom de votre compte de stockage Azure.insights-logs-auditevent: nom du conteneur d'objets blob dans lequel les journaux sont stockés (varie selon le type de ressource et la catégorie de journal).
Option de suppression de la source : sélectionnez l'option de suppression de votre choix :
- Jamais : ne supprime jamais aucun fichier après les transferts.
- Supprimer les fichiers transférés : supprime les fichiers après un transfert réussi.
- Supprimer les fichiers transférés et les répertoires vides : supprime les fichiers et les répertoires vides après un transfert réussi.
Âge maximal des fichiers : incluez les fichiers modifiés au cours des derniers jours. La valeur par défaut est de 180 jours.
Clé partagée : saisissez la valeur de la clé partagée (clé d'accès) que vous avez récupérée à partir du compte de stockage à l'étape 3.
Espace de noms de l'élément : espace de noms de l'élément.
Libellés d'ingestion : libellé à appliquer aux événements de ce flux.
Cliquez sur Suivant.
Vérifiez la configuration de votre nouveau flux sur l'écran Finaliser, puis cliquez sur Envoyer.
Configurer le pare-feu Azure Storage (le cas échéant)
Si votre compte de stockage Azure utilise un pare-feu, vous devez ajouter les plages d'adresses IP Google SecOps.
- Dans le portail Azure, accédez à votre compte de stockage (par exemple,
azureresourcelogs). - Sélectionnez Mise en réseau sous Sécurité et mise en réseau.
- Sous Pare-feu et réseaux virtuels, sélectionnez Activé à partir des réseaux virtuels et adresses IP sélectionnés.
- Dans la section Pare-feu, sous Plage d'adresses, cliquez sur + Ajouter une plage d'adresses IP.
Ajoutez chaque plage d'adresses IP Google SecOps au format CIDR.
- Pour obtenir les plages d'adresses IP actuelles, choisissez l'une des options suivantes :
- Consultez la documentation sur la liste d'autorisation d'adresses IP.
- Récupérez-les par programmation à l'aide de l'API Feed Management.
- Pour obtenir les plages d'adresses IP actuelles, choisissez l'une des options suivantes :
Cliquez sur Enregistrer.
Table de mappage UDM
| Champ de journal | Mappage UDM | Logique |
|---|---|---|
| Différents champs de libellé field*_label supplémentaires | additional.fields | Fusionné à partir de différents champs*_label field supplémentaires |
| authenticationMethod | extensions.auth.mechanism | Définissez sur USERNAME_PASSWORD si authenticationMethod est défini sur "Password" (Mot de passe). |
| category, event_type | extensions.auth.type | Définissez la valeur sur MACHINE pour SQLSecurityAuditEvents, sur SSO pour des catégories spécifiques et sur AUTHTYPE_UNSPECIFIED pour les autres. |
| properties.partialipaddress | intermediary.ip | Valeur de properties.partialipaddress si elle n'est pas vide |
| properties.event_time, stage_time, risk_time, last_update_time, time | metadata.collected_timestamp | Converti à l'aide d'ISO8601 à partir de properties.event_time, ou de stage_time, ou de risk_time, ou de last_update_time, ou de time avec grok de secours |
| properties.message, properties.activity, properties.log.stage | metadata.description | Valeur de properties.message si elle n'est pas vide, sinon de properties.activity, sinon de properties.log.stage |
| event_type | metadata.event_type | Valeur de event_type si elle n'est pas vide, sinon GENERIC_EVENT |
| category, record.category | metadata.product_event_type | Valeur copiée directement à partir de category ou record.category |
| properties.event_id, properties.log.auditID | metadata.product_log_id | Valeur de properties.event_id si elle n'est pas vide, sinon valeur de properties.log.auditID |
| properties.log.apiVersion | metadata.product_version | Valeur copiée directement à partir de properties.log.apiVersion |
| protocol | network.application_protocol | Valeur copiée directement à partir du protocole |
| properties.log.verb | network.dhcp.opcode | Valeur copiée directement à partir de properties.log.verb (en majuscules) |
| properties.CsMethod, record.properties.CsMethod | network.http.method | Valeur copiée directement à partir de properties.CsMethod ou record.properties.CsMethod |
| user_agent | network.http.parsed_user_agent | Converti à partir de user_agent |
| properties.Referer, uri | network.http.referral_url | Valeur de properties.Referer si elle n'est pas vide, sinon valeur de l'URI |
| properties.ScStatus, record.properties.ScStatus, properties.statusCode, record.properties.statusCode, responseStatus.code | network.http.response_code | Converti en entier à partir de properties.ScStatus, record.properties.ScStatus, properties.statusCode, record.properties.statusCode ou responseStatus.code |
| user_agent | network.http.user_agent | Valeur copiée directement à partir de user_agent |
| properties.ScBytes, record.properties.ScBytes, properties.responseLength | network.received_bytes | Converti en uinteger à partir de properties.ScBytes, record.properties.ScBytes ou properties.responseLength |
| properties.CsBytes, record.properties.CsBytes, properties.requestLength | network.sent_bytes | Converti en uinteger à partir de properties.CsBytes, record.properties.CsBytes ou properties.requestLength |
| properties.session_id | network.session_id | Valeur copiée directement à partir de properties.session_id (convertie en chaîne) |
| properties.tlsVersion | network.tls.version | Valeur copiée directement à partir de properties.tlsVersion |
| domain_name_value | principal.administrative_domain | Valeur copiée directement à partir de domain_name_value |
| properties.clientAppUsed, target_application | principal.application | Valeur de "properties.clientAppUsed" si elle n'est pas vide, sinon valeur de "target_application". |
| prop_device_id | principal.asset.asset_id | Définissez sur "ID de l'appareil" suivi de prop_device_id si la valeur n'est pas nulle. |
| matériel | principal.asset.hardware | Fusionné depuis le matériel |
| properties.host_name, properties.CIp, record.properties.CIp, properties.ComputerName, record.properties.ComputerName, properties.CsHost, record.properties.CsHost, properties.server_instance_name, record.properties.server_instance_name, server_name | principal.asset.hostname | Valeur de properties.host_name si elle n'est pas vide, sinon de properties.CIp (adresse IP grok), record.properties.CIp (adresse IP grok), properties.ComputerName, record.properties.ComputerName, properties.CsHost, record.properties.CsHost, properties.server_instance_name, record.properties.server_instance_name ou server_name |
| src_ip, src_ip1, properties.client_ip, record.properties.clientIpAddress, properties.clientIpAddress, callerIpAddress, properties.ipAddress, ip | principal.asset.ip | Valeur de src_ip, src_ip1, properties.client_ip (adresse IP grok), record.properties.clientIpAddress, properties.clientIpAddress (adresse IP grok), record.properties.clientIpAddress, callerIpAddress (adresse IP grok), properties.ipAddress ou ip |
| properties.host_name, properties.CsHost, record.properties.CsHost | principal.hostname | Valeur de properties.host_name si elle n'est pas vide, sinon valeur de properties.CsHost ou record.properties.CsHost |
| src_ip, src_ip1, properties.client_ip, record.properties.clientIpAddress, properties.clientIpAddress, callerIpAddress, properties.ipAddress, ip | principal.ip | Valeur de src_ip, src_ip1, properties.client_ip (adresse IP grok), record.properties.clientIpAddress, properties.clientIpAddress (adresse IP grok), record.properties.clientIpAddress, callerIpAddress (adresse IP grok), properties.ipAddress ou ip |
| properties.location.city, provisioning_steps_city | principal.location.city | Valeur de properties.location.city si elle n'est pas vide, sinon valeur de provisioning_steps_city |
| properties.location.countryOrRegion, provisioning_steps_country, location, Region | principal.location.country_or_region | Valeur de properties.location.countryOrRegion si elle n'est pas vide, sinon de provisioning_steps_country, sinon de location, sinon de Region |
| properties.location.geoCoordinates.latitude | principal.location.region_latitude | Valeur copiée directement à partir de properties.location.geoCoordinates.latitude |
| properties.location.geoCoordinates.longitude | principal.location.region_longitude | Valeur copiée directement à partir de properties.location.geoCoordinates.longitude |
| properties.location.state | principal.location.state | Valeur copiée directement à partir de properties.location.state |
| prop_os | principal.platform | Définissez la valeur sur WINDOWS si prop_os correspond à (?i)Win, sur LINUX si (?i)Lin ou sur MAC si (?i)Mac. |
| properties.deviceDetail.operatingSystem | principal.platform_version | Valeur copiée directement à partir de properties.deviceDetail.operatingSystem |
| src_port | principal.port | Converti en entier à partir de src_port |
| is_compliant_label, is_managed_label, serice_type_label, serice_credential_label | principal.resource.attribute.labels | Fusionné à partir de is_compliant_label, is_managed_label, serice_type_label, serice_credential_label |
| properties.sourceSystem.Name | principal.resource.name | Valeur copiée directement à partir de properties.sourceSystem.Name |
| properties.sourceSystem.Id | principal.resource.product_object_id | Valeur copiée directement à partir de properties.sourceSystem.Id |
| properties.server_principal_name, source_user_principal_name, user_principal_name, local_account_username_value | principal.user.email_addresses | Fusionné à partir de properties.server_principal_name (si l'adresse e-mail correspond), source_user_principal_name (si l'adresse e-mail correspond), user_principal_name (si l'adresse e-mail correspond) ou local_account_username_value (si l'adresse e-mail correspond) |
| properties.sequence_group_id, grpname, properties.log.user.groups | principal.user.group_identifiers | Fusionné à partir de properties.sequence_group_id, grpname ou properties.log.user.groups |
| properties.sourceIdentity.details.id, properties.userId, details_id_not_present | principal.user.product_object_id | Valeur de properties.sourceIdentity.details.id si elle n'est pas vide, sinon de properties.userId, sinon de details_id_not_present |
| properties.ServicePrincipalDisplayName, properties.servicePrincipalName, properties.sourceIdentity.details.DisplayName, properties.userDisplayName, record.properties.log.user.username | principal.user.user_display_name | Valeur extraite de properties.ServicePrincipalDisplayName si elle n'est pas vide, sinon de properties.servicePrincipalName, sinon de properties.sourceIdentity.details.DisplayName, sinon de properties.userDisplayName, sinon de record.properties.log.user.username |
| properties.servicePrincipalId, user_userPrincipalName, source_user_principal_name, details_user_principal_name, user_principal_name, properties.accountName, record.properties.log.user.uid | principal.user.userid | Valeur de properties.servicePrincipalId si elle n'est pas vide, sinon de user_userPrincipalName, sinon de source_user_principal_name, sinon de details_user_principal_name, sinon de user_principal_name, sinon de properties.accountName, sinon de record.properties.log.user.uid |
| security_action, succeeded, statusText, resultType | security_result.action | Définissez sur "ALLOW" si security_action est "allow". Sinon, définissez sur "ALLOW" si "succeeded" est "true", ou si statusText est "Success", ou si resultType est "success". Sinon, définissez sur "BLOCK" si "succeeded" est "false", ou si statusText est "failed", ou si resultType est "failed". |
| properties.action_name | security_result.action_details | Valeur copiée directement à partir de properties.action_name |
| status_label | security_result.about.resource.attribute.labels | Fusionné à partir de status_label |
| properties_log_label, corr_key_label, resultType_label, resultSignature_label, networkName_label, networkType_label, method_label, authentication_step_requirement_label, authentication_step_result_detail_label, stepdate_label, initiatedby_name_label, initiatedby_id_label, initiatedby_type_label, targetSystem_id_label, targetSystem_name_label, containerID_label, pod_label, authentication_label, api_name_label, scale_unit_label, namespace_name_label, subscription_id_label, activity_id_label_1, task_name_label, environment_label, cookie, additional_field_event_ip, additional_field_event_primary_stamp, additional_field_event_stamp_type, source, correlationId_field, activityDateTime_field, detectedDateTime_field, lastUpdatedDateTime_field, count_label, total_label, minimum_label, maximum_label, average_label, metricName_label, timeGrain_label, ApiName_label, Authentication_label, GeoType_label, old_label, new_label, add_label, keyId_label, sr_result.rule_name, sr_result.rule_id, resultField, sr_result.detection_fields | security_result.detection_fields | Fusionné à partir de properties_log_label, corr_key_label, resultType_label, resultSignature_label, networkName_label, networkType_label, method_label, authentication_step_requirement_label, authentication_step_result_detail_label, stepdate_label, initiatedby_name_label, initiatedby_id_label, initiatedby_type_label, targetSystem_id_label, targetSystem_name_label, containerID_label, pod_label, authentication_label, api_name_label, scale_unit_label, namespace_name_label, subscription_id_label, activity_id_label_1, task_name_label, environment_label, cookie, additional_field_event_ip, additional_field_event_primary_stamp, additional_field_event_stamp_type, source, correlationId_field, activityDateTime_field, detectedDateTime_field, lastUpdatedDateTime_field, count_label, total_label, minimum_label, maximum_label, average_label, metricName_label, timeGrain_label, ApiName_label, Authentication_label, GeoType_label, old_label, new_label, add_label, keyId_label, sr_result.rule_name, sr_result.rule_id, resultField, sr_result.detection_fields |
| resultDescription, sec_result.description, properties.queryexecutionstatus | security_result.description | Valeur extraite de resultDescription (supprimer les sauts de ligne) ; sinon, extraite de sec_result.description ; sinon, extraite de properties.queryexecutionstatus |
| policy_id_value | security_result.rule_id | Valeur copiée directement à partir de policy_id_value |
| properties.Result, statusText, properties.queryexecutionstatus | security_result.summary | Valeur de properties.Result si elle n'est pas vide, sinon de statusText, sinon de properties.queryexecutionstatus |
| target_application | target.application | Valeur de target_application |
| properties.ComputerName, record.properties.ComputerName, properties.server_instance_name, record.properties.server_instance_name | target.asset.hostname | Valeur issue de properties.ComputerName, record.properties.ComputerName, properties.server_instance_name ou record.properties.server_instance_name |
| (codé en dur) | target.cloud.environment | Définissez-le sur "MICROSOFT_AZURE". |
| properties.SPort, record.properties.SPort | target.port | Converti en entier à partir de properties.SPort ou record.properties.SPort |
| properties.querytext.query | target.process.command_line | Valeur copiée directement à partir de properties.querytext.query |
| properties.processId | target.process.pid | Converti en chaîne à partir de properties.processId |
| subscription_id_label, resource_group_label, request_resource_type_label, request_resource_id_label, additional_objectKey, additional_clientRequestId, additional_RiskEventType, additional_tokenIssuerType, keyId_label, appid_label | target.resource.attribute.labels | Fusionné à partir de subscription_id_label, resource_group_label, request_resource_type_label, request_resource_id_label, additional_objectKey, additional_clientRequestId, additional_RiskEventType, additional_tokenIssuerType, keyId_label, appid_label |
| properties_databasename, properties.resourceDisplayName, record.properties.databasename, record.properties.databaseName | target.resource.name | Valeur de properties_databasename si elle n'est pas vide ; sinon, valeur de properties.resourceDisplayName ; sinon, valeur de record.properties.databasename ; sinon, valeur de record.properties.databaseName |
| resourceId, properties.resourceId | target.resource.product_object_id | Valeur de resourceId si elle n'est pas vide, sinon de properties.resourceId |
| properties_collectionname, properties.resourceDisplayName, record.properties.collectionname, record.properties.collectionName, properties.log.objectRef.resource | target.resource.resource_subtype | Valeur issue de properties_collectionname si elle n'est pas vide, sinon issue de properties.resourceDisplayName, sinon issue de record.properties.collectionname, sinon issue de record.properties.collectionName, sinon issue de properties.log.objectRef.resource |
| resourceId, message | target.resource.resource_type | Défini sur DATABASE si resourceId correspond au modèle ; sinon, CLUSTER si le message correspond à MANAGEDCLUSTERS ; sinon, VIRTUAL_MACHINE si MANAGEDINSTANCES ; sinon, DATABASE si DATABASEACCOUNTS |
| resourceType | target.resource.type | Valeur copiée directement à partir de resourceType |
| properties.CsUriStem, properties.log.requestURI, value (from additionalInfo) | target.url | Valeur de properties.CsUriStem si elle n'est pas vide ; sinon, valeur de properties.log.requestURI ; sinon, valeur (de additionalInfo) |
| user_principal_name | target.user.email_addresses | Fusionné à partir de user_principal_name (si l'adresse e-mail correspond) |
| properties.userId | target.user.product_object_id | Valeur copiée directement à partir de properties.userId |
| properties.userDisplayName | target.user.user_display_name | Valeur copiée directement à partir de properties.userDisplayName |
| user_principal_name, properties.userPrincipalName | target.user.userid | Valeur de user_principal_name si elle n'est pas vide, sinon valeur de properties.userPrincipalName |
| (codé en dur) | metadata.product_name | Définissez la valeur sur "Journaux de ressources Azure". |
| (codé en dur) | metadata.vendor_name | Défini sur "Microsoft" |
Vous avez encore besoin d'aide ? Obtenez des réponses de membres de la communauté et de professionnels Google SecOps.