收集 Office 365 邮件跟踪日志
本文档介绍了如何使用多种注入方法将 Office 365 邮件轨迹日志注入到 Google Security Operations。注入标签标识将原始日志数据标准化为结构化 UDM 格式的解析器。本文档中的信息适用于具有 OFFICE_365_MESSAGETRACE 注入标签的解析器。
Office 365 邮件跟踪是 Microsoft Exchange Online 的一项功能,用于跟踪电子邮件在 Exchange Online 邮件流管道中的传输情况。邮件跟踪日志提供有关每封电子邮件的详细信息,包括发件人和收件人地址、主题、递送状态、来源和目标 IP 地址以及邮件大小。这些数据对于排查邮件递送问题、调查可疑邮件活动以及监控邮件流量模式至关重要。
系统会使用 Exchange Online PowerShell 中的 Get-MessageTraceV2 cmdlet,以编程方式检索邮件跟踪数据。Exchange Online PowerShell 模块 (ExchangeOnlineManagement) 在 Windows、macOS 和 Linux 上正式受支持,需使用 PowerShell 7.4.0 或更高版本(在 Windows 上则需使用 Windows PowerShell 5.1)。
准备工作
请确保满足以下前提条件:
- Google SecOps 实例
- 具有 Exchange Online 的 Microsoft 365 租户
- Microsoft 365 中的全局管理员、Exchange 管理员或安全读取者角色
- 对 Google Cloud Console 的访问权限(用于创建 API 密钥、GCS 和 Webhook)
- 在 Google SecOps 中创建和管理 Feed 的权限
- 用于运行导出脚本的专用 Windows、macOS 或 Linux 服务器或工作站:
- Windows:Windows 10/11 或 Windows Server 2016 或更高版本,并安装了 Windows PowerShell 5.1(内置)或 PowerShell 7.4.0 或更高版本
- macOS:macOS 13 Ventura 或更高版本,且安装了 PowerShell 7.4.0 或更高版本
- Linux:Debian 11 及更高版本、Ubuntu 20.04 及更高版本、RHEL 8 及更高版本,或 Fedora 36 及更高版本,且安装了 PowerShell 7.4.0 或更高版本
- 从导出机器到 Microsoft 365 和 Google SecOps 提取端点的网络连接
设置导出环境
Office 365 邮件跟踪没有内置推送功能。您必须在专用的 Windows、macOS 或 Linux 服务器或工作站上运行导出脚本,该脚本会使用 PowerShell 从 Exchange Online 检索邮件跟踪数据,并将其发送到 Google SecOps。
您可以通过 Exchange Online PowerShell 获取邮件跟踪数据,但存在以下保留限制:
Get-MessageTraceV2:返回过去 10 天的数据。结果会立即显示。Start-HistoricalSearch:返回 10 到 90 天的数据。结果将以可下载的 CSV 报告形式提供,可能需要几个小时才能准备就绪。
以下步骤会在您的机器上安装 PowerShell 和 Exchange Online PowerShell 模块。
安装 PowerShell
Windows
Windows 10、Windows 11 和 Windows Server 2016 或更高版本中包含 Windows PowerShell 5.1。无需进行额外安装。
如需验证 PowerShell 版本,请打开 PowerShell 并运行以下命令:
$PSVersionTable.PSVersion(可选)如需安装 PowerShell 7 以提高性能,请以管理员身份打开命令提示符或 PowerShell,然后运行以下命令:
winget install --id Microsoft.PowerShell --source winget
macOS
- 安装 Homebrew(如果尚未安装)。
打开终端并运行以下命令:
brew install powershell/tap/powershell运行以下命令,验证安装是否成功:
pwsh --version输出应显示
PowerShell 7.x.x或更高版本。
Linux (Debian/Ubuntu)
- 打开具有 root 或 sudo 权限的终端。
运行以下命令:
sudo apt-get update sudo apt-get install -y wget apt-transport-https software-properties-common source /etc/os-release wget -q "https://packages.microsoft.com/config/ubuntu/$VERSION_ID/packages-microsoft-prod.deb" sudo dpkg -i packages-microsoft-prod.deb rm packages-microsoft-prod.deb sudo apt-get update sudo apt-get install -y powershell运行以下命令,验证安装是否成功:
pwsh --version
Linux (RHEL/CentOS/Fedora)
- 打开具有 root 或 sudo 权限的终端。
注册 Microsoft 代码库:
curl "https://packages.microsoft.com/config/rhel/$(rpm -E %rhel)/prod.repo" | sudo tee /etc/yum.repos.d/microsoft.repo安装 PowerShell:
sudo dnf install -y powershell运行以下命令,验证安装是否成功:
pwsh --version
安装 Exchange Online PowerShell 模块
安装 PowerShell 后,安装 Exchange Online 管理模块。此步骤在所有平台上都相同。
启动 PowerShell:
- Windows:以管理员身份打开 PowerShell 或 PowerShell 7
- macOS 和 Linux:打开终端并运行
pwsh
运行以下命令:
Install-Module -Name ExchangeOnlineManagement -Scope CurrentUser -Force如果系统提示您从不受信任的代码库 (PSGallery) 安装,请输入
Y进行确认。运行以下命令,验证安装是否成功:
Import-Module ExchangeOnlineManagement Get-Module ExchangeOnlineManagement | Select-Object Name, Version
输出应显示模块名称和版本号。
设置基于证书的身份验证(计划脚本必需)
Connect-ExchangeOnline -UserPrincipalName 方法需要交互式登录,不能在预设脚本中使用。对于无人值守的执行,请使用 Azure AD(Microsoft Entra ID)应用设置基于证书的身份验证。
创建自签名证书
Windows(以管理员身份在 PowerShell 中运行):
mkdir C:\Certs $cert = New-SelfSignedCertificate -Subject "CN=MessageTraceExport" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec KeyExchange -KeyLength 2048 -NotAfter (Get-Date).AddYears(2) $cert.Thumbprint Export-Certificate -Cert $cert -FilePath "C:\Certs\MessageTraceExport.cer"保存指纹值,以便在后续步骤中使用。
macOS 和 Linux(在终端中运行):
mkdir -p /opt/certs openssl req -x509 -newkey rsa:2048 -keyout /opt/certs/messagetrace-key.pem -out /opt/certs/messagetrace-cert.pem -days 730 -nodes -subj "/CN=MessageTraceExport" openssl pkcs12 -export -out /opt/certs/messagetrace.pfx -inkey /opt/certs/messagetrace-key.pem -in /opt/certs/messagetrace-cert.pem -passout pass: chmod 644 /opt/certs/messagetrace.pfx获取证书指纹:
openssl x509 -in /opt/certs/messagetrace-cert.pem -noout -fingerprint -sha1 | sed 's/://g' | cut-d= -f2保存指纹值,以便在后续步骤中使用。
在 Microsoft Entra ID 中注册应用
- 登录 Microsoft Entra 管理中心。
- 依次前往身份 > 应用 > 应用注册。
- 点击 New registration(新注册)。
- 提供以下配置详细信息:
- 名称:输入
MessageTraceExport - 支持的账号类型:选择仅此组织目录中的账号
- 名称:输入
- 点击注册。
- 在应用概览页面上,复制并保存应用(客户端)ID。
- 从概览页面复制目录(租户)ID 并保存。
将证书上传到应用
- 在应用页面上,依次前往证书和密钥 > 证书。
- 点击上传证书。
- 上传证书文件:
- Windows:上传
C:\Certs\MessageTraceExport.cer - macOS 和 Linux:上传
/opt/certs/messagetrace-cert.pem
- Windows:上传
- 点击 Add(添加)。
分配 API 权限
导出脚本会运行 Get-MessageTraceV2 cmdlet,这需要两项 Office 365 Exchange Online 应用权限:Exchange.ManageAsApp(用于以应用身份进行身份验证)和 ReportingWebService.Read.All(用于读取邮件跟踪数据)。如果缺少 ReportingWebService.Read.All,脚本会失败并显示 403 The caller does not have permission 错误。
- 在应用页面上,前往 API 权限。
- 点击添加权限。
- 选择我组织使用的 API。
- 搜索并选择 Office 365 Exchange Online。
- 选择应用权限。
- 添加以下两项权限:
- 展开 Exchange,然后选择 Exchange.ManageAsApp。
- 展开 ReportingWebService,然后选择 ReportingWebService.Read.All。
- 点击添加权限。
点击为 <您的组织>授予管理员同意书,然后确认。
分配 Exchange 管理员角色
- 在 Microsoft Entra 管理中心内,依次前往身份 > 角色和管理员 > 所有角色。
- 搜索并选择 Exchange 管理员。
- 点击添加分配。
- 点击未选择任何成员,然后搜索
MessageTraceExport应用。 - 选择相应应用,然后点击下一步。
- 选择有效作为分配关系类型。
- 点击分配。
验证无人值守连接
启动 PowerShell 并运行以下命令:
Windows:
Connect-ExchangeOnline -CertificateThumbprint &<quot;CERTIFICATE_THUMB>PRINT"<; -AppId ">;APPLICATION_ID" -Organization "yourdomain.onmicrosoft.com" Get-MessageTraceV2 -StartDate (Get-Date).AddHours(-1) -EndDate (Get-Date) -ResultSize 1 Disconnect-ExchangeOnline -Confirm:$falsemacOS 和 Linux(先运行
pwsh):Connect-ExchangeOnline -CertificateFilePath "/opt/certs/messagetrace.pfx"<; -AppId ">;APPLICATION_ID" -Organization "yourdomain.onmicrosoft.com" Get-MessageTraceV2 -StartDate (Get-Date).AddHours(-1) -EndDate (Get-Date) -ResultSize 1 Disconnect-ExchangeOnline -Confirm:$false将
<CERTIFICATE_THUMBPRINT>、<APPLICATION_ID>和yourdomain.onmicrosoft.com替换为您的实际值。如果该命令返回消息跟踪数据(或没有错误的空结果集),则表示身份验证正常运作。
选择注入方法
Google SecOps 支持多种 Office 365 邮件跟踪日志注入方法。选择最适合您环境的方法:
| 注入方法 | 使用场景 | 延迟时间 | 设置复杂性 |
|---|---|---|---|
| Webhook | 通过脚本或应用实时推送 | 秒 | 低 |
| Google Cloud Storage V2 | 批量导出到 GCS 存储桶 | 几分钟到几小时 | 中 |
选项 1:Webhook 提取
如果您有脚本或应用可将包含消息跟踪数据的 HTTP POST 请求发送到 Google SecOps,请使用此方法。
在 Google SecOps 中创建 Webhook Feed
创建 Feed
- 前往 SIEM 设置 > Feed。
- 点击添加新 Feed。
- 在下一页上,点击配置单个 Feed。
- 在 Feed 名称字段中,输入 Feed 的名称(例如
Office 365 Message Trace - Webhook)。 - 选择 Webhook 作为来源类型。
- 选择 Office 365 邮件跟踪作为日志类型。
- 点击下一步。
- 为以下输入参数指定值:
- 定界符(可选):输入
\n以拆分以换行符分隔的 JSON 事件 - 资产命名空间:资产命名空间
- 注入标签:要应用于此 Feed 中事件的标签
- 定界符(可选):输入
- 点击下一步。
- 在最终确定界面中查看新的新闻信息流配置,然后点击提交。
生成并保存密钥
创建 Feed 后,您必须生成用于身份验证的密钥:
- 在 Feed 详情页面上,点击生成密钥。
- 系统会显示一个对话框,其中包含密钥。
复制并妥善保存密钥。
获取 Feed 端点网址
- 前往该 Feed 的详细信息标签页。
- 在端点信息部分,复制 Feed 端点网址。
网址格式为:
https://{region}-chronicle.googleapis.com/v1/{parent}/logs:import其中,
{region}是 Google SecOps 实例所在的区域(例如us、europe或asia-southeast1),{parent}是资源路径,格式为projects/<PROJECT_ID>/locations/<LOCATION>/instances/<INSTANCE_ID>/logTypes/<LOG_TYPE>。保存此网址,以便在后续步骤中使用。
点击完成。
创建 Google Cloud API 密钥
Google SecOps 需要使用 API 密钥进行身份验证。在 Google Cloud Console 中创建受限 API 密钥。
创建 API 密钥
- 前往 Google Cloud 控制台“凭据”页面。
- 选择您的项目(与您的 Google SecOps 实例关联的项目)。
- 依次点击创建凭据 > API 密钥。
- 系统会创建 API 密钥,并在对话框中显示。
- 点击修改 API 密钥以限制密钥。
限制 API 密钥
- 在 API 密钥设置页面中:
- 名称:输入描述性名称(例如
Google SecOps Webhook API Key - O365 Message Trace)
- 名称:输入描述性名称(例如
- 在 API 限制下:
- 选择限制密钥。
- 在选择 API 下拉菜单中,搜索并选择 Google SecOps API(或 Chronicle API)。
- 点击保存。
- 从页面顶部的 API 密钥字段复制 API 密钥值。
安全地保存 API 密钥。
创建 Webhook 导出脚本
在您设置导出环境的机器上创建以下 PowerShell 脚本。此脚本从 Exchange Online 检索邮件跟踪数据,并将其发送到 Google SecOps webhook 端点。
Windows
创建脚本目录:
mkdir C:\Scripts创建一个名为
C:\Scripts\messagetrace-webhook.ps1的文件,其中包含以下内容:# Configuration $endpointUrl = "https://{region}-chronicle.googleapis.com/v1/{parent}/logs:import" $<apiKey<>/span> = "API_KEY&<quot; $sec>retKey = "SECRET<_KEY" $certThumbp>rint = "<;CERTIFICATE_T>HUMBPRINT" $appId = "APPLICATION_ID" $organization = "yourdomain.onmicrosoft.com" # Log file $logFile = "C:\Logs\messagetrace-webhook.log" if (!(Test-Path "C:\Logs")) { New-Item -ItemType Directory -Path "C:\Logs" } try { Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Starting message trace export" # Connect to Exchange Online using certificate-based authentication Connect-ExchangeOnline -CertificateThumbprint $certThumbprint -AppId $appId -Organization $organization -ShowBanner:$false # Retrieve message trace data for the last hour (up to 10 days available) $startDate = (Get-Date).AddHours(-1) $endDate = Get-Date $messages = Get-MessageTraceV2 -StartDate $startDate -EndDate $endDate -ResultSize 5000 if ($messages.Count -eq 0) { Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - No messages found in the time range" Disconnect-ExchangeOnline -Confirm:$false exit 0 } # Convert to NDJSON (one JSON object per line) $ndjson = ($messages | ForEach-Object { $_ | ConvertTo-Json -Compress }) -join "`n" # Send to Google SecOps webhook $headers = @{ "X-goog-api-key" = $apiKey "X-Webhook-Access-Key" = $secretKey } # Send raw UTF-8 bytes so PowerShell does not re-encode the NDJSON body $bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($ndjson) $response = Invoke-RestMethod -Uri $endpointUrl -Method Post -Headers $headers -Body $bodyBytes -ContentType "application/json" Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Successfully sent $($messages.Count) messages" } catch {Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Error: $_" } finally { Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue }替换占位值:
<API_KEY>:Google Cloud API 密钥<SECRET_KEY>:Google SecOps webhook 密钥<CERTIFICATE_THUMBPRINT>:身份验证设置中的证书指纹<APPLICATION_ID>:Azure AD 应用(客户端)IDyourdomain.onmicrosoft.com:您的 Microsoft 365 租户网域
macOS 和 Linux
创建脚本目录:
sudo mkdir -p /opt/scripts sudo mkdir -p /var/log/messagetrace创建一个名为
/opt/scripts/messagetrace-webhook.ps1的文件,其中包含以下内容:# Configuration $endpointUrl = "https://{region}-chronicle.googleapis.com/v1/{parent}/logs:import" $<apiKey<>/span> = "API_KEY&<quot; $sec>retKey = "SECRET_KEY" $certFilePath = "/opt</certs/message>trace.pfx" $appId = "APPLICATION_ID" $organization = "yourdomain.onmicrosoft.com" # Log file $logFile = "/var/log/messagetrace/messagetrace-webhook.log" try { Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Starting message trace export" # Connect to Exchange Online using certificate-based authentication Connect-ExchangeOnline -CertificateFilePath $certFilePath -AppId $appId -Organization $organization -ShowBanner:$false # Retrieve message trace data for the last hour (up to 10 days available) $startDate = (Get-Date).AddHours(-1) $endDate = Get-Date $messages = Get-MessageTraceV2 -StartDate $startDate -EndDate $endDate -ResultSize 5000 if ($messages.Count -eq 0) { Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - No messages found in the time range" Disconnect-ExchangeOnline -Confirm:$false exit 0 } # Convert to NDJSON (one JSON object per line) $ndjson = ($messages | ForEach-Object { $_ | ConvertTo-Json -Compress }) -join "`n" # Send to Google SecOps webhook $headers = @{ "X-goog-api-key" = $apiKey "X-Webhook-Access-Key" = $secretKey } # Send raw UTF-8 bytes so PowerShell does not re-encode the NDJSON body $bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($ndjson) $response = Invoke-RestMethod -Uri $endpointUrl -Method Post -Headers $headers -Body $bodyBytes -ContentType "application/json" Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Successfully sent $($messages.Count) messages" } catch { Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Error: $_" } finally { Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue }替换占位值:
<API_KEY>:Google Cloud API 密钥<SECRET_KEY>:Google SecOps webhook 密钥<APPLICATION_ID>:Azure AD 应用(客户端)IDyourdomain.onmicrosoft.com:您的 Microsoft 365 租户网域
设置文件权限:
sudo chmod 700 /opt/scripts/messagetrace-webhook.ps1
安排导出脚本
将脚本配置为定期(例如每小时)自动运行。
Windows
- 打开任务计划程序:按
Win+R,输入taskschd.msc,然后按Enter。 - 在右侧窗格中,点击创建任务。
- 在常规标签页上:
- 名称:输入
MessageTrace Webhook Export - 选择无论用户是否登录都运行
- 选择以最高权限运行
- 名称:输入
- 在触发器标签页上:
- 点击 New(新建)。
- 将开始任务设置为按计划。
- 选择每天,将开始时间设置为
12:00:00 AM(午夜,以便在整点重复),然后设置每 1 天重复一次。 - 选择每
1 hour重复执行任务,持续时间为无限期。 - 选择已启用。
- 点击确定。
在操作标签页上:
- 点击 New(新建)。
- 将操作设置为启动计划。
在程序/脚本字段中,输入:
powershell.exe在添加参数字段中,输入:
-NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\messagetrace-webhook.ps1"点击确定。
在设置标签页中:
- 选择允许按需运行任务
- 取消选中如果任务运行时间超过以下值,则停止任务复选框
点击确定,然后在系统提示时输入服务账号凭证。
macOS
在
~/Library/LaunchAgents/com.chronicle.messagetrace-webhook.plist处创建 launchd plist 文件:<?xml version="1.0" encodin>g<="UTF-8"? !DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.a>p<ple.com/DTDs/Proper>t<yLis>t-1.0<.dt>d&quo<t; p>list <versio>n="1.0" dict keyLabe<l/key > st>ringcom.chronicle.messa<getr>ace-w<ebhoo>k/string < >span>keyProgramArguments/k<>ey arrayg keyRunAtLoad/key true/ /dict /plist<>/span>string/usr/<>local/bin/pwsh/s<tring > < string-NoProf<ile/st>ring string-File/string < string/op<t/scri>pts/m<ess>agetrace-webh<ook.>ps1/s<tring <>span class="devsite-syntax-w"> <</span>/a>rray keyStartInterval/key < integ<er3600>/integer keyStandardOutPath/key string/>var/l<og/>messagetrace/laun<chd->stdou<t.log/>string keyStandardErrorPath/key string/>var/l<og/>messagetr<ace/>launc<hd-st>d<err.l>o<g/stri>n加载作业:
launchctl load ~/Library/LaunchAgents/com.chronicle.messagetrace-webhook.plist验证作业是否已加载:
launchctl list | grep messagetrace
Linux
打开 crontab 编辑器:
crontab -e添加以下行,以便每小时运行一次脚本:
0 * * * * /usr/bin/pwsh -NoProfile -File /opt/scripts/messagetrace-webhook.ps1 >> /var/log/messagetrace/cron.log 2>&1保存并退出编辑器。
验证 Cron 作业是否已注册:
crontab -l
验证日志注入
手动运行脚本进行测试:
Windows:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\messagetrace-webhook.ps1"macOS 和 Linux:
pwsh -NoProfile -File /opt/scripts/messagetrace-webhook.ps1检查日志文件是否存在错误:
Windows:
Get-Content "C:\Logs\messagetrace-webhook.log"-Tail 10macOS 和 Linux:
tail -10 /var/log/messagetrace/messagetrace-webhook.log在 Google SecOps 中,前往搜索,并验证是否显示包含
metadata.log_type = "OFFICE_365_MESSAGETRACE"的日志。
选项 2:Google Cloud Storage V2 注入
如果您的导出脚本会将邮件轨迹日志写入 Google Cloud Storage 存储桶,请使用此方法。
创建 GCS 存储桶
- 前往 Google Cloud 控制台。
- 选择您的项目或创建一个新项目。
- 在导航菜单中,前往 Cloud Storage > 存储桶。
- 点击创建存储分区。
提供以下配置详细信息:
设置 值 为存储桶命名 输入一个全局唯一的名称(例如 office365-messagetrace-logs)位置类型 根据您的需求进行选择(区域级、双区域级、多区域级) 位置 选择位置(例如 us-central1)存储类别 标准(推荐用于频繁访问的日志) 访问权限控制 均匀(推荐) 保护工具 可选:启用对象版本控制或保留政策 点击创建。
安装 Google Cloud CLI
在设置导出环境的同一台机器上安装 Google Cloud CLI。gsutil 命令(包含在 Google Cloud CLI 中)用于将文件上传到 GCS 存储桶。
Windows
- 下载 Google Cloud CLI 安装程序 (
GoogleCloudSDKInstaller.exe)。 - 运行
GoogleCloudSDKInstaller.exe。在安装选项界面上,保留默认选择。点击安装。安装完成后,保持选中运行gcloud init,然后点击完成。 打开命令提示符并运行以下命令,验证安装是否成功:
gcloud --version gsutil --version
macOS
打开终端并运行以下命令:
brew install google-cloud-sdk验证安装:
gcloud --version gsutil --version
Linux (Debian/Ubuntu)
- 打开具有 root 或 sudo 权限的终端。
运行以下命令:
sudo apt-get install -y apt-transport-https ca-certificates gnupg curl curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee /etc/apt/sources.list.d/google-cloud-sdk.list sudo apt-get update sudo apt-get install -y google-cloud-cli验证安装:
gcloud --version gsutil --version
Linux (RHEL/CentOS/Fedora)
- 打开具有 root 或 sudo 权限的终端。
创建代码库文件:
sudo tee /etc/yum.repos.d/google-cloud-sdk.repo << 'EOF' [google-cloud-cli] name=Google Cloud CLI baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el9-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=0 gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF安装 Google Cloud CLI:
sudo dnf install -y google-cloud-cli验证安装:
gcloud --version gsutil --version
对 Google Cloud CLI 进行身份验证
运行以下命令进行身份验证:
gcloud auth login设置包含 GCS 存储桶的项目:
gcloud config set project <PROJECT_ID>将
<PROJECT_ID>替换为您的 Google Cloud 项目 ID。
对于无人值守(预定)使用,请使用服务账号密钥进行身份验证。导出脚本会使用此服务账号将文件上传到 GCS 存储桶。它与用于从存储桶中读取数据的 Google SecOps 服务账号(在后续步骤中配置)是分开的。
- 前往 Google Cloud 控制台,然后选择您的项目。
- 点击创建服务账号。
- 在服务账号名称字段中,输入一个名称(例如
chronicle-gcs-export)。 - 点击创建并继续。
- 在向此服务账号授予对项目的访问权限部分,选择 Storage Object Creator 角色。
- 点击完成。
- 在服务账号列表中,点击您创建的服务账号。
- 前往密钥标签页。
- 依次点击添加密钥> 创建新密钥。
- 选择 JSON,然后点击创建。
- 保存下载的 JSON 密钥文件:
- Windows:
C:\Certs\gcs-service-account.json - macOS 和 Linux:
/opt/certs/gcs-service-account.json
- Windows:
激活服务账号:
gcloud auth activate-service-account --key-file=<PATH_TO_KEY_FILE>
创建 GCS 导出脚本
Windows
创建一个名为
C:\Scripts\messagetrace-gcs.ps1的文件,其中包含以下内容:# Configuration $certThumbprint = &<quot;CERTIFICATE_THUMB>PRINT" <$appId = ">;APPLICATION_ID" $organization = "yourdomain.onmicrosoft.com" $gcsBucket = "gs://office365-messagetrace-logs/messagetrace/" $localLogDir = "C:\Logs\MessageTrace" # Log file $logFile = "C:\Logs\messagetrace-gcs.log" if (!(Test-Path $localLogDir)) { New-Item -ItemType Directory -Path $localLogDir } try { Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Starting message trace export to GCS" # Connect to Exchange Online using certificate-based authentication Connect-ExchangeOnline -CertificateThumbprint $certThumbprint -AppId $appId -Organization $organization -ShowBanner:$false # Retrieve message trace data for the last hour (up to 10 days available) $startDate = (Get-Date).AddHours(-1) $endDate = Get-Date $messages = Get-MessageTraceV2 -StartDate $startDate -EndDate $endDate -ResultSize 5000 if ($messages.Count -eq 0) { Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - No messages found in the time range" Disconnect-ExchangeOnline -Confirm:$false exit 0 } # Convert to NDJSON (one JSON object per line) $ndjson = $messages | ForEach-Object { $_ | ConvertTo-Json -Compress } $fileName = "messagetrace_$(Get-Date -Format 'yyyyMMddHHmmss').json" $filePath = Join-Path $localLogDir $fileName $ndjson | Out-File -FilePath $filePath -Encoding UTF8 # Upload to GCS gsutil cp $filePath $gcsBucket Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Uploaded $fileName with $($messages.Count) messages" # Remove local file after successful upload Remove-Item $filePath } catch { Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Error: $_" } finally { Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue }替换占位值:
<CERTIFICATE_THUMBPRINT>:身份验证设置中的证书指纹<APPLICATION_ID>:Azure AD 应用(客户端)IDyourdomain.onmicrosoft.com:您的 Microsoft 365 租户网域office365-messagetrace-logs:您的 GCS 存储桶名称
macOS 和 Linux
创建一个名为
/opt/scripts/messagetrace-gcs.ps1的文件,其中包含以下内容:# Configuration $certFilePath = "/opt/certs/messagetrace.pfx" <$appId = ">;APPLICATION_ID" $organization = "yourdomain.onmicrosoft.com" $gcsBucket = "gs://office365-messagetrace-logs/messagetrace/" $localLogDir = "/var/log/messagetrace/export" # Log file $logFile = "/var/log/messagetrace/messagetrace-gcs.log" if (!(Test-Path $localLogDir)) { New-Item -ItemType Directory -Path $localLogDir } try { Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Starting message trace export to GCS" # Connect to Exchange Online using certificate-based authentication Connect-ExchangeOnline -CertificateFilePath $certFilePath -AppId $appId -Organization $organization -ShowBanner:$false # Retrieve message trace data for the last hour (up to 10 days available) $startDate = (Get-Date).AddHours(-1) $endDate = Get-Date $messages = Get-MessageTraceV2 -StartDate $startDate -EndDate $endDate -ResultSize 5000 if ($messages.Count -eq 0) { Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - No messages found in the time range" Disconnect-ExchangeOnline -Confirm:$false exit 0 } # Convert to NDJSON (one JSON object per line) $ndjson = $messages | ForEach-Object { $_ | ConvertTo-Json -Compress } $fileName = "messagetrace_$(Get-Date -Format 'yyyyMMddHHmmss').json" $filePath = Join-Path $localLogDir $fileName $ndjson | Out-File -FilePath $filePath -Encoding UTF8 # Upload to GCS gsutil cp $filePath $gcsBucket Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Uploaded $fileName with $($messages.Count) messages" # Remove local file after successful upload Remove-Item $filePath } catch { Add-Content -Path $logFile -Value "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Error: $_" } finally { Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue }替换占位值:
<APPLICATION_ID>:Azure AD 应用(客户端)IDyourdomain.onmicrosoft.com:您的 Microsoft 365 租户网域office365-messagetrace-logs:您的 GCS 存储桶名称
设置文件权限:
sudo chmod 700 /opt/scripts/messagetrace-gcs.ps1
安排 GCS 导出脚本
Windows
- 打开任务计划程序:按
Win+R,输入taskschd.msc,然后按Enter。 - 在右侧窗格中,点击创建任务。
- 在常规标签页上:
- 名称:输入
MessageTrace GCS Export - 选择无论用户是否登录都运行
- 选择以最高权限运行
- 名称:输入
- 在触发器标签页上:
- 点击 New(新建)。
- 将开始任务设置为按计划。
- 选择每天,将开始时间设置为
12:00:00 AM(午夜,以便在整点重复),然后设置每 1 天重复一次。 - 选择每
1 hour重复执行任务,持续时间为无限期。 - 选择已启用。
- 点击确定。
在操作标签页上:
- 点击 New(新建)。
- 将操作设置为启动计划。
在程序/脚本字段中,输入:
powershell.exe在添加参数字段中,输入:
-NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\messagetrace-gcs.ps1"点击确定。
在设置标签页中:
- 选择允许按需运行任务
- 取消选中如果任务运行时间超过以下值,则停止任务复选框
点击确定,然后在系统提示时输入服务账号凭证。
macOS
在
~/Library/LaunchAgents/com.chronicle.messagetrace-gcs.plist处创建 launchd plist 文件:<?xml version="1.0" encodin>g<="UTF-8"? !DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.a>p<ple.com/DTDs/Proper>t<yLis>t-1.0<.dt>d&quo<t; p>list <versio>n="1.0" dict key<Label/k>ey < <>/span>stringcom.chronic<le.m>essag<etrac>e-gcs/str<ing > keyProgramArgumen<>ts/key array< > string/<>usr/local/bin/pw<sh/str>ing < >string-No<Profil>e/string string-File/stri<ng > s<>;tring/opt/s<cri>pts/messagetr<ace->gcs.p<s1/stri>ng < /array < >span>keyStartInterval/<key > i<nteger>3600/integer keyStandardOutPath/key <string/>var/l<og/>messagetrace/laun<chd->gcs-s<tdout.>log/string keyStandardErrorPath/key <string/>var/l<og/>messagetr<ace/>launc<hd-gc>s<-stde>r<r.log/>string keyRunAtLoad/key true/ /dict /plist加载作业:
launchctl load ~/Library/LaunchAgents/com.chronicle.messagetrace-gcs.plist验证作业是否已加载:
launchctl list | grep messagetrace
Linux
打开 crontab 编辑器:
crontab -e添加以下行,以便每小时运行一次脚本:
0 * * * * /usr/bin/pwsh -NoProfile -File /opt/scripts/messagetrace-gcs.ps1 >> /var/log/messagetrace/cron-gcs.log 2>&1保存并退出编辑器。
验证 Cron 作业是否已注册:
crontab -l
验证 GCS 上传
手动运行脚本以进行测试:
Windows:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\messagetrace-gcs.ps1"macOS 和 Linux:
pwsh -NoProfile -File /opt/scripts/messagetrace-gcs.ps1验证文件是否已上传到 GCS 存储桶:
gsutil ls gs://office365-messagetrace-logs/messagetrace/检查日志文件是否存在错误:
Windows:
Get-Content "C:\Logs\messagetrace-gcs.log"-Tail 10macOS 和 Linux:
tail -10 /var/log/messagetrace/messagetrace-gcs.log
获取 Google SecOps 服务账号
- 前往 SIEM 设置 > Feed。
- 点击添加新 Feed。
- 点击配置单个 Feed。
- 在 Feed 名称字段中,输入 Feed 的名称(例如
Office 365 Message Trace - GCS)。 - 选择 Google Cloud Storage V2 作为来源类型。
- 选择 Office 365 邮件跟踪作为日志类型。
- 点击获取服务账号。
系统会显示一个专属的服务账号邮箱,例如:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com复制此邮箱,以便在下一步中使用。
授予 IAM 权限
- 前往 Cloud Storage > 存储桶。
- 点击您的存储桶名称。
- 前往权限标签页。
- 点击授予访问权限。
- 提供以下配置详细信息:
- 添加主账号:粘贴 Google SecOps 服务账号电子邮件地址
- 分配角色:选择 Storage Object Viewer
点击保存。
为 GCS 配置 Google SecOps Feed
- 从 Feed 创建页面继续操作(或前往 SIEM 设置 > Feed > 添加新 Feed)。
- 点击下一步。
为以下输入参数指定值:
存储桶网址:输入带有前缀路径的 GCS 存储桶 URI:
gs://office365-messagetrace-logs/messagetrace/
- 来源删除选项:根据您的偏好选择删除选项:
- 永不:转移后永不删除任何文件(建议用于测试)
- 删除已转移的文件:在成功转移后删除文件
- 删除已转移的文件和空目录:在成功转移后删除文件和空目录
- 文件存在时间上限:包含过去指定天数内修改过的文件(默认值为 180 天)
- 资源命名空间:资源命名空间
- 注入标签:要应用于此 Feed 中事件的标签
点击下一步。
在最终确定界面中查看新的新闻信息流配置,然后点击提交。
UDM 映射表
下表列出了 OFFICE_365_MESSAGETRACE 日志类型的日志字段及其对应的 UDM 字段。
| 日志字段 | UDM 映射 | 逻辑 |
|---|---|---|
additional_AdditionalFields |
additional.fields |
已合并 |
additional_DeliveryLocation |
additional.fields |
已合并 |
additional_OrgLevelPolicy |
additional.fields |
已合并 |
additional_connectors |
additional.fields |
已合并 |
additional_delivery_action |
additional.fields |
已合并 |
additional_fields_UrlLocation |
additional.fields |
已合并 |
additional_orgLevelAction |
additional.fields |
已合并 |
end_date_label |
additional.fields |
已合并 |
index_label |
additional.fields |
已合并 |
metadata_id_label |
additional.fields |
已合并 |
operationName_label |
additional.fields |
已合并 |
start_date_label |
additional.fields |
已合并 |
tenant_label |
additional.fields |
已合并 |
type_label |
additional.fields |
已合并 |
properties.AuthenticationDetails |
extensions.auth.auth_details |
直接映射 |
Received |
metadata.event_timestamp |
已解析为 UNIX_MS |
time |
metadata.event_timestamp |
解析为 ISO8601 |
tenantId |
metadata.product_deployment_id |
直接映射 |
category |
metadata.product_event_type |
直接映射 |
MessageTraceId |
metadata.product_log_id |
直接映射 |
SenderAddress |
network.email.from |
直接映射 |
properties.SenderFromAddress |
network.email.from |
直接映射 |
MessageId |
network.email.mail_id |
直接映射 |
Subject |
network.email.subject |
已合并 |
properties.Subject |
network.email.subject |
已合并 |
RecipientAddress |
network.email.to |
已合并 |
properties.RecipientEmailAddress |
network.email.to |
已合并 |
Size |
network.received_bytes |
直接映射 |
Organization |
principal.administrative_domain |
直接映射 |
properties.SenderFromDomain |
principal.administrative_domain |
直接映射 |
FromIP |
principal.ip |
已合并 |
properties.FileName |
principal.process.file.names |
已合并 |
properties.SHA256 |
principal.process.file.sha256 |
直接映射 |
properties.FileSize |
principal.process.file.size |
已重命名/映射 |
additional_UserLevelAction |
principal.user.attribute.labels |
已合并 |
additional_UserLevelPolicy |
principal.user.attribute.labels |
已合并 |
sender_email_from_domain_label |
principal.user.attribute.labels |
已合并 |
properties.SenderFromAddress |
principal.user.email_addresses |
已合并 |
properties.SenderObjectId |
principal.user.product_object_id |
直接映射 |
properties.SenderDisplayName |
principal.user.user_display_name |
直接映射 |
action |
security_result.action |
已合并 |
Status |
security_result.action_details |
直接映射 |
security_result_category |
security_result.category |
已合并 |
properties.ConfidenceLevel |
security_result.confidence_details |
直接映射 |
detect_method |
security_result.detection_fields |
已合并 |
detection_method |
security_result.rule_name |
直接映射 |
properties.ThreatNames |
security_result.threat_name |
直接映射 |
properties.UrlDomain |
target.asset.hostname |
直接映射 |
ToIP |
target.asset.ip |
已合并 |
properties.UrlDomain |
target.hostname |
直接映射 |
ToIP |
target.ip |
已合并 |
properties.Url |
target.url |
直接映射 |
properties.RecipientEmailAddress |
target.user.email_addresses |
已合并 |
properties.RecipientObjectId |
target.user.product_object_id |
直接映射 |
| 不适用 | metadata.event_type |
常量:EMAIL_TRANSACTION |
| 不适用 | network.direction |
常量:INBOUND |
| 不适用 | principal.process.file.file_type |
常量:FILE_TYPE_PNG |
| 不适用 | security_result.confidence |
常量:HIGH_CONFIDENCE |
id |
event.idm.read_only_udm.metadata.product_log_id |
从更新日志映射 |
receivedDateTime |
event.idm.read_only_udm.metadata.event_timestamp |
从更新日志映射 |
fromIP |
event.idm.read_only_udm.principal.ip和event.idm.read_only_udm.principal.asset.ip之间 |
从更新日志映射 |
toIP |
event.idm.read_only_udm.target.ip和event.idm.read_only_udm.target.asset.ip之间 |
从更新日志映射 |
status |
event.idm.read_only_udm.security_result.action_details |
从更新日志映射 |
size |
event.idm.read_only_udm.network.received_bytes |
从更新日志映射 |
senderAddress |
event.idm.read_only_udm.network.email.from |
从更新日志映射 |
recipientAddress |
event.idm.read_only_udm.network.email.to |
从更新日志映射 |
subject |
event.idm.read_only_udm.network.email.subject |
从更新日志映射 |
messageId |
event.idm.read_only_udm.network.email.mail_id |
从更新日志映射 |
properties.SenderMailFromDomain", "properties.UserLevelAction", and "properties.UserLevelPolicy |
principal.user.attribute.labels |
从更新日志映射 |
properties.EmailDirection |
network.direction |
从更新日志映射 |
properties.DeliveryAction", "properties.DeliveryLocation", "properties.Connectors", "properties.OrgLevelAction", "properties.OrgLevelPolicy", "properties.AdditionalFields", and "properties.UrlLocation |
additional.fields |
从更新日志映射 |
operationName", "Tenant |
additional.fields |
从更新日志映射 |
properties.DetectionMethods |
security_result.detection_fields |
从更新日志映射 |
更新日志
需要更多帮助?获得社区成员和 Google SecOps 专业人士的解答。