收集 Slack 审核日志
支持的平台:
Google SecOps
SIEM
本文档介绍了如何使用 Google Cloud Run functions 将 Slack 审核日志注入到 Google Security Operations。解析器可处理两种格式的 Slack 审核日志。它首先会对布尔值进行归一化处理,然后清除预定义的字段。然后,它将“message”字段解析为 JSON,并通过舍弃非 JSON 消息来处理这些消息。解析器会根据特定字段(date_create 和 user_id)是否存在应用不同的逻辑来将原始日志字段映射到 UDM,包括元数据、正文、网络、目标和相关信息,并构建安全结果。
准备工作
请确保满足以下前提条件:
- Google SecOps 实例
- 对 Slack Enterprise Grid 租户和管理控制台的特权访问权限
- 对 GCP Cloud Run functions 和 Cloud Scheduler 的特权访问权限
收集 Slack 审核日志的前提条件(应用 ID、OAuth 令牌、组织 ID)
- 登录 Enterprise Grid 组织的 Slack 管理控制台。
- 前往 https://api.slack.com/apps,然后依次点击创建新应用 > 从头开始。
- 输入应用名称,然后选择您的开发 Slack 工作区。
- 点击创建应用。
- 在左侧边栏中,前往 OAuth 和权限。
- 前往范围部分,然后添加以下用户令牌范围:
- auditlogs:read
- 依次点击安装到 Workspace > 允许。
- 安装完成后,依次前往组织级应用 > 安装到组织。
- 使用组织所有者/管理员账号授权该应用。
- 复制并安全地保存以
xoxp-开头的用户 OAuth 令牌(这是您的 SLACK_ADMIN_TOKEN)。 - 复制您的组织 ID,该 ID 可在 Slack 管理控制台中的设置和权限 > 组织设置下找到。
设置目录
- 在本地机器上创建一个新目录,用于部署 Cloud Run 函数。
- 从 Chronicle 提取脚本 GitHub 代码库下载以下文件:
- 从 slack 文件夹中下载:
.env.ymlmain.pyrequirements.txt
- 从代码库的根目录中,下载整个 common 目录及其所有文件:
common/__init__.pycommon/auth.pycommon/env_constants.pycommon/ingest.pycommon/status.pycommon/utils.py
- 从 slack 文件夹中下载:
- 将所有下载的文件放入部署目录。
您的目录结构应如下所示:
deployment_directory/
├─common/
│ ├─__init__.py
│ ├─auth.py
│ ├─env_constants.py
│ ├─ingest.py
│ ├─status.py
│ └─utils.py
├─.env.yml
├─main.py
└─requirements.txt
在 Google Secret Manager 中创建 Secret
- 在 Google Cloud 控制台中,依次前往安全性 > Secret Manager。
- 点击创建 Secret。
- 为 Chronicle 服务账号提供以下配置详细信息:
- 名称:输入
chronicle-service-account。 - 密钥值:粘贴您的 Google SecOps 提取身份验证 JSON 文件的内容。
- 名称:输入
- 点击创建密钥。
复制密文资源名称,格式如下:
projects/<PROJECT_ID>/secrets/chronicle-service-account/versions/latest再次点击创建 Secret 以创建第二个 Secret。
为 Slack 令牌提供以下配置详细信息:
- 名称:输入
slack-admin-token。 - 密钥值:粘贴您的 Slack 用户 OAuth 令牌(以
xoxp-开头)。
- 名称:输入
点击创建密钥。
复制密文资源名称,格式如下:
projects/<PROJECT_ID>/secrets/slack-admin-token/versions/latest
设置所需的运行时环境变量
- 打开部署目录中的
.env.yml文件。 使用您的值配置环境变量:
CHRONICLE_CUSTOMER_ID: "<your-chronicle-customer-id>" CHRONICLE_REGION: us CHRONICLE_SERVICE_ACCOUNT: "projects/<PROJECT_ID>/secrets/chronicle-service-account/versions/latest" CHRONICLE_NAMESPACE: "" POLL_INTERVAL: "5" SLACK_ADMIN_TOKEN: "projects/<PROJECT_ID>/secrets/slack-admin-token/versions/latest"- 替换以下内容:
<your-chronicle-customer-id>:您的 Google SecOps 客户 ID。<PROJECT_ID>:您的 Google Cloud 项目 ID。- CHRONICLE_REGION:设置为您的 Google SecOps 区域。有效值:
us、asia-northeast1、asia-south1、asia-southeast1、australia-southeast1、europe、europe-west2、europe-west3、europe-west6、europe-west9、europe-west12、me-central1、me-central2、me-west1、northamerica-northeast2、southamerica-east1。 - POLL_INTERVAL:函数执行的频率间隔(以分钟为单位)。此时长必须与 Cloud Scheduler 作业间隔相同。
- 替换以下内容:
保存
.env.yml文件。
部署 Cloud Run 函数
- 在 Google Cloud 控制台中打开终端或 Cloud Shell。
导航到您的部署目录:
cd /path/to/deployment_directory执行以下命令以部署 Cloud Run 函数:
gcloud functions deploy slack-audit-to-chronicle \ --entry-point main \ --trigger-http \ --runtime python39 \ --env-vars-file .env.yml \ --timeout 300s \ --memory 512MB \ --service-account <SERVICE_ACCOUNT_EMAIL>- 将
<SERVICE_ACCOUNT_EMAIL>替换为您希望 Cloud Run 函数使用的服务账号的电子邮件地址。
- 将
等待部署完成。
部署完成后,请记下输出中的函数网址。
设置 Cloud Scheduler
- 在 Google Cloud 控制台中,依次前往 Cloud Scheduler > 创建作业。
- 提供以下配置详细信息:
- 名称:输入
slack-audit-scheduler。 - 区域:选择与您部署 Cloud Run 函数时所选的区域相同的区域。
- 频率:输入
*/5 * * * *(每 5 分钟运行一次,与POLL_INTERVAL值一致)。 - 时区:选择 UTC。
- 目标类型:选择 HTTP。
- 网址:输入部署输出中的 Cloud Run 函数网址。
- HTTP 方法:选择 POST。
- 身份验证标头:选择添加 OIDC 令牌。
- 服务账号:选择用于 Cloud Run 函数的同一服务账号。
- 名称:输入
- 点击创建。
UDM 映射表
| 日志字段 | UDM 映射 | 逻辑 |
|---|---|---|
action |
metadata.product_event_type |
直接从原始日志中的 action 字段映射。 |
actor.type |
principal.labels.value |
直接从 actor.type 字段映射,并添加了键 actor.type。 |
actor.user.email |
principal.user.email_addresses |
直接从 actor.user.email 字段映射。 |
actor.user.id |
principal.user.product_object_id |
直接从 actor.user.id 字段映射。 |
actor.user.id |
principal.user.userid |
直接从 actor.user.id 字段映射。 |
actor.user.name |
principal.user.user_display_name |
直接从 actor.user.name 字段映射。 |
actor.user.team |
principal.user.group_identifiers |
直接从 actor.user.team 字段映射。 |
context.ip_address |
principal.ip |
直接从 context.ip_address 字段映射。 |
context.location.domain |
about.resource.attribute.labels.value |
直接从 context.location.domain 字段映射,并添加了键 context.location.domain。 |
context.location.id |
about.resource.id |
直接从 context.location.id 字段映射。 |
context.location.name |
about.resource.name |
直接从 context.location.name 字段映射。 |
context.location.name |
about.resource.attribute.labels.value |
直接从 context.location.name 字段映射,并添加了键 context.location.name。 |
context.location.type |
about.resource.resource_subtype |
直接从 context.location.type 字段映射。 |
context.session_id |
network.session_id |
直接从 context.session_id 字段映射。 |
context.ua |
network.http.user_agent |
直接从 context.ua 字段映射。 |
context.ua |
network.http.parsed_user_agent |
使用 parseduseragent 过滤条件从 context.ua 字段派生的已解析的用户代理信息。 |
country |
principal.location.country_or_region |
直接从 country 字段映射。 |
date_create |
metadata.event_timestamp.seconds |
date_create 字段中的纪元时间戳会转换为时间戳对象。 |
details.inviter.email |
target.user.email_addresses |
直接从 details.inviter.email 字段映射。 |
details.inviter.id |
target.user.product_object_id |
直接从 details.inviter.id 字段映射。 |
details.inviter.name |
target.user.user_display_name |
直接从 details.inviter.name 字段映射。 |
details.inviter.team |
target.user.group_identifiers |
直接从 details.inviter.team 字段映射。 |
details.reason |
security_result.description |
直接从 details.reason 字段映射,如果是数组,则用英文逗号连接。 |
details.type |
about.resource.attribute.labels.value |
直接从 details.type 字段映射,并添加了键 details.type。 |
details.type |
security_result.summary |
直接从 details.type 字段映射。 |
entity.app.id |
target.resource.id |
直接从 entity.app.id 字段映射。 |
entity.app.name |
target.resource.name |
直接从 entity.app.name 字段映射。 |
entity.channel.id |
target.resource.id |
直接从 entity.channel.id 字段映射。 |
entity.channel.name |
target.resource.name |
直接从 entity.channel.name 字段映射。 |
entity.channel.privacy |
target.resource.attribute.labels.value |
直接从 entity.channel.privacy 字段映射,并添加了键 entity.channel.privacy。 |
entity.file.filetype |
target.resource.attribute.labels.value |
直接从 entity.file.filetype 字段映射,并添加了键 entity.file.filetype。 |
entity.file.id |
target.resource.id |
直接从 entity.file.id 字段映射。 |
entity.file.name |
target.resource.name |
直接从 entity.file.name 字段映射。 |
entity.file.title |
target.resource.attribute.labels.value |
直接从 entity.file.title 字段映射,并添加了键 entity.file.title。 |
entity.huddle.date_end |
about.resource.attribute.labels.value |
直接从 entity.huddle.date_end 字段映射,并添加了键 entity.huddle.date_end。 |
entity.huddle.date_start |
about.resource.attribute.labels.value |
直接从 entity.huddle.date_start 字段映射,并添加了键 entity.huddle.date_start。 |
entity.huddle.id |
about.resource.attribute.labels.value |
直接从 entity.huddle.id 字段映射,并添加了键 entity.huddle.id。 |
entity.huddle.participants.0 |
about.resource.attribute.labels.value |
直接从 entity.huddle.participants.0 字段映射,并添加了键 entity.huddle.participants.0。 |
entity.huddle.participants.1 |
about.resource.attribute.labels.value |
直接从 entity.huddle.participants.1 字段映射,并添加了键 entity.huddle.participants.1。 |
entity.type |
target.resource.resource_subtype |
直接从 entity.type 字段映射。 |
entity.user.email |
target.user.email_addresses |
直接从 entity.user.email 字段映射。 |
entity.user.id |
target.user.product_object_id |
直接从 entity.user.id 字段映射。 |
entity.user.name |
target.user.user_display_name |
直接从 entity.user.name 字段映射。 |
entity.user.team |
target.user.group_identifiers |
直接从 entity.user.team 字段映射。 |
entity.workflow.id |
target.resource.id |
直接从 entity.workflow.id 字段映射。 |
entity.workflow.name |
target.resource.name |
直接从 entity.workflow.name 字段映射。 |
id |
metadata.product_log_id |
直接从 id 字段映射。 |
ip |
principal.ip |
直接从 ip 字段映射。由基于 action 字段的逻辑确定。默认值为 USER_COMMUNICATION,但会根据 action 的值更改为其他值,例如 USER_CREATION、USER_LOGIN、USER_LOGOUT、USER_RESOURCE_ACCESS、USER_RESOURCE_UPDATE_PERMISSIONS 或 USER_CHANGE_PERMISSIONS。硬编码为“SLACK_AUDIT”。如果存在 date_create,则设置为“Enterprise Grid”;否则,如果存在 user_id,则设置为“Audit Logs”。硬编码为“Slack”。硬编码为“REMOTE”。如果 action 包含“user_login”或“user_logout”,则设置为“SSO”。否则,设置为“MACHINE”。在提供的示例中未映射。默认为“ALLOW”,但如果 action 为“user_login_failed”,则设置为“BLOCK”。如果 date_create 存在,则设置为“Slack”;否则,如果 user_id 存在,则设置为“SLACK”。 |
user_agent |
network.http.user_agent |
直接从 user_agent 字段映射。 |
user_id |
principal.user.product_object_id |
直接从 user_id 字段映射。 |
username |
principal.user.product_object_id |
直接从 username 字段映射。 |
需要更多帮助?从社区成员和 Google SecOps 专业人士那里获得解答。