收集 Azure DevOps 审核日志
支持的平台:
Google SecOps
SIEM
概览
此解析器处理采用 JSON 格式的 Azure DevOps 审核日志。它会从嵌套和顶级 JSON 结构中提取字段,并将其映射到 UDM。基于特定字段值的条件逻辑会对事件进行分类,并使用相关安全信息丰富输出。解析器还会尝试使用 Grok 模式提取 JSON 载荷,以处理非 JSON 格式的消息。
准备工作
- 确保您拥有 Google SecOps 实例。
- 确保您拥有有效的 Azure DevOps 组织。
- 确保您拥有对 Azure DevOps 组织和 Azure 的特权访问权限。
在 Google SecOps 中配置 Feed 以注入 Azure DevOps 日志
- 依次前往 SIEM 设置 > Feed。
- 点击新增。
- 在Feed 名称字段中,输入 Feed 的名称(例如 Azure DevOps 日志)。
- 选择Webhook 作为来源类型。
- 选择 Azure DevOps 作为日志类型。
- 点击下一步。
- 可选:为以下输入参数指定值:
- 分隔符:用于分隔日志行(例如
\n
)的分隔符。 - 资源命名空间:资源命名空间。
- 提取标签:应用于此 Feed 中的事件的标签。
- 分隔符:用于分隔日志行(例如
- 点击下一步。
- 在最终确定界面中查看 Feed 配置,然后点击提交。
- 点击生成 Secret 密钥,生成用于对此 Feed 进行身份验证的 Secret 密钥。
- 复制并存储密钥。您将无法再查看此密钥。如有必要,您可以重新生成新的 Secret 密钥,但此操作会使之前的 Secret 密钥过时。
- 在详情标签页中,从端点信息字段复制 Feed 端点网址。您需要在客户端应用中指定此端点网址。
- 点击完成。
为该网站钩子 Feed 创建 API 密钥
依次前往 Google Cloud 控制台 > 凭据。
点击创建凭据,然后选择 API 密钥。
限制 API 密钥对 Google Security Operations API 的访问权限。
指定端点网址
- 在客户端应用中,指定 webhook Feed 中提供的 HTTPS 端点网址。
通过在自定义标头中指定 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 中配置审核功能
- 登录您的组织 (
https://dev.azure.com/{yourorganization}
)。 - 选择组织设置对应的齿轮图标。
- 在安全下,选择政策。
- 将记录审核事件按钮切换为开启。
在 Azure 中配置 Event Grid 主题
- 登录 Azure 门户。
- 搜索并访问 Event Grid。
- 在自定义事件下,找到主题。
- 点击 + 创建。
- 选择您的订阅和资源组。提供名称(例如 DevopsAuditLog),然后选择区域。点击检查并创建。
- 访问新的主题,然后复制主题端点网址。
- 依次前往设置 > 访问密钥,然后复制密钥 1。
将 Azure DevOps 日志流配置为 Event Grid
- 登录您的组织 (
https://dev.azure.com/{yourorganization}
)。 - 选择组织设置对应的齿轮图标。
- 选择审核。
- 前往数据流标签页,然后依次选择新建数据流 > 事件网格。
- 输入在在 Azure 中配置 Event Grid 主题中创建的主题端点和访问密钥。
在 Azure DevOps 中为 Google SecOps 配置 Webhook
- 在 Azure 门户中,搜索并访问 Event Grid。
- 选择之前创建的主题。
- 依次前往实体 > 事件订阅。
- 点击 + 事件订阅。
- 提供一个描述性名称(例如 Google SecOps 集成)。
- 选择网站钩子,然后点击配置端点。
- 配置端点:
- 订阅方端点:输入 Google SecOps API 端点网址。
- 将
?key=<API_KEY>&secret=<SECRET_KEY>
附加到该载荷网址。 - 将 Content-Type 标头设置为 application/json。
- 点击创建。
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 |
如果不是“Azure DevOps 服务”,则直接从 ActorDisplayName 字段映射。如果是“Azure DevOps 服务”,则会作为标签添加到 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 |
已添加为键为“条件”的附加字段。 |
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 |
已添加为键为“范围”的标签。 |
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 |
如果操作成功(已成功、已创建、已修改、已执行、已更新、已移除),请将其设为“允许”;如果操作失败(已失败、超时),请将其设为“屏蔽”。 |
不适用 | 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 ,则设置为“命名空间”。 |
变化
2024-01-19
- 如果存在主要用户数据和目标资源数据,则将“metadata.eventtype”值从“SERVICE*”更改为“USER_RESOURCE_UPDATE_CONTENT”。
- 将“IpAddress”的映射从“target.ip”更改为“principal.ip”。
- 将“ActorCUID”的映射从“principal.user.product_object_id”更改为“additional.fields”。
- 将“ScopeId”的映射从“principal.asset_id”更改为“resource_ancestors.product_object_id”。
- 将“_Internal_WorkspaceResourceId”的映射从“target.resource.product_object_id”更改为“additional.fields”。
- 将“ProjectId”的映射从“target.resource.attribute.labels”更改为“target.resource_ancestors.product_object_id”。
- 将“AuthenticationMechanism”的映射从“security_result.summary”更改为“extensions.auth.auth_details”。
- 将“CorrelationId”的映射从“network.session_id”更改为“additional.fields”。
- 将“ScopeDisplayName”的映射从“additional.fields”更改为“target.resource_ancestors.name”。
- 将“PipelineId”的映射从“additional.fields”更改为“target.resource.product_object_id”。
- 将“PipelineName”的映射从“additional.fields”更改为“target.resource.name”。
- 将“PipelineScope”的映射从“additional.fields”更改为“target.resource.attribute.labels”。
- 将“PipelineRevision”的映射从“additional.fields”更改为“target.resource.attribute.labels”。
- 将“ProjectId”的映射从“target.resource.resource.attribute.labels”更改为“target.resource_ancestors.product_object_id”。
- 将“区域”的映射从“additional.fields”更改为“target.application”。
- 将“MICROSOFT_AZURE”值映射到“target.asset.attribute.cloud.environment”。
- 如果“AuthenticationMechanism”的值为“ServicePrincipal”,请将“SERVICE_ACCOUNT_TYPE”设置为“principal.user.account_type”,否则将“CLOUD_ACCOUNT_TYPE”设置为“principal.user.account_type”。
- 将“Category”映射到“security_result.action_details”。
- 根据“详细信息”字段将“允许”或“屏蔽”映射到“security_result.action”。
- 将“activityId”映射到“additional.fields”。
2024-01-09
- 添加了 Grok 和 gsub 来解析未解析的 JSON 日志。
- 已将“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”映射到“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”。
- 将“level”映射到“security_result.severity”。
- 将“appname”映射到“target.application”。
- 将“category.details”映射到“security.result.category.details”。
- 将“rec.resourceId”映射到“target.resource.id”。
- 将“res.extensionResourceName”映射到“principal.hostname”。
2023-11-23
- 添加了对 JSON 日志的新模式的支持。
- 将“data.TimeGenerated”映射到“metadata.event_timestamp”。
- 如果缺少“_Internal_WorkspaceResourceId”,则将“topic”映射到“target.resource.product_object_id”。
- 将“data.Data.ConnectionId”映射到“additional.fields”。
- 将“data.Data.ownerDetails”映射到“additional.fields”。
- 将“data.Data.DeploymentResult”映射到“additional.fields”。
- 将“data.Data.EnvironmentName”映射到“additional.fields”。
- 将“data.Data.JobName”映射到“additional.fields”。
- 将“data.Data.StageName”映射到“additional.fields”。
- 将“data.Data.RunName”映射到“additional.fields”。
- 将“data.Data.RetentionLeaseId”映射到“additional.fields”。
- 将“data.Data.CheckSuiteId”映射到“additional.fields”。
- 将“data.Data.CheckSuiteStatus”映射到“additional.fields”。
- 将“data.Data.ApprovalRequest”映射到“additional.fields”。
- 将“data.Data.ApprovalType”映射到“additional.fields”。
- 将“subject”映射到“additional.fields”。
- 将“data.ActorUserId”映射到“principal.user.userid”。
- 将“data.ActorDisplayName”映射到“principal.user.user_display_name”。
- 将“data.ActorCUID”映射到“principal.user.product_object_id”。
- 将“data.ActorUPN”映射到“principal.user.email_addresses”。
- 将“data.ScopeId”映射到“principal.asset_id”。
- 将“data.CorrelationId”映射到“network.session_id”。
- 将“data.UserAgent”映射到“network.http.user_agent”。
- 将“data.ProjectId”映射到“target.resource.attribute.labels”。
- 将“data.ScopeType”映射到“additional.fields”。
- 将“data.ProjectName”映射到“target.resource.attribute.labels”。
- 将“data.Details”映射到“metadata.description”。
- 将“data.CategoryDisplayName”映射到“security_result.rule_name”。
- 将“data.Area”映射到“additional.fields”。
- 将“data.Id”映射到“metadata.product_log_id”。
- 将“data.ActionId”映射到“metadata.product_event_type”。
- 将“data.Timestamp”映射到“metadata.event_timestamp”。
2022-06-28
- 新创建的解析器