收集 GitLab 日志
支持的平台:
Google SecOps
SIEM
概览
此解析器会从 GitLab JSON 日志中提取字段,将其标准化为统一数据模型 (UDM),并使用其他上下文丰富数据。它会处理各种 GitLab 事件类型,重点关注用户操作、资源访问和安全结果,同时还会处理网络和应用相关信息。该解析器还会根据 GitLab 中的角色和操作执行逻辑,对事件进行分类并分配适当的严重程度。
准备工作
- 确保您拥有 Google SecOps 实例。
- 确保您拥有对 GitLab 的超级用户访问权限。
在 Google SecOps 中配置 Feed 以提取 GitLab 日志
- 依次前往 SIEM 设置 > Feed。
- 点击新增。
- 在Feed 名称字段中,输入 Feed 的名称(例如 GitLab 日志)。
- 选择Webhook 作为来源类型。
- 选择 Gitlab 作为日志类型。
- 点击下一步。
- 可选:为以下输入参数指定值:
- 分隔符:用于分隔日志行的分隔符,例如
\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 进行身份验证而生成的密钥。
在 GitLab 中为 Google SecOps 配置 webhook
- 打开网络浏览器,然后前往您要为其配置 webhook 的 GitLab 项目。
- 在您的项目中,依次前往设置 > Webhook。
- 点击添加新的 Webhook。
- 在 网址 字段中,粘贴 Google SecOps 端点网址。
- 点击添加自定义标头。
- 在标头名称字段中输入 X-Webhook-Access-Key。
- 对于 Header Value(标头值)字段,请复制在配置 Google SecOps Feed 期间生成的 Secret Key。
- 点击添加自定义标头。
- 在“标头名称”字段中输入 X-goog-api-key。
- 对于 Header Value 字段,请复制在 Google SecOps Feed 配置期间生成的 API 密钥。 注意:为增强安全性,请生成一个 Secret 令牌,并将其添加到 GitLab Webhook 配置和相应的 Google SecOps Feed 配置中。这有助于验证传入的 webhook 的真实性。
- 选择应触发该 webhook 的 GitLab 事件。例如,您可以选择推送事件,以便在每次有代码推送到代码库时将数据发送到 Google SecOps。仔细考虑哪些事件与您的安全监控需求相关。事件过多可能会导致不必要的加载。
- 为更好地了解该 webhook 的用途,请为其指定一个有意义的名称,例如 Google SecOps Webhook。
- 确保选中 Enable SSL verification(启用 SSL 验证)复选框。这对于安全通信至关重要。
- 点击添加网络钩子以保存您的配置。
UDM 映射表
日志字段 | UDM 映射 | 逻辑 |
---|---|---|
author_id |
principal.user.userid |
已转换为字符串。 |
author_name |
principal.user.email_addresses |
如果值与电子邮件地址正则表达式匹配。 |
author_name |
principal.user.user_display_name |
如果值与电子邮件地址正则表达式不匹配。 |
details.as |
principal.resource.attribute.labels |
已添加为键为“as”的标签。 |
details.add |
principal.resource.attribute.labels |
添加为键为“add”的标签。 |
details.as |
principal.user.role_name |
原始日志字段值。 |
details.as |
principal.user.attribute.roles.type |
如果 details.as 为“Owner”(所有者),则设置为“ADMINISTRATOR”(管理员);如果 details.as 为“Developer”(开发者)“Maintainer”(维护者)或“Reporter”(报告者),则设置为“SERVICE_ACCOUNT”(服务账号);如果 details.as 为“Guest”(访客),则设置为“TYPE_UNSPECIFIED”(未指定类型)。 |
details.custom_message |
security_result.description |
原始日志字段值。 |
details.custom_message.action |
security_result.summary |
原始日志字段值。 |
details.entity_path |
target.file.full_path |
原始日志字段值。 |
details.target_id |
target.resource.id |
已转换为字符串。 |
entity_path |
target.file.full_path |
原始日志字段值。 |
entity_type |
target.resource.attribute.labels |
已添加为键为“Entity Type”(实体类型)的标签。 |
event_type |
metadata.product_event_type |
原始日志字段值。 |
insertId |
metadata.product_log_id |
原始日志字段值。 |
ip_address |
principal.ip ,principal.asset.ip |
原始日志字段值。 |
jsonPayload.action |
additional.fields |
作为键为“action”且值为字符串的字段添加。 |
jsonPayload.controller |
additional.fields |
作为键为“controller”且值为字符串的字段添加。 |
jsonPayload.correlation_id |
principal.asset_id |
带有“id:”前缀。 |
jsonPayload.cpu_s |
additional.fields |
作为键为“cpu_s”且值为字符串的字段添加。 |
jsonPayload.details.custom_message.protocol |
network.application_protocol |
如果值为“web”,则设置为“UNKNOWN_APPLICATION_PROTOCOL”,否则转换为大写。此外,如果值为“web”,还会添加一个键为“Application Protocol”的附加字段。 |
jsonPayload.mem_total_bytes |
additional.fields |
作为键为“mem_total_bytes”且值为字符串的字段添加。 |
jsonPayload.meta_caller_id |
additional.fields |
作为键为“Caller Id”且值为字符串的字段添加。 |
jsonPayload.meta_client_id |
target.user.userid |
原始日志字段值。 |
jsonPayload.meta_feature_category |
additional.fields |
作为键为“Feature Category”(地图项类别)且值为字符串的字段添加。 |
jsonPayload.meta_remote_ip |
principal.ip ,principal.asset.ip |
原始日志字段值,会解析为 JSON 数组并合并到 IP 字段中。 |
jsonPayload.meta_user |
principal.user.userid |
如果 jsonPayload.username 为空,则用作后备方案。 |
jsonPayload.method |
network.http.method |
原始日志字段值。 |
jsonPayload.path |
target.process.file.full_path |
原始日志字段值。 |
jsonPayload.pid |
target.process.pid |
已转换为字符串。 |
jsonPayload.remote_ip |
principal.ip ,principal.asset.ip |
原始日志字段值。 |
jsonPayload.request_urgency |
additional.fields |
已添加为键为“Request Urgency”且值为字符串的字段。 |
jsonPayload.severity |
security_result.severity |
如果值为“INFO”,则设置为“INFORMATIONAL”;如果值为“ERROR”,则设置为“ERROR”;如果值为“NOTICE”,则设置为“MEDIUM”。 |
jsonPayload.status |
network.http.response_code |
如果不是“有效”,则转换为整数。 |
jsonPayload.ua |
network.http.user_agent |
原始日志字段值。 |
jsonPayload.username |
principal.user.userid |
原始日志字段值。 |
jsonPayload.worker_id |
principal.application |
原始日志字段值。 |
labels.instance_name |
principal.hostname ,principal.asset.hostname |
原始日志字段值,如果消息包含“正在移除用户”,则使用此值。 |
logName |
security_result.category_details |
原始日志字段值。 |
message |
security_result.summary |
原始日志字段值,如果 jsonPayload.severity 为“ERROR”,则使用此值。 |
protoPayload.@type |
additional.fields |
作为键为“protoPayload type”且值为字符串的字段添加。 |
protoPayload.authenticationInfo.principalEmail |
principal.user.email_addresses ,principal.user.userid |
原始日志字段值。 |
protoPayload.authenticationInfo.principalSubject |
additional.fields |
作为键为“authenticationInfo principalSubject”且值为字符串的字段添加。 |
protoPayload.authenticationInfo.serviceAccountKeyName |
additional.fields |
作为键为“authenticationInfo serviceAccountKeyName”且值为字符串的字段添加。 |
protoPayload.authorizationInfo |
target.resource.attribute.labels ,security_result.action |
此字段中的值会添加为标签,键以“authenticationInfo”开头。如果 granted 中的值为 true,则将 security_result.action 设置为“允许”;如果为 false,则将其设置为“屏蔽”。resourceAttributes 等嵌套字段也会作为标签添加,其键的前缀为“authenticationInfo_resourceAttributes”。 |
protoPayload.methodName |
additional.fields |
作为键为“protoPayload methodName”且值为字符串的字段添加。 |
protoPayload.request.@type |
additional.fields |
以键“Request Type”和字符串值的形式添加为字段。 |
protoPayload.request.resource |
target.resource.attribute.labels |
已添加为键为“Request resource”(请求资源)的标签。 |
protoPayload.requestMetadata.callerIp |
additional.fields |
作为键为“requestMetadata callerIp”且值为字符串的字段添加。 |
protoPayload.requestMetadata.callerSuppliedUserAgent |
additional.fields |
作为键为“requestMetadata callerSuppliedUserAgent”且值为字符串的字段添加。 |
protoPayload.serviceName |
additional.fields |
已添加为键为“serviceName”且值为字符串的字段。 |
protoPayload.status.code |
additional.fields |
作为键为“protoPayload status code”且值为字符串的字段添加。 |
protoPayload.status.message |
additional.fields 、target.user.email_addresses 、target.user.userid |
作为键为“protoPayload status message”且值为字符串的字段添加。如果可以从消息中提取电子邮件地址,系统会将其添加到 target.user.email_addresses 和 target.user.userid 。 |
receiveTimestamp |
metadata.event_timestamp ,timestamp |
解析为事件时间戳。 |
resource.labels.project_id |
target.resource.attribute.labels |
已添加为键为“Project id”的标签。 |
resource.labels.zone |
target.cloud.availability_zone |
原始日志字段值。 |
resource.type |
target.cloud.environment |
如果值与“gce”匹配,则设置为“GOOGLE_CLOUD_PLATFORM”。 |
security_result.action |
security_result.action |
派生自 protoPayload.authorizationInfo.granted 。 |
security_result.category_details |
security_result.category_details |
已与 logName 合并。 |
security_result.description |
security_result.description |
派生自 jsonPayload.details.custom_message 。 |
security_result.severity |
security_result.severity |
派生自 severity 或 jsonPayload.severity 。 |
security_result.summary |
security_result.summary |
派生自 jsonPayload.details.custom_message.action 或 jsonPayload.message 。 |
severity |
security_result.severity |
如果值为“INFO”,则设置为“INFORMATIONAL”;如果值为“ERROR”,则设置为“ERROR”;如果值为“NOTICE”,则设置为“MEDIUM”。 |
sourceLocation |
principal.resource.attribute.labels |
此字段中的值会添加为标签。 |
target_details |
target.resource.attribute.labels |
已添加为键为“Target Details”的标签。 |
target_type |
target.resource.attribute.labels |
已添加为键为“target type”的标签。 |
timestamp |
timestamp |
原始日志字段值。根据是否存在 principal 和 target 字段进行设置。如果未满足任何特定条件,则默认为“GENERIC_EVENT”。可能的值包括“USER_RESOURCE_UPDATE_CONTENT”“USER_RESOURCE_ACCESS”“USER_UNCATEGORIZED”。设置为“GITLAB”。设置为“GITLAB”。 |
变化
2024-04-08
- 将“custom_message.action”映射到“security_result.summary”。
- 将“ip_address”映射到“principal.ip”。
- 将“applicationProtocol”映射到“network.application_protocol”。
- 将“details.author_name”映射到“principal.user.email_addresses”
- 将“author_id”映射到“principal.user.userid”。
- 将“target_id”映射到“target.resource.id”。
- 将“details.entity_path”映射到“target.file.full_path”。
- 将“event_type”映射到“product_event_type”。
- 将“target_type”“entity_type”和“target_details”映射到“resource.attribute.labels”。
2023-10-20
- 将以“db_”开头的字段映射到了“additional_fields”。
- 将以“redis_”开头的字段映射到了“additional_fields”。
- 将“severity”或“jsonPayload.severity”映射到“security_result.severity”,前提是值为“ERROR”或“NOTICE”。
- 将“jsonPayload.correlation_id”映射到“principal.asset_id”。
- 将“jsonPayload 的未映射字段”映射到“additional_fields”。
- 将“jsonPayload.worker_id”映射到“principal.application”。
- 将“jsonPayload.method”映射到“network.http.method”。
- 将“jsonPayload.pid”映射到“target.process.pid”。
- 将“jsonPayload.status”映射到“network.http.response_code”。
- 将“resource.labels.zone”映射到“target.cloud.availability_zone”。
- 将“resource.type”映射到“target.cloud.environment”。
- 将“jsonPayload.meta_user”映射到“target.user.userid”。
- 将“jsonPayload.username”映射到“principal.user.userid”。
- 将“jsonPayload.remote_ip”映射到“principal.ip”。
- 将“jsonPayload.ua”映射到“network.http.user_agent”。
- 将“jsonPayload.meta_client_id”映射到“target.user.userid”。
- 将“jsonPayload.path”映射到“target.process.file.full_path”。
- 将“protoPayload.authenticationInfo.principalEmail”映射到“principal.user.email_addresses”。
- 将“protoPayload”中的其他字段映射到“additional.fields”。
- 在映射“metadata.event_type”之前,提供了一个条件检查,以确保存在所需的映射。
2023-10-10
- 将“jsonPayload.details.as”映射到“principal.resource.attribute.labels”和“principal.user.role_name”。
- 对于“jsonPayload.details.as”等于“Owner”的日志,将“principal_role.type”设置为“ADMINISTRATOR”。
- 对于将“jsonPayload.details.as”设置为“开发者”“维护者”或“报告者”的日志,将“principal_role.type”设置为“SERVICE_ACCOUNT”。
- 对于“jsonPayload.details.as”等于“Guest”的日志,将“principal_role.type”设置为“TYPE_UNSPECIFIED”。
- 将“jsonPayload.details.add”映射到“principal.resource.attribute.labels”。
- 将“jsonPayload.entity_type”映射到“target.resource.attribute.labels”。
2023-08-31
- 新创建的解析器。
需要更多帮助?向社区成员和 Google SecOps 专业人士寻求解答。