收集 Azure DevOps 审核日志

解析器版本:3.0

支持的平台:

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

准备工作

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

  • Google SecOps 实例
  • 有效的 Azure DevOps 组织
  • 对 Azure DevOps 组织和 Azure 的特权访问权限

设置 Feed

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

  • SIEM 设置 > Feed > 添加新 Feed
  • 内容中心 > 内容包 > 开始

如何设置 Azure DevOps 审核 Feed

  1. 点击 Azure 平台包。
  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 中配置 Event Grid 主题

  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 中配置事件网格主题中创建的主题端点和访问密钥。

在 Azure DevOps 中为 Google SecOps 配置 Webhook

  1. 在 Azure 门户中,搜索并访问 Event Grid。
  2. 选择之前创建的主题。
  3. 前往实体 > 事件订阅。
  4. 点击 + 事件订阅。
  5. 提供描述性名称(例如 *Google SecOps Integration)。
  6. 选择 Web Hook,然后点击配置端点。
  7. 配置端点:
    1. 订阅者端点:输入 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"
    }
    
  • Event Grid 封装的 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 以键为“降水”的附加字段形式添加。
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 添加为键为“日出”的附加字段。
Sunset additional.fields 添加为键为“Sunset”的附加字段。
Temperature additional.fields 添加为键为“温度”的附加字段。
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,则设置为“流水线”;如果存在 authorization_id,则设置为“令牌”;如果存在 agent_id,则设置为“代理”;如果存在 namespace_id,则设置为“命名空间”。

更新日志

查看此解析器的更新日志

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