收集 Azure DevOps 审核日志
支持的语言:
Google SecOps
SIEM
概览
此解析器可处理 JSON 格式的 Azure DevOps 审核日志。它从嵌套和顶级 JSON 结构中提取字段,并将它们映射到 UDM。基于特定字段值的条件逻辑可对事件进行分类,并使用相关的安全信息丰富输出内容。解析器还会尝试使用 grok 模式提取 JSON 载荷,从而处理非 JSON 格式的消息。
准备工作
确保您满足以下前提条件:
- Google SecOps 实例
- 有效的 Azure DevOps 组织
- 对 Azure DevOps 组织和 Azure 的特权访问权限
设置 Feed
您可以通过两种不同的入口点在 Google SecOps 平台中设置 Feed:
- SIEM 设置 > Feed
- 内容中心 > 内容包
通过“SIEM 设置”>“Feed”设置 Feed
如需为相应产品系列中的不同日志类型配置多个 Feed,请参阅按产品配置 Feed。
如需配置单个 Feed,请按以下步骤操作:
- 依次前往 SIEM 设置> Feed。
- 点击添加新 Feed。
- 在下一页上,点击配置单个 Feed。
- 在 Feed 名称字段中,输入 Feed 的名称(例如 Azure Devops 日志)。
- 选择 Webhook 作为来源类型。
- 选择 Azure DevOps 审核作为日志类型。
- 点击下一步。
- 可选:为以下输入参数指定值:
- 拆分分隔符:用于分隔日志行的分隔符,例如
\n
。 - 资源命名空间:资源命名空间。
- 注入标签:应用于此 Feed 中事件的标签。
- 拆分分隔符:用于分隔日志行的分隔符,例如
- 点击下一步。
- 在最终确定界面中检查 Feed 配置,然后点击提交。
- 点击生成密钥,生成用于对此 Feed 进行身份验证的密钥。
- 复制并存储密钥。您将无法再次查看此密钥。如有需要,您可以重新生成新的 Secret 密钥,但此操作会使之前的 Secret 密钥失效。
- 在详情标签页中,从端点信息字段复制 Feed 端点网址。您需要在客户端应用中指定此端点网址。
- 点击完成。
设置来自内容中心的 Feed
为以下字段指定值:
- 拆分分隔符:用于分隔日志行的分隔符,例如
\n
。
高级选项
- Feed 名称:用于标识 Feed 的预填充值。
- 来源类型:用于将日志收集到 Google SecOps 中的方法。
- 资源命名空间:资源命名空间。
- 注入标签:应用于此 Feed 中事件的标签。
- 点击下一步。
- 在最终确定界面中检查 Feed 配置,然后点击提交。
- 点击生成密钥,生成用于对此 Feed 进行身份验证的密钥。
为 Webhook 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}
)。 - 选择齿轮图标,打开组织设置。
- 选择审核。
- 前往数据流标签页,然后依次选择新数据流 > Event Grid。
- 输入在 Azure 中配置事件网格主题中创建的主题端点和访问密钥。
在 Azure DevOps 中为 Google SecOps 配置 Webhook
- 在 Azure 门户中,搜索并访问 Event Grid。
- 选择之前创建的主题。
- 前往实体 > 事件订阅。
- 点击 + 事件订阅。
- 提供一个描述性名称(例如,*
Google SecOps Integration
)。 - 选择 Web Hook,然后点击配置端点。
- 配置端点:
- 订阅者端点:输入 Google SecOps API 端点网址。
- 在 HTTP 标头部分中,添加以下标头:
- 标题 1:
- 键:
X-goog-api-key
- 值:您在为 Webhook Feed 创建 API 密钥部分中创建的 API 密钥。
- 键:
- 标题 2:
- 键:
X-Webhook-Access-Key
- 值:您在在 Google SecOps 中配置 Feed 以注入 Azure DevOps 日志部分中生成的密钥。
- 键:
- 标题 1:
- 将 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 Service”,则直接从 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 |
添加为键为“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 |
添加为键为“湿度”的附加字段。 |
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 |
添加为键为“日出”的附加字段。 |
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 ,则设置为“流水线”;如果存在 authorization_id ,则设置为“令牌”;如果存在 agent_id ,则设置为“代理”;如果存在 namespace_id ,则设置为“命名空间”。 |
需要更多帮助?从社区成员和 Google SecOps 专业人士那里获得解答。