Collecter les journaux d'audit Azure DevOps

Compatible avec:

Présentation

Cet analyseur gère les journaux d'audit Azure DevOps au format JSON. Il extrait des champs à partir de structures JSON imbriquées et de premier niveau, et les met en correspondance avec l'UDM. La logique conditionnelle basée sur des valeurs de champ spécifiques permet de classer les événements et d'enrichir la sortie avec des informations de sécurité pertinentes. L'analyseur gère également les messages au format autre que JSON en essayant d'extraire une charge utile JSON à l'aide de modèles Grok.

Avant de commencer

  • Assurez-vous de disposer d'une instance Google SecOps.
  • Assurez-vous de disposer d'une organisation Azure DevOps active.
  • Assurez-vous de disposer d'un accès privilégié à l'organisation Azure DevOps et à Azure.

Configurer un flux dans Google SecOps pour ingérer les journaux Azure DevOps

  1. Accédez à Paramètres du SIEM > Flux.
  2. Cliquez sur Ajouter.
  3. Dans le champ Nom du flux, saisissez un nom pour le flux (par exemple, Journaux Azure DevOps).
  4. Sélectionnez Webhook comme type de source.
  5. Sélectionnez Azure DevOps comme Type de journal.
  6. Cliquez sur Suivant.
  7. 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.
  8. Cliquez sur Suivant.
  9. Vérifiez la configuration du flux dans l'écran Finaliser, puis cliquez sur Envoyer.
  10. Cliquez sur Générer une clé secrète pour générer une clé secrète permettant d'authentifier ce flux.
  11. 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.
  12. 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.
  13. Cliquez sur OK.

Créer une clé API pour le flux webhook

  1. Accédez à la console Google Cloud > Identifiants.

    Accéder à "Identifiants"

  2. Cliquez sur Créer des identifiants, puis sélectionnez Clé API.

  3. Limitez l'accès de la clé API à l'API Google Security Operations.

Spécifier l'URL du point de terminaison

  1. Dans votre application cliente, spécifiez l'URL du point de terminaison HTTPS fournie dans le flux de webhook.
  2. 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 la fonctionnalité d'audit dans Azure DevOps

  1. Connectez-vous à votre organisation (https://dev.azure.com/{yourorganization}).
  2. Sélectionnez l'icône en forme de roue dentée pour Paramètres de l'organisation.
  3. Sélectionnez Règles sous Sécurité.
  4. Activez le bouton Journaliser les événements d'audit sur ON.

Configurer un sujet Event Grid dans Azure

  1. Connectez-vous au portail Azure.
  2. Recherchez et accédez à Event Grid.
  3. Recherchez Thèmes sous Événements personnalisés.
  4. Cliquez sur + Créer.
  5. Sélectionnez votre abonnement et votre groupe de ressources. Attribuez un nom (par exemple, DevopsAuditLog) et sélectionnez la région. Cliquez sur Vérifier et créer.
  6. Accédez au nouveau sujet et copiez l'URL du point de terminaison du sujet.
  7. Accédez à Paramètres > Clés d'accès, puis copiez la clé 1.

Configurer le flux de journaux Azure DevOps vers Event Grid

  1. Connectez-vous à votre organisation (https://dev.azure.com/{yourorganization}).
  2. Sélectionnez l'icône en forme de roue dentée pour Paramètres de l'organisation.
  3. Sélectionnez Audit.
  4. Accédez à l'onglet Diffusions, puis sélectionnez Nouvelle diffusion > Grille d'événements.
  5. Saisissez le point de terminaison du sujet et la clé d'accès créés dans Configurer un sujet Event Grid dans Azure.

Configurer un webhook dans Azure DevOps pour Google SecOps

  1. Dans le portail Azure, recherchez et accédez à Event Grid.
  2. Sélectionnez le sujet créé précédemment.
  3. Accédez à Entités > Abonnement aux événements.
  4. Cliquez sur + Abonnement à l'événement.
  5. Attribuez un nom descriptif (par exemple, Intégration Google SecOps).
  6. Sélectionnez Web Hook, puis cliquez sur Configurer un point de terminaison.
  7. Configurez le point de terminaison :
    • Point de terminaison de l'abonné: saisissez l'URL du point de terminaison de l'API Google SecOps.
    • Ajoutez ?key=<API_KEY>&secret=<SECRET_KEY> à l'URL de la charge utile.
    • Définissez l'en-tête Content-Type sur application/json.
  8. Cliquez sur Créer.

Tableau de mappage UDM

Champ de journal Mappage UDM Logique
ActivityId metadata.product_log_id Mappé directement à partir du champ Id dans le journal brut lorsque le champ records n'est pas présent, ou à partir du champ ActivityId dans l'objet data lorsque records est présent.
ActionId metadata.product_event_type Mappé directement à partir du champ ActionId dans l'objet data.
ActorCUID additional.fields Inclus en tant que champ supplémentaire avec la clé "CUID de l'acteur".
ActorDisplayName principal.user.user_display_name Mappé directement à partir du champ ActorDisplayName s'il ne s'agit pas de "Azure DevOps Service". S'il s'agit de "Azure DevOps Service", il est ajouté en tant que libellé à principal.resource.attribute.labels.
ActorUPN principal.user.email_addresses Mappé directement à partir du champ ActorUPN s'il correspond à un format d'adresse e-mail.
ActorUserId principal.user.userid Mappé directement à partir du champ ActorUserId.
Area target.application Permet de créer le champ target.application en ajoutant "DevOps " au début de la valeur Area.
AuthenticationMechanism extensions.auth.auth_details, security_result.rule_id Analyse pour extraire les informations d'authentification et l'ID de règle. Les informations d'authentification sont mappées sur extensions.auth.auth_details. L'ID de règle extrait est mappé sur security_result.rule_id.
CategoryDisplayName security_result.action_details Mappé directement sur security_result.action_details.
City principal.location.city Mappé directement à partir du champ City.
Conditions additional.fields Ajouté en tant que champ supplémentaire avec la clé "Conditions".
Country principal.location.country_or_region Mappé directement à partir du champ Country.
Data.* Divers Les champs de l'objet Data sont mappés sur différents champs UDM en fonction de leur nom et de leur contexte. Vous trouverez des exemples spécifiques ci-dessous.
Data.AccessLevel target.resource.attribute.labels Ajouté en tant que libellé avec la clé "AccessLevel".
Data.AgentId target.resource.product_object_id Mappé sur target.resource.product_object_id si PipelineId et AuthorizationId ne sont pas présents.
Data.AgentName target.resource.name Mappé sur target.resource.name si PipelineName, NamespaceName et DisplayName ne sont pas présents.
Data.AuthorizationId target.resource.product_object_id Mappé sur target.resource.product_object_id si PipelineId n'est pas présent.
Data.CallerProcedure additional.fields Ajouté en tant que champ supplémentaire avec la clé "CallerProcedure".
Data.CheckSuiteId additional.fields Ajouté en tant que champ supplémentaire avec la clé "CheckSuiteId".
Data.CheckSuiteStatus additional.fields Ajouté en tant que champ supplémentaire avec la clé "CheckSuiteStatus".
Data.ConnectionId additional.fields Ajouté en tant que champ supplémentaire avec la clé "ConnectionId".
Data.ConnectionName additional.fields Ajouté en tant que champ supplémentaire avec la clé "ConnectionName".
Data.ConnectionType additional.fields Ajouté en tant que champ supplémentaire avec la clé "ConnectionType".
Data.DefinitionId additional.fields Ajouté en tant que champ supplémentaire avec la clé "DefinitionId".
Data.DeploymentResult additional.fields Ajouté en tant que champ supplémentaire avec la clé "DeploymentResult".
Data.DisplayName target.resource.name Mappé sur target.resource.name si PipelineName et NamespaceName ne sont pas présents.
Data.EndpointIdList additional.fields Ajouté en tant que champ supplémentaire avec la clé "EndpointIdList".
Data.EnvironmentName additional.fields Ajouté en tant que champ supplémentaire avec la clé "EnvironmentName".
Data.Filter.continuationToken target.resource.attribute.labels Ajouté en tant que libellé avec la clé "continuation_token".
Data.Filter.endTime target.resource.attribute.labels Ajouté en tant que libellé avec la clé "filter_end_time".
Data.Filter.startTime target.resource.attribute.labels Ajouté en tant que libellé avec la clé "filter_start_time".
Data.FinishTime additional.fields Ajouté en tant que champ supplémentaire avec la clé "FinishTime".
Data.GroupId target.group.product_object_id Mappé directement sur target.group.product_object_id lorsque Data.Updates.0.GroupId n'est pas présent.
Data.GroupName target.group.group_display_name Mappé directement sur target.group.group_display_name.
Data.JobName additional.fields Ajouté en tant que champ supplémentaire avec la clé "JobName".
Data.MemberId target.user.userid Mappé directement sur target.user.userid lorsque Data.Updates.0.MemberId n'est pas présent.
Data.MemberDisplayName target.user.user_display_name Mappé directement sur target.user.user_display_name.
Data.NamespaceId target.resource.product_object_id Mappé sur target.resource.product_object_id si PipelineId, AuthorizationId et AgentId ne sont pas présents.
Data.NamespaceName target.resource.name Mappé sur target.resource.name si PipelineName n'est pas présent.
Data.ownerDetails additional.fields Ajouté en tant que champ supplémentaire avec la clé "OwnerDetails".
Data.OwnerId additional.fields Ajouté en tant que champ supplémentaire avec la clé "OwnerId".
Data.PipelineId target.resource.product_object_id Mappé directement sur target.resource.product_object_id.
Data.PipelineName target.resource.name Mappé directement sur target.resource.name.
Data.PipelineRevision target.resource.attribute.labels Ajouté en tant que libellé avec la clé "PipelineRevision".
Data.PipelineScope target.resource.attribute.labels Ajouté en tant que libellé avec la clé "PipelineScope".
Data.PlanType additional.fields Ajouté en tant que champ supplémentaire avec la clé "PlanType".
Data.PreviousAccessLevel target.resource.attribute.labels Ajouté en tant que libellé avec la clé "PreviousAccessLevel".
Data.PublisherName target.resource.attribute.labels Ajouté en tant que libellé avec la clé "PublisherName".
Data.Reason additional.fields Ajouté en tant que champ supplémentaire avec la clé "Reason" (Motif).
Data.ReleaseId additional.fields Ajouté en tant que champ supplémentaire avec la clé "ReleaseId".
Data.ReleaseName additional.fields Ajouté en tant que champ supplémentaire avec la clé "ReleaseName".
Data.RequesterId additional.fields Ajouté en tant que champ supplémentaire avec la clé "RequesterId".
Data.RetentionLeaseId additional.fields Ajouté en tant que champ supplémentaire avec la clé "RetentionLeaseId".
Data.RetentionOwnerId additional.fields Ajouté en tant que champ supplémentaire avec la clé "RetentionOwnerId".
Data.RunName additional.fields Ajouté en tant que champ supplémentaire avec la clé "RunName".
Data.Scopes target.resource.attribute.labels Ajoutés en tant que libellés avec la clé "Champ d'application".
Data.StageName additional.fields Ajouté en tant que champ supplémentaire avec la clé "StageName".
Data.StartTime additional.fields Ajouté en tant que champ supplémentaire avec la clé "StartTime".
Data.TargetUser target.user.userid Mappé directement sur target.user.userid.
Data.Timestamp metadata.event_timestamp Analysé et mappé sur metadata.event_timestamp.
Data.TokenType target.resource.attribute.labels Ajouté en tant que libellé avec la clé "TokenType".
Data.Updates.0.GroupId target.group.product_object_id Mappé directement sur target.group.product_object_id.
Data.Updates.0.MemberId target.user.userid Mappé directement sur target.user.userid.
Data.ValidFrom target.resource.attribute.labels Ajouté en tant que libellé avec la clé "ValidFrom".
Data.ValidTo target.resource.attribute.labels Ajouté en tant que libellé avec la clé "ValidTo".
DewPoint additional.fields Ajouté en tant que champ supplémentaire avec la clé "DewPoint".
Details metadata.description Mappé directement sur metadata.description.
Humidity additional.fields Ajouté en tant que champ supplémentaire avec la clé "Humidité".
Icon additional.fields Ajouté en tant que champ supplémentaire avec la clé "Icône".
Id metadata.product_log_id Mappé directement sur metadata.product_log_id.
IpAddress principal.ip Mappé directement sur principal.ip.
MoonPhase additional.fields Ajouté en tant que champ supplémentaire avec la clé "MoonPhase".
Moonrise additional.fields Ajouté en tant que champ supplémentaire avec la clé "Moonrise".
Moonset additional.fields Ajouté en tant que champ supplémentaire avec la clé "Moonset".
OperationName metadata.product_event_type Mappé directement sur metadata.product_event_type.
Precipitation additional.fields Ajouté en tant que champ supplémentaire avec la clé "Précipitations".
Pressure additional.fields Ajouté en tant que champ supplémentaire avec la clé "Pression".
ProjectId target.resource_ancestors.product_object_id Permet de renseigner le champ product_object_id dans target.resource_ancestors lorsque l'ancêtre est de type CLOUD_PROJECT.
ProjectName target.resource_ancestors.name, target.resource.attribute.labels Permet de renseigner le champ name dans target.resource_ancestors lorsque l'ancêtre est de type CLOUD_PROJECT. Ajouté également en tant que libellé à target.resource.attribute.labels avec la clé "ProjectName".
RoleLocation target.location.name Mappé directement sur target.location.name.
ScopeDisplayName target.resource_ancestors.name Permet de renseigner le champ name dans target.resource_ancestors lorsque l'ancêtre est de type CLOUD_ORGANIZATION.
ScopeId target.resource_ancestors.product_object_id Permet de renseigner le champ product_object_id dans target.resource_ancestors lorsque l'ancêtre est de type CLOUD_ORGANIZATION.
ScopeType additional.fields Ajouté en tant que champ supplémentaire avec la clé "ScopeType".
Sunrise additional.fields Ajouté en tant que champ supplémentaire avec la clé "Sunrise".
Sunset additional.fields Ajouté en tant que champ supplémentaire avec la clé "Arrêt".
Temperature additional.fields Ajouté en tant que champ supplémentaire avec la clé "Température".
TenantId metadata.product_deployment_id, additional.fields Mappé directement sur metadata.product_deployment_id. Ajouté également en tant que champ supplémentaire avec la clé "TenantId".
TimeGenerated metadata.event_timestamp Analysé et mappé sur metadata.event_timestamp.
UserAgent network.http.user_agent, network.http.parsed_user_agent Mappé directement sur network.http.user_agent. Il est également analysé et mappé sur network.http.parsed_user_agent.
UVIndex additional.fields Ajouté en tant que champ supplémentaire avec la clé "UVIndex".
Visibility additional.fields Ajouté en tant que champ supplémentaire avec la clé "Visibilité".
WindDirection additional.fields Ajouté en tant que champ supplémentaire avec la clé "WindDirection".
WindSpeed additional.fields Ajouté en tant que champ supplémentaire avec la clé "WindSpeed".
_Internal_WorkspaceResourceId additional.fields Ajouté en tant que champ supplémentaire avec la clé "workspace_resource_id".
N/A metadata.event_type Déterminé par une logique basée sur OperationName et d'autres champs. La valeur par défaut est "GENERIC_EVENT" si aucun type d'événement spécifique n'est associé. Les valeurs possibles sont "STATUS_SHUTDOWN", "RESOURCE_CREATION", "STATUS_UPDATE", "USER_RESOURCE_DELETION", "RESOURCE_READ", "RESOURCE_WRITTEN", "RESOURCE_DELETION" et "GROUP_MODIFICATION".
N/A metadata.vendor_name Défini sur "Microsoft".
N/A metadata.product_name Définissez-le sur "Azure DevOps".
N/A metadata.log_type Défini sur "AZURE_DEVOPS".
N/A principal.user.account_type Définissez cette valeur sur "SERVICE_ACCOUNT_TYPE" si AuthenticationMechanism contient "ServicePrincipal", sinon sur "CLOUD_ACCOUNT_TYPE".
N/A target.asset.attribute.cloud.environment Variable définie sur MICROSOFT_AZURE.
N/A security_result.action Définissez cette valeur sur "ALLOW" pour les opérations réussies (Succeeded, Created, Modified, executed, updated, removed) et sur "BLOCK" pour les opérations ayant échoué (Failed, TimedOut).
N/A extensions.auth.mechanism Défini sur "USERNAME_PASSWORD" si summary est "UserAuthToken".
N/A target.resource.resource_type Défini sur "SETTING" si pipeline_id est présent, "CREDENTIAL" si authorization_id est présent, "DEVICE" si agent_id est présent ou "DATABASE" si namespace_id est présent. Sinon, elle est définie sur "STORAGE_BUCKET" dans certains cas en fonction de operationName.
N/A target.resource.resource_subtype Défini sur "Pipeline" si pipeline_id est présent, "Jeton" si authorization_id est présent, "Agent" si agent_id est présent ou "Espace de noms" si namespace_id est présent.

Modifications

2024-01-19

  • Modification de la valeur "metadata.eventtype" de "SERVICE*" en "USER_RESOURCE_UPDATE_CONTENT" si des données utilisateur principales et des données de ressources cibles sont présentes.
  • Modification du mappage de "IpAddress" de "target.ip" à "principal.ip".
  • Modification du mappage de "ActorCUID" de "principal.user.product_object_id" à "additional.fields".
  • Modification du mappage de "ScopeId" de "principal.asset_id" à "resource_ancestors.product_object_id".
  • Modification du mappage de "_Internal_WorkspaceResourceId" de "target.resource.product_object_id" à "additional.fields".
  • La mise en correspondance de "ProjectId" est passée de "target.resource.attribute.labels" à "target.resource_ancestors.product_object_id".
  • Modification du mappage de "AuthenticationMechanism" de "security_result.summary" à "extensions.auth.auth_details".
  • Modification du mappage de "CorrelationId" de "network.session_id" à "additional.fields".
  • Modification du mappage de "ScopeDisplayName" de "additional.fields" à "target.resource_ancestors.name".
  • Modification du mappage de "PipelineId" de "additional.fields" à "target.resource.product_object_id".
  • Modification de la mise en correspondance de "PipelineName" de "additional.fields" à "target.resource.name".
  • Modification du mappage de "PipelineScope" de "additional.fields" à "target.resource.attribute.labels".
  • Modification du mappage de "PipelineRevision" de "additional.fields" à "target.resource.attribute.labels".
  • La mise en correspondance de "ProjectId" est passée de "target.resource.resource.attribute.labels" à "target.resource_ancestors.product_object_id".
  • La mise en correspondance de "Zone" a été modifiée de "additional.fields" à "target.application".
  • Mappage de la valeur "MICROSOFT_AZURE" sur "target.asset.attribute.cloud.environment".
  • Lorsque la valeur "ServicePrincipal" est définie pour "AuthenticationMechanism", définissez "SERVICE_ACCOUNT_TYPE" sur "principal.user.account_type", sinon définissez "CLOUD_ACCOUNT_TYPE" sur "principal.user.account_type".
  • "Category" a été mappé sur "security_result.action_details".
  • Mappage de "ALLOW" ou "BLOCK" sur "security_result.action" en fonction du champ "Details".
  • Mappage de "ActivityId" sur "additional.fields".

2024-01-09

  • Ajout de Grok et de gsub pour analyser les journaux JSON non analysés.
  • "rec.correlationId", "properties.currentHealthStatus", "properties.previousHealthStatus", "properties.type", "properties.cause", "properties.title", "properties.details", "properties.recommendationType", "properties.recommendationCategory", "properties.recommendationImpact", "properties.recommendationName", "properties.recommendationResourceLink", "properties.recommendationSchemaVersion", "properties.eventCategory", "properties.hierarchy", "properties.message", "properties.entity", "identity.claims.xms.tcdt", "identity.claims.aio", "identity.claims.appid", "identity.claims.appidacr", "identity.claims.aud", "identity.claims.exp", "identity.claims.iat", "identity.claims.idtyp", "identity.claims.iss", "identity.claims.uti", "identity.claims.rh", "identity.claims.ver", "identity.claims.nbf", "identity.authorization.evidence.roleAssignmentId", "identity.authorization.evidence.principalType", "identity.authorization.evidence.principalId", "identity.authorization.evidence.roleAssignmentScope", "identity.authorization.evidence.roleDefinitionId" mappés sur "security_result.detection_fields".
  • "resultSignature.label", "rec.resultType", "Visibility", "Humidity", "Precipitation","MoonPhase", "Moonrise", "Moonset", "Pressure", "WindSpeed", "UVIndex", "DewPoint", WindDirection", "Sunrise", "Sunset", "Temperature", "Icon", "Conditions" à "additional.fields".
  • Mappage de "level" sur "security_result.severity".
  • "appname" a été mappé sur "target.application".
  • Mappage de "category.details" sur "security.result.category.details".
  • "rec.resourceId" a été mappé sur "target.resource.id".
  • Mappage de "res.extensionResourceName" sur "principal.hostname".

2023-11-23

  • Prise en charge d'un nouveau format de journaux JSON.
  • Mappage de "data.TimeGenerated" sur "metadata.event_timestamp".
  • Lorsque "_Internal_WorkspaceResourceId" est manquant, la valeur "topic" est mappée sur "target.resource.product_object_id".
  • Mappage de "data.Data.ConnectionId" sur "additional.fields".
  • Mappage de "data.Data.ownerDetails" sur "additional.fields".
  • "data.Data.DeploymentResult" a été mappé sur "additional.fields".
  • "data.Data.EnvironmentName" a été mappé sur "additional.fields".
  • "data.Data.JobName" a été mappé sur "additional.fields".
  • "data.Data.StageName" a été mappé sur "additional.fields".
  • "data.Data.RunName" a été mappé sur "additional.fields".
  • "data.Data.RetentionLeaseId" a été mappé sur "additional.fields".
  • Mappage de "data.Data.CheckSuiteId" sur "additional.fields".
  • Mappage de "data.Data.CheckSuiteStatus" sur "additional.fields".
  • "data.Data.ApprovalRequest" a été mappé sur "additional.fields".
  • "data.Data.ApprovalType" a été mappé sur "additional.fields".
  • Mappage de "subject" sur "additional.fields".
  • Mappage de "data.ActorUserId" sur "principal.user.userid".
  • Mappage de "data.ActorDisplayName" sur "principal.user.user_display_name".
  • Mappage de "data.ActorCUID" sur "principal.user.product_object_id".
  • Mappage de "data.ActorUPN" sur "principal.user.email_addresses".
  • "data.ScopeId" a été mappé sur "principal.asset_id".
  • "data.CorrelationId" a été mappé sur "network.session_id".
  • Mappage de "data.UserAgent" sur "network.http.user_agent".
  • "data.ProjectId" a été mappé sur "target.resource.attribute.labels".
  • "data.ScopeType" a été mappé sur "additional.fields".
  • "data.ProjectName" a été mappé sur "target.resource.attribute.labels".
  • Mappage de "data.Details" sur "metadata.description".
  • "data.CategoryDisplayName" a été mappé sur "security_result.rule_name".
  • Mappage de "data.Area" sur "additional.fields".
  • "data.Id" a été mappé sur "metadata.product_log_id".
  • "data.ActionId" a été mappé sur "metadata.product_event_type".
  • Mappage de "data.Timestamp" sur "metadata.event_timestamp".

2022-06-28

  • Analyseur nouvellement créé