收集 Azure DevOps 审核日志

解析器版本:3.0

支持范围:

此解析器可处理 JSON 格式的 Azure DevOps 审核日志。它会从嵌套和顶级 JSON 结构中提取字段,并将其映射到 UDM。基于特定字段值的条件逻辑会对事件进行分类,并使用相关安全信息丰富输出。解析器还会尝试使用 grok 模式提取 JSON 载荷,从而处理非 JSON 格式的消息。

准备工作

确保您满足以下前提条件:

  • Google SecOps 实例
  • 一个活跃的 Azure DevOps 组织
  • 对 Azure DevOps 组织和 Azure 的特权访问权限

设置 Feed

在 Google SecOps 平台中,您可以通过两个不同的入口点设置 Feed:

  • 设置 > 数据管理 > Feed > 添加新 Feed(在仅限 SIEM 的平台上,依次点击设置 > Feed > 添加新 Feed)
  • 内容中心 > 内容包 > 开始使用

如何设置 Azure DevOps 审核 Feed

  1. 点击 Azure Platform 软件包。
  2. 找到 Azure DevOps 审核日志类型,然后点击添加新 Feed。
  3. 为以下字段指定值:

    • 来源类型:Microsoft Azure Blob Storage V2。
    • Azure URI:Blob 端点网址。
      • ENDPOINT_URL/BLOB_NAME
        • 替换以下内容:
          • ENDPOINT_URL:Blob 端点网址 (https://<storageaccountname>.blob.core.windows.net)
          • BLOB_NAME:blob 的名称(例如 insights-logs-<logname>)
    • 来源删除选项:根据您的提取偏好设置选择删除选项。

    • 文件存在时间上限:包含过去指定天数内修改过的文件。默认值为 180 天。

    • 共享密钥:用于访问 Azure 资源的共享密钥(采用 base-64 编码的 512 位随机字符串)。

    高级选项

    • Feed 名称:用于标识 Feed 的预填充值。
    • 资产命名空间:资产命名空间。
    • 注入标签:应用于此 Feed 中事件的标签。
  4. 点击创建 Feed。

如需详细了解如何为此产品系列中的不同日志类型配置多个 Feed,请参阅按产品配置 Feed。

为 webhook Feed 创建 API 密钥

  1. 前往 Google Cloud 控制台 > 凭证。

    转到“凭据”页面

  2. 点击创建凭据,然后选择 API 密钥。

  3. 将 API 密钥访问权限限制为 Google Security Operations API。

指定端点网址

  1. 在客户端应用中,指定 Webhook Feed 中提供的 HTTPS 端点网址。
  2. 通过在自定义标头中以以下格式指定 API 密钥和密钥,启用身份验证:

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

    建议:将 API 密钥指定为标头,而不是在网址中指定。如果您的 webhook 客户端不支持自定义标头,您可以使用以下格式的查询参数指定 API 密钥和密钥:

    ENDPOINT_URL?key=API_KEY&secret=SECRET
    

替换以下内容:

  • ENDPOINT_URL:Feed 端点网址。
  • API_KEY:用于向 Google Security Operations 进行身份验证的 API 密钥。
  • SECRET:您为验证 Feed 而生成的密钥。

在 Azure DevOps 中配置审核功能

  1. 登录您的组织 (https://dev.azure.com/{yourorganization})。
  2. 选择组织设置对应的齿轮图标。
  3. 选择安全下的政策。
  4. 将记录审核事件按钮切换到开启。

在 Azure 中配置事件网格主题

  1. 登录 Azure 门户。
  2. 搜索并访问 Event Grid。
  3. 在自定义事件下找到主题。
  4. 点击 + 创建。
  5. 选择订阅和资源组。提供名称(例如 DevopsAuditLog),然后选择区域。点击检查并创建。
  6. 访问新主题,然后复制主题端点网址。
  7. 依次前往设置 > 访问密钥,然后复制密钥 1。

配置 Azure DevOps 日志流到 Event Grid

  1. 登录您的组织 (https://dev.azure.com/{yourorganization})。
  2. 选择组织设置对应的齿轮图标。
  3. 选择审核。
  4. 前往数据流标签页,然后依次选择新建数据流 > Event Grid。
  5. 输入在在 Azure 中配置 Event Grid 主题中创建的主题端点和访问密钥。

在 Azure DevOps 中为 Google SecOps 配置 Webhook

  1. 在 Azure 门户中,搜索并访问 Event Grid。
  2. 选择之前创建的主题。
  3. 前往实体 > 事件订阅。
  4. 点击 + Event Subscription(+ 事件订阅)。
  5. 提供描述性名称(例如 *Google SecOps Integration)。
  6. 选择 Web Hook,然后点击配置端点。
  7. 配置端点:
    1. Subscriber endpoint(订阅者端点):输入 Google SecOps API 端点网址。
    2. 在 HTTP 标头部分中,添加以下标头:
    3. 将 Content-Type 标头设置为 application/json。
  8. 点击创建。

支持的 Azure DevOps 审核示例日志

  • 标准审核 JSON

    {
      "ActivityId": "aeec0738-ebbf-4e62-9a44-83dd7b704e75",
      "ActorCUID": "e0729319-5632-78c1-9625-b53fe559bcd7",
      "ActorDisplayName": "User Name",
      "ActorUPN": "user@example.com",
      "ActorUserId": "e0729319-5632-68c1-9625-b53fe559bcd7",
      "Area": "Group",
      "AuthenticationMechanism": "SessionToken_Unscoped authorizationId: f5729c3d-951b-4a52-88d9-a",
      "Category": "Modify",
      "CategoryDisplayName": "Modify",
      "CorrelationId": "a26a652e-1596-4c83-bb0f-946ff3ccc91c",
      "Data": {
        "CallerProcedure": "prc_UpdateGroupMembership",
        "EventAuthor": "b33f1e32-f5e3-4210-9fde-6e61f7a761b3",
        "Idempotent": "True",
        "Incremental": "True",
        "InsertInactiveUpdates": "False",
        "ScopeId": "1b713128-b6f0-4fd7-91af-94ed1f69c464",
        "Updates": [
          {
            "GroupId": "BE656E6C-7C01-47DB-BC03-CD7E82610AFE",
            "MemberId": "9D4E1A54-8B4C-42E2-BECC-94BEDC6E2F4B",
            "Active": true
          }
        ],
        "GroupId": "be656e6c-7c01-47db-bc03-cd7e82610afe",
        "GroupName": "[Project_Alpha]\\Project Administrators",
        "MemberId": "9d4e1a54-8b4c-42e2-becc-94bedc6e2f4b",
        "MemberDisplayName": "Member Name"
      },
      "Details": "Member Name was added as a member of group [Project_Alpha]\\Project Administrators",
      "Id": "0b11aadb-0bcc-47ef-9038-b091140dcbe5",
      "IpAddress": "192.168.1.10",
      "OperationName": "Group.UpdateGroupMembership.Add",
      "ProjectId": "00000000-0000-0000-0000-000000000000",
      "ScopeDisplayName": "Organization_X",
      "ScopeId": "1b713128-b6f0-4fd7-91af-94ed1f69c464",
      "ScopeType": "Enterprise",
      "SourceSystem": "Azure",
      "TenantId": "5ca654a4-807f-4676-9c9f-0b7335cea18e",
      "TimeGenerated": "2022-06-20T00:43:35.7370000Z",
      "Type": "AzureDevOpsAuditing",
      "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36",
      "_Internal_WorkspaceResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-event-grid/providers/microsoft.operationalinsights/workspaces/logging-workspace"
    }
    
  • 事件网格封装的 JSON

    {
      "id": "9362f75d-b450-47e0-a54b-4fd51d08798e",
      "subject": "AzureDevOps/Auditing",
      "data": {
        "Id": "9362f75d-b450-47e0-a54b-4fd51d08798e",
        "CorrelationId": "848f8abd-9f91-479e-857b-454efa0bf393",
        "ActivityId": "0b7078f1-87bb-441d-8dcc-780c6d0a0511",
        "ActorCUID": "00000000-0000-0000-0000-000000000000",
        "ActorUserId": "0000000d-0000-8888-8000-000000000000",
        "ActorClientId": "00000000-0000-0000-0000-000000000000",
        "ActorUPN": "Azure DevOps Service",
        "Timestamp": "2023-08-03T23:34:31.037Z",
        "ScopeType": 4,
        "ScopeDisplayName": "Organization_X",
        "ScopeId": "1bf2d4d0-3f60-4f08-b217-ce48cebc6816",
        "ProjectId": "b87f0d76-bb83-4274-a865-5ebdc6fe0500",
        "ProjectName": "IT_Project",
        "UserAgent": "TFS JobAgent(TfsJobAgent.exe, 19.224.33927.8)",
        "ActionId": "Release.DeploymentCompleted",
        "Data": {
          "CallerProcedure": "Release.prc_OnDeploymentCompleted",
          "DeploymentResult": "Succeeded",
          "PipelineId": "18",
          "PipelineName": "digital-client-app-dvlp",
          "ReleaseName": "23.07.38",
          "RequesterId": "0000000D-0000-8888-8000-000000000000",
          "StageName": "Build browser"
        },
        "Details": "Deployment of release \"23.07.38\" on pipeline \"digital-client-app-dvlp\" to \"Build browser\" in Project IT_Project was Succeeded",
        "Area": "Release",
        "Category": 5,
        "CategoryDisplayName": "Execute",
        "ActorDisplayName": "Azure DevOps Service"
      },
      "eventType": "AzureDevOpsAuditEvent",
      "dataVersion": "1.0",
      "metadataVersion": "1",
      "eventTime": "2023-08-03T23:34:31.037Z",
      "topic": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-prod/providers/Microsoft.EventGrid/topics/audit-topic"
    }
    
  • Event Grid JSON 数组

    [
      {
        "id": "14b02dab-67eb-4d9d-acd2-4487aac05b14",
        "subject": "AzureDevOps/Auditing",
        "data": {
          "Id": "14b02dab-67eb-4d9d-acd2-4487aac05b14",
          "CorrelationId": "e0475568-bd77-484b-b065-5170561f0bf5",
          "ActivityId": "a2a70439-18dd-4bbb-be20-2844600feaca",
          "ActorCUID": "712594c0-94c1-779b-af6c-80752141078d",
          "ActorUserId": "712594c0-94c1-679b-af6c-80752141078d",
          "ActorClientId": "00000000-0000-0000-0000-000000000000",
          "ActorUPN": "user@example.com",
          "AuthenticationMechanism": "Basic_AAD",
          "Timestamp": "2023-12-20T18:33:21.9375261Z",
          "ScopeType": 4,
          "ScopeDisplayName": "Organization_X",
          "ScopeId": "021edafa-0760-4e1d-ba33-00b910e811e9",
          "ProjectId": "00000000-0000-0000-0000-000000000000",
          "IpAddress": "10.0.0.50",
          "UserAgent": "python/3.11.5 (Windows-10-10.0.19045-SP0) msrest/0.7.1 azure-devops/5.1.0b4 devOpsCli/0.25.0",
          "ActionId": "Security.ModifyPermission",
          "Data": {
            "NamespaceId": "b7e84409-6553-448a-bbb2-af228e07cbeb",
            "NamespaceName": "Library",
            "Token": "Library/Collection/VariableGroup/4693",
            "Permissions": [
              {
                "baseEntry": {
                  "descriptor": "Microsoft.TeamFoundation.Identity;S-1-9-1551374245...",
                  "allow": 19,
                  "deny": 0,
                  "isEmpty": false
                },
                "inheritedAllow": 0,
                "inheritedDeny": 0,
                "effectiveAllow": 0,
                "effectiveDeny": 0,
                "includesExtendedInfo": false,
                "descriptor": "Microsoft.TeamFoundation.Identity;S-1-9-1551374245...",
                "allow": 19,
                "deny": 0,
                "isEmpty": false
              }
            ],
            "EventSummary": [
              {
                "PermissionNames": "View library item",
                "Change": "allow",
                "SubjectDescriptor": "Microsoft.TeamFoundation.Identity;S-1-9-1551374245...",
                "SubjectDisplayName": "[Team_Project]\\Project Administrators"
              }
            ],
            "EventSummaryType": "ChangedPermission",
            "SubjectDisplayName": "[Team_Project]\\Project Administrators"
          },
          "Details": "3 permissions were modified for [Team_Project]\\Project Administrators",
          "Area": "Permissions",
          "Category": 1,
          "CategoryDisplayName": "Modify",
          "ActorDisplayName": "User Name"
        },
        "eventType": "AzureDevOpsAuditEvent",
        "dataVersion": "1.0",
        "metadataVersion": "1",
        "eventTime": "2023-12-20T18:33:21.9375261Z",
        "topic": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-prod/providers/Microsoft.EventGrid/topics/audit-topic"
      }
    ]
    

UDM 映射表

日志字段 UDM 映射 逻辑
ActivityId metadata.product_log_id 如果 records 字段不存在,则直接从原始日志中的 Id 字段映射;如果 records 存在,则从 data 对象中的 ActivityId 字段映射。
ActionId metadata.product_event_type 直接从 data 对象中的 ActionId 字段映射。
ActorCUID additional.fields 作为附加字段包含在内,键为“Actor CUID”。
ActorDisplayName principal.user.user_display_name 如果 ActorDisplayName 字段不是“Azure DevOps Service”,则直接从该字段映射。如果为“Azure DevOps Service”,则会作为标签添加到 principal.resource.attribute.labels。
ActorUPN principal.user.email_addresses 如果 ActorUPN 字段与电子邮件地址格式匹配,则直接从该字段映射。
ActorUserId principal.user.userid 直接从 ActorUserId 字段映射。
Area target.application 用于通过在 Area 值前面添加“DevOps ”来构造 target.application 字段。
AuthenticationMechanism extensions.auth.auth_details,security_result.rule_id 经过解析,可提取身份验证详细信息和规则 ID。身份验证详细信息会映射到 extensions.auth.auth_details。提取的规则 ID 会映射到 security_result.rule_id。
CategoryDisplayName security_result.action_details 直接映射到 security_result.action_details。
City principal.location.city 直接从 City 字段映射。
Conditions additional.fields 作为附加字段添加,键为“Conditions”。
Country principal.location.country_or_region 直接从 Country 字段映射。
Data.* 多项 Data 对象中的字段会根据其名称和上下文映射到不同的 UDM 字段。请参阅以下具体示例。
Data.AccessLevel target.resource.attribute.labels 添加为键为“AccessLevel”的标签。
Data.AgentId target.resource.product_object_id 如果 PipelineId 和 AuthorizationId 不存在,则映射到 target.resource.product_object_id。
Data.AgentName target.resource.name 如果 PipelineName、NamespaceName 和 DisplayName 不存在,则映射到 target.resource.name。
Data.AuthorizationId target.resource.product_object_id 如果 PipelineId 不存在,则映射到 target.resource.product_object_id。
Data.CallerProcedure additional.fields 作为附加字段添加,键为“CallerProcedure”。
Data.CheckSuiteId additional.fields 已添加为键为“CheckSuiteId”的额外字段。
Data.CheckSuiteStatus additional.fields 已添加为键为“CheckSuiteStatus”的附加字段。
Data.ConnectionId additional.fields 作为附加字段添加,键为“ConnectionId”。
Data.ConnectionName additional.fields 作为附加字段添加,键为“ConnectionName”。
Data.ConnectionType additional.fields 作为附加字段添加,键为“ConnectionType”。
Data.DefinitionId additional.fields 作为附加字段添加,键为“DefinitionId”。
Data.DeploymentResult additional.fields 作为附加字段添加,键为“DeploymentResult”。
Data.DisplayName target.resource.name 如果 PipelineName 和 NamespaceName 不存在,则映射到 target.resource.name。
Data.EndpointIdList additional.fields 作为附加字段添加,键为“EndpointIdList”。
Data.EnvironmentName additional.fields 作为附加字段添加,键为“EnvironmentName”。
Data.Filter.continuationToken target.resource.attribute.labels 作为键为“continuation_token”的标签添加。
Data.Filter.endTime target.resource.attribute.labels 添加为键为“filter_end_time”的标签。
Data.Filter.startTime target.resource.attribute.labels 添加为键为“filter_start_time”的标签。
Data.FinishTime additional.fields 作为附加字段添加,键为“FinishTime”。
Data.GroupId target.group.product_object_id 如果 Data.Updates.0.GroupId 不存在,则直接映射到 target.group.product_object_id。
Data.GroupName target.group.group_display_name 直接映射到 target.group.group_display_name。
Data.JobName additional.fields 作为附加字段添加,键为“JobName”。
Data.MemberId target.user.userid 如果 Data.Updates.0.MemberId 不存在,则直接映射到 target.user.userid。
Data.MemberDisplayName target.user.user_display_name 直接映射到 target.user.user_display_name。
Data.NamespaceId target.resource.product_object_id 如果 PipelineId、AuthorizationId 和 AgentId 不存在,则映射到 target.resource.product_object_id。
Data.NamespaceName target.resource.name 如果 PipelineName 不存在,则映射到 target.resource.name。
Data.ownerDetails additional.fields 作为附加字段添加,键为“OwnerDetails”。
Data.OwnerId additional.fields 作为附加字段添加,键为“OwnerId”。
Data.PipelineId target.resource.product_object_id 直接映射到 target.resource.product_object_id。
Data.PipelineName target.resource.name 直接映射到 target.resource.name。
Data.PipelineRevision target.resource.attribute.labels 添加为键为“PipelineRevision”的标签。
Data.PipelineScope target.resource.attribute.labels 添加为键为“PipelineScope”的标签。
Data.PlanType additional.fields 作为附加字段添加,键为“PlanType”。
Data.PreviousAccessLevel target.resource.attribute.labels 添加为键为“PreviousAccessLevel”的标签。
Data.PublisherName target.resource.attribute.labels 已添加为键为“PublisherName”的标签。
Data.Reason additional.fields 作为附加字段添加,键为“Reason”。
Data.ReleaseId additional.fields 作为附加字段添加,键为“ReleaseId”。
Data.ReleaseName additional.fields 作为附加字段添加,键为“ReleaseName”。
Data.RequesterId additional.fields 作为附加字段添加,键为“RequesterId”。
Data.RetentionLeaseId additional.fields 作为附加字段添加,键为“RetentionLeaseId”。
Data.RetentionOwnerId additional.fields 作为附加字段添加,键为“RetentionOwnerId”。
Data.RunName additional.fields 作为额外字段添加,键为“RunName”。
Data.Scopes target.resource.attribute.labels 添加为键为“Scope”的标签。
Data.StageName additional.fields 作为附加字段添加,键为“StageName”。
Data.StartTime additional.fields 作为附加字段添加,键为“StartTime”。
Data.TargetUser target.user.userid 直接映射到 target.user.userid。
Data.Timestamp metadata.event_timestamp 已解析并映射到 metadata.event_timestamp。
Data.TokenType target.resource.attribute.labels 作为键为“TokenType”的标签添加。
Data.Updates.0.GroupId target.group.product_object_id 直接映射到 target.group.product_object_id。
Data.Updates.0.MemberId target.user.userid 直接映射到 target.user.userid。
Data.ValidFrom target.resource.attribute.labels 添加为键为“ValidFrom”的标签。
Data.ValidTo target.resource.attribute.labels 已添加为键为“ValidTo”的标签。
DewPoint additional.fields 作为附加字段添加,键为“DewPoint”。
Details metadata.description 直接映射到 metadata.description。
Humidity additional.fields 作为附加字段添加,键为“Humidity”。
Icon additional.fields 作为附加字段添加,键为“Icon”。
Id metadata.product_log_id 直接映射到 metadata.product_log_id。
IpAddress principal.ip 直接映射到 principal.ip。
MoonPhase additional.fields 添加为键为“MoonPhase”的额外字段。
Moonrise additional.fields 已添加为键为“Moonrise”的附加字段。
Moonset additional.fields 已添加为键为“Moonset”的额外字段。
OperationName metadata.product_event_type 直接映射到 metadata.product_event_type。
Precipitation additional.fields 作为额外字段添加,键为“Precipitation”。
Pressure additional.fields 作为附加字段添加,键为“Pressure”。
ProjectId target.resource_ancestors.product_object_id 当祖先实体类型为 CLOUD_PROJECT 时,用于填充 target.resource_ancestors 中的 product_object_id 字段。
ProjectName target.resource_ancestors.name,target.resource.attribute.labels 当祖先实体类型为 CLOUD_PROJECT 时,用于填充 target.resource_ancestors 中的 name 字段。还作为标签添加到 target.resource.attribute.labels,键为“ProjectName”。
RoleLocation target.location.name 直接映射到 target.location.name。
ScopeDisplayName target.resource_ancestors.name 当祖先实体类型为 CLOUD_ORGANIZATION 时,用于填充 target.resource_ancestors 中的 name 字段。
ScopeId target.resource_ancestors.product_object_id 当祖先实体类型为 CLOUD_ORGANIZATION 时,用于填充 target.resource_ancestors 中的 product_object_id 字段。
ScopeType additional.fields 作为附加字段添加,键为“ScopeType”。
Sunrise additional.fields 作为附加字段添加,键为“Sunrise”。
Sunset additional.fields 已添加为键为“Sunset”的附加字段。
Temperature additional.fields 作为附加字段添加,键为“Temperature”。
TenantId metadata.product_deployment_id,additional.fields 直接映射到 metadata.product_deployment_id。还添加为键为“TenantId”的额外字段。
TimeGenerated metadata.event_timestamp 已解析并映射到 metadata.event_timestamp。
UserAgent network.http.user_agent,network.http.parsed_user_agent 直接映射到 network.http.user_agent。也会被解析并映射到 network.http.parsed_user_agent。
UVIndex additional.fields 作为附加字段添加,键为“UVIndex”。
Visibility additional.fields 作为附加字段添加,键为“Visibility”。
WindDirection additional.fields 作为附加字段添加,键为“WindDirection”。
WindSpeed additional.fields 作为附加字段添加,键为“WindSpeed”。
_Internal_WorkspaceResourceId additional.fields 作为附加字段添加,键为“workspace_resource_id”。
不适用 metadata.event_type 由基于 OperationName 和其他字段的逻辑确定。如果未匹配到特定事件类型,则默认为“GENERIC_EVENT”。可能的值包括“STATUS_SHUTDOWN”“RESOURCE_CREATION”“STATUS_UPDATE”“USER_RESOURCE_DELETION”“RESOURCE_READ”“RESOURCE_WRITTEN”“RESOURCE_DELETION”和“GROUP_MODIFICATION”。
不适用 metadata.vendor_name 设置为“Microsoft”。
不适用 metadata.product_name 设置为“Azure DevOps”。
不适用 metadata.log_type 设置为“AZURE_DEVOPS”。
不适用 principal.user.account_type 如果 AuthenticationMechanism 包含“ServicePrincipal”,则设置为“SERVICE_ACCOUNT_TYPE”,否则设置为“CLOUD_ACCOUNT_TYPE”。
不适用 target.asset.attribute.cloud.environment 设置为 MICROSOFT_AZURE。
不适用 security_result.action 对于成功的操作(成功、已创建、已修改、已执行、已更新、已移除),设置为“ALLOW”;对于失败的操作(失败、超时),设置为“BLOCK”。
不适用 extensions.auth.mechanism 如果 summary 为“UserAuthToken”,则设置为“USERNAME_PASSWORD”。
不适用 target.resource.resource_type 如果存在 pipeline_id,则设置为“SETTING”;如果存在 authorization_id,则设置为“CREDENTIAL”;如果存在 agent_id,则设置为“DEVICE”;如果存在 namespace_id,则设置为“DATABASE”。否则,在某些情况下,系统会根据 operationName 将其设置为“STORAGE_BUCKET”。
不适用 target.resource.resource_subtype 如果存在 pipeline_id,则设置为“Pipeline”;如果存在 authorization_id,则设置为“Token”;如果存在 agent_id,则设置为“Agent”;如果存在 namespace_id,则设置为“Namespace”。

更新日志

查看此解析器的更新日志

需要更多帮助?获得社区成员和 Google SecOps 专业人士的解答。