Collect Azure DevOps audit logs

Supported in:

Overview

This parser handles Azure DevOps audit logs in JSON format. It extracts fields from nested and top-level JSON structures, mapping them to the UDM. Conditional logic based on specific field values categorizes events and enriches the output with relevant security information. The parser also handles non-JSON formatted messages by attempting to extract a JSON payload using grok patterns.

Before you begin

Ensure you have the following prerequisites:

  • Google SecOps instance
  • An active Azure DevOps Organization
  • Privileged access to Azure Devops Organization and Azure

Set up feeds

There are two different entry points to set up feeds in the Google SecOps platform:

  • SIEM Settings > Feeds > Add New
  • Content Hub > Content Packs > Get Started

How to set up the Azure DevOps audit feed

  1. Click the Azure Platformpack.
  2. Locate the Azure DevOps auditlog type and click Add new feed.
  3. Specify values for the following fields:

    • Source Type: Microsoft Azure Blob Storage V2.
    • Azure URI: The blob endpoint URL.
      • ENDPOINT_URL/BLOB_NAME
        • Replace the following:
          • ENDPOINT_URL : The blob endpoint URL ( https://<storageaccountname>.blob.core.windows.net )
          • BLOB_NAME : The name of the blob (such as, insights-logs-<logname> )
    • Source deletion options: Select the deletion option according to your ingestion preferences.

    • Maximum File Age: Includes files modified in the last number of days. Default is 180 days.

    • Shared key: The shared key (a 512-bit random string in base-64 encoding) used to access Azure resources.

    Advanced options

    • Feed Name: A prepopulated value that identifies the feed.
    • Asset namespace: The asset namespace .
    • Ingestion labels: The label applied to the events from this feed.
  4. Click Create feed.

For more information about configuring multiple feeds for different log types within this product family, see Configure feeds by product .

Create an API key for the webhook feed

  1. Go to Google Cloud console > Credentials.

    Go to Credentials

  2. Click Create credentials, and then select API key.

  3. Restrict the API key access to the Google Security Operations API.

Specify the endpoint URL

  1. In your client application, specify the HTTPS endpoint URL provided in the webhook feed.
  2. Enable authentication by specifying the API key and secret key as part of the custom header in the following format:

     X-goog-api-key = API_KEY 
    X-Webhook-Access-Key = SECRET 
     
    

    Recommendation: Specify the API key as a header instead of specifying it in the URL. If your webhook client doesn't support custom headers, you can specify the API key and secret key using query parameters in the following format:

      ENDPOINT_URL 
    ?key= API_KEY 
    &secret= SECRET 
     
    

Replace the following:

  • ENDPOINT_URL : The feed endpoint URL.
  • API_KEY : The API key to authenticate to Google Security Operations.
  • SECRET : The secret key that you generated to authenticate the feed.

Configure Auditing feature in Azure Devops

  1. Sign in to your organization ( https://dev.azure.com/{yourorganization} ).
  2. Select the gear icon for Organization settings.
  3. Select Policiesunder Security.
  4. Toggle the Log Audit Eventsbutton to ON.

Configure an Event Grid Topic in Azure

  1. Sign in to the Azure Portal.
  2. Search for and access Event Grid.
  3. Locate Topicsunder Custom events.
  4. Click + Create.
  5. Select your Subscriptionand Resource Group. Provide a name (for example, DevopsAuditLog ) and select the region. Click Review and create.
  6. Access the new Topicand copy the Topic Endpoint URL.
  7. Go to Settings > Access Keysand copy Key 1.

Configure Azure Devops Log Stream to Event Grid

  1. Sign in to your organization ( https://dev.azure.com/{yourorganization} ).
  2. Select the gear icon for Organization settings.
  3. Select Auditing.
  4. Go to the Streamstab and select New stream > Event Grid.
  5. Enter the topic endpointand access keycreated in Configure an Event Grid Topic in Azure .

Configure a Webhook in Azure DevOps for Google SecOps

  1. In the Azure Portal, search for and access Event Grid.
  2. Select previously created Topic.
  3. Go to Entities > Event Subscription.
  4. Click + Event Subscription.
  5. Provide a descriptive name (for example, * Google SecOps Integration ).
  6. Select Web Hookand click Configure an endpoint.
  7. Configure the endpoint:
    1. Subscriber endpoint: Enter the Google SecOps API endpoint URL.
    2. In the HTTP headerssection, add the following headers:
    3. Set the Content-Typeheader to application/json .
  8. Click Create.

UDM Mapping Table

Log Field UDM Mapping Logic
ActivityId
metadata.product_log_id Directly mapped from the Id field in the raw log when the records field is not present, or from the ActivityId field within the data object when records is present.
ActionId
metadata.product_event_type Directly mapped from the ActionId field within the data object.
ActorCUID
additional.fields Included as an additional field with key "Actor CUID".
ActorDisplayName
principal.user.user_display_name Directly mapped from the ActorDisplayName field if it's not "Azure DevOps Service". If it is "Azure DevOps Service", it's added as a label to principal.resource.attribute.labels .
ActorUPN
principal.user.email_addresses Directly mapped from the ActorUPN field if it matches an email address pattern.
ActorUserId
principal.user.userid Directly mapped from the ActorUserId field.
Area
target.application Used to construct the target.application field by prepending "DevOps " to the Area value.
AuthenticationMechanism
extensions.auth.auth_details , security_result.rule_id Parsed to extract authentication details and rule ID. The authentication details are mapped to extensions.auth.auth_details . The extracted rule ID is mapped to security_result.rule_id .
CategoryDisplayName
security_result.action_details Directly mapped to security_result.action_details .
City
principal.location.city Directly mapped from the City field.
Conditions
additional.fields Added as an additional field with key "Conditions".
Country
principal.location.country_or_region Directly mapped from the Country field.
Data.*
Various Fields within the Data object are mapped to different UDM fields based on their names and context. See below for specific examples.
Data.AccessLevel
target.resource.attribute.labels Added as a label with key "AccessLevel".
Data.AgentId
target.resource.product_object_id Mapped to target.resource.product_object_id if PipelineId and AuthorizationId are not present.
Data.AgentName
target.resource.name Mapped to target.resource.name if PipelineName , NamespaceName , and DisplayName are not present.
Data.AuthorizationId
target.resource.product_object_id Mapped to target.resource.product_object_id if PipelineId is not present.
Data.CallerProcedure
additional.fields Added as an additional field with key "CallerProcedure".
Data.CheckSuiteId
additional.fields Added as an additional field with key "CheckSuiteId".
Data.CheckSuiteStatus
additional.fields Added as an additional field with key "CheckSuiteStatus".
Data.ConnectionId
additional.fields Added as an additional field with key "ConnectionId".
Data.ConnectionName
additional.fields Added as an additional field with key "ConnectionName".
Data.ConnectionType
additional.fields Added as an additional field with key "ConnectionType".
Data.DefinitionId
additional.fields Added as an additional field with key "DefinitionId".
Data.DeploymentResult
additional.fields Added as an additional field with key "DeploymentResult".
Data.DisplayName
target.resource.name Mapped to target.resource.name if PipelineName and NamespaceName are not present.
Data.EndpointIdList
additional.fields Added as an additional field with key "EndpointIdList".
Data.EnvironmentName
additional.fields Added as an additional field with key "EnvironmentName".
Data.Filter.continuationToken
target.resource.attribute.labels Added as a label with key "continuation_token".
Data.Filter.endTime
target.resource.attribute.labels Added as a label with key "filter_end_time".
Data.Filter.startTime
target.resource.attribute.labels Added as a label with key "filter_start_time".
Data.FinishTime
additional.fields Added as an additional field with key "FinishTime".
Data.GroupId
target.group.product_object_id Directly mapped to target.group.product_object_id when Data.Updates.0.GroupId is not present.
Data.GroupName
target.group.group_display_name Directly mapped to target.group.group_display_name .
Data.JobName
additional.fields Added as an additional field with key "JobName".
Data.MemberId
target.user.userid Directly mapped to target.user.userid when Data.Updates.0.MemberId is not present.
Data.MemberDisplayName
target.user.user_display_name Directly mapped to target.user.user_display_name .
Data.NamespaceId
target.resource.product_object_id Mapped to target.resource.product_object_id if PipelineId , AuthorizationId , and AgentId are not present.
Data.NamespaceName
target.resource.name Mapped to target.resource.name if PipelineName is not present.
Data.ownerDetails
additional.fields Added as an additional field with key "OwnerDetails".
Data.OwnerId
additional.fields Added as an additional field with key "OwnerId".
Data.PipelineId
target.resource.product_object_id Directly mapped to target.resource.product_object_id .
Data.PipelineName
target.resource.name Directly mapped to target.resource.name .
Data.PipelineRevision
target.resource.attribute.labels Added as a label with key "PipelineRevision".
Data.PipelineScope
target.resource.attribute.labels Added as a label with key "PipelineScope".
Data.PlanType
additional.fields Added as an additional field with key "PlanType".
Data.PreviousAccessLevel
target.resource.attribute.labels Added as a label with key "PreviousAccessLevel".
Data.PublisherName
target.resource.attribute.labels Added as a label with key "PublisherName".
Data.Reason
additional.fields Added as an additional field with key "Reason".
Data.ReleaseId
additional.fields Added as an additional field with key "ReleaseId".
Data.ReleaseName
additional.fields Added as an additional field with key "ReleaseName".
Data.RequesterId
additional.fields Added as an additional field with key "RequesterId".
Data.RetentionLeaseId
additional.fields Added as an additional field with key "RetentionLeaseId".
Data.RetentionOwnerId
additional.fields Added as an additional field with key "RetentionOwnerId".
Data.RunName
additional.fields Added as an additional field with key "RunName".
Data.Scopes
target.resource.attribute.labels Added as labels with key "Scope".
Data.StageName
additional.fields Added as an additional field with key "StageName".
Data.StartTime
additional.fields Added as an additional field with key "StartTime".
Data.TargetUser
target.user.userid Directly mapped to target.user.userid .
Data.Timestamp
metadata.event_timestamp Parsed and mapped to metadata.event_timestamp .
Data.TokenType
target.resource.attribute.labels Added as a label with key "TokenType".
Data.Updates.0.GroupId
target.group.product_object_id Directly mapped to target.group.product_object_id .
Data.Updates.0.MemberId
target.user.userid Directly mapped to target.user.userid .
Data.ValidFrom
target.resource.attribute.labels Added as a label with key "ValidFrom".
Data.ValidTo
target.resource.attribute.labels Added as a label with key "ValidTo".
DewPoint
additional.fields Added as an additional field with key "DewPoint".
Details
metadata.description Directly mapped to metadata.description .
Humidity
additional.fields Added as an additional field with key "Humidity".
Icon
additional.fields Added as an additional field with key "Icon".
Id
metadata.product_log_id Directly mapped to metadata.product_log_id .
IpAddress
principal.ip Directly mapped to principal.ip .
MoonPhase
additional.fields Added as an additional field with key "MoonPhase".
Moonrise
additional.fields Added as an additional field with key "Moonrise".
Moonset
additional.fields Added as an additional field with key "Moonset".
OperationName
metadata.product_event_type Directly mapped to metadata.product_event_type .
Precipitation
additional.fields Added as an additional field with key "Precipitation".
Pressure
additional.fields Added as an additional field with key "Pressure".
ProjectId
target.resource_ancestors.product_object_id Used to populate the product_object_id field within target.resource_ancestors when the ancestor is of type CLOUD_PROJECT .
ProjectName
target.resource_ancestors.name , target.resource.attribute.labels Used to populate the name field within target.resource_ancestors when the ancestor is of type CLOUD_PROJECT . Also added as a label to target.resource.attribute.labels with key "ProjectName".
RoleLocation
target.location.name Directly mapped to target.location.name .
ScopeDisplayName
target.resource_ancestors.name Used to populate the name field within target.resource_ancestors when the ancestor is of type CLOUD_ORGANIZATION .
ScopeId
target.resource_ancestors.product_object_id Used to populate the product_object_id field within target.resource_ancestors when the ancestor is of type CLOUD_ORGANIZATION .
ScopeType
additional.fields Added as an additional field with key "ScopeType".
Sunrise
additional.fields Added as an additional field with key "Sunrise".
Sunset
additional.fields Added as an additional field with key "Sunset".
Temperature
additional.fields Added as an additional field with key "Temperature".
TenantId
metadata.product_deployment_id , additional.fields Directly mapped to metadata.product_deployment_id . Also added as an additional field with key "TenantId".
TimeGenerated
metadata.event_timestamp Parsed and mapped to metadata.event_timestamp .
UserAgent
network.http.user_agent , network.http.parsed_user_agent Directly mapped to network.http.user_agent . Also parsed and mapped to network.http.parsed_user_agent .
UVIndex
additional.fields Added as an additional field with key "UVIndex".
Visibility
additional.fields Added as an additional field with key "Visibility".
WindDirection
additional.fields Added as an additional field with key "WindDirection".
WindSpeed
additional.fields Added as an additional field with key "WindSpeed".
_Internal_WorkspaceResourceId
additional.fields Added as an additional field with key "workspace_resource_id".
N/A
metadata.event_type Determined by logic based on the OperationName and other fields. Defaults to "GENERIC_EVENT" if no specific event type is matched. Possible values include "STATUS_SHUTDOWN", "RESOURCE_CREATION", "STATUS_UPDATE", "USER_RESOURCE_DELETION", "RESOURCE_READ", "RESOURCE_WRITTEN", "RESOURCE_DELETION", and "GROUP_MODIFICATION".
N/A
metadata.vendor_name Set to "Microsoft".
N/A
metadata.product_name Set to "Azure DevOps".
N/A
metadata.log_type Set to "AZURE_DEVOPS".
N/A
principal.user.account_type Set to "SERVICE_ACCOUNT_TYPE" if AuthenticationMechanism contains "ServicePrincipal", otherwise set to "CLOUD_ACCOUNT_TYPE".
N/A
target.asset.attribute.cloud.environment Set to MICROSOFT_AZURE .
N/A
security_result.action Set to "ALLOW" for successful operations (Succeeded, Created, Modified, executed, updated, removed) and "BLOCK" for failed operations (Failed, TimedOut).
N/A
extensions.auth.mechanism Set to "USERNAME_PASSWORD" if summary is "UserAuthToken".
N/A
target.resource.resource_type Set to "SETTING" if pipeline_id is present, "CREDENTIAL" if authorization_id is present, "DEVICE" if agent_id is present, or "DATABASE" if namespace_id is present. Otherwise, it is set to "STORAGE_BUCKET" in some cases based on operationName .
N/A
target.resource.resource_subtype Set to "Pipeline" if pipeline_id is present, "Token" if authorization_id is present, "Agent" if agent_id is present, or "Namespace" if namespace_id is present.

Need more help? Get answers from Community members and Google SecOps professionals.

Create a Mobile Website
View Site in Mobile | Classic
Share by: