收集 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 控制台 (用於建立 API 金鑰、GCS 和 Webhook)
- 在 Google SecOps 中建立及管理動態消息的權限
- 專用的 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)
- 開啟具有根層級或 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)
- 開啟具有根層級或 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 系統管理中心。
- 依序前往「身分識別」>「應用程式」>「應用程式註冊」。
- 按一下 [新增註冊]。
- 請提供下列設定詳細資料:
- 「Name」(名稱):輸入
MessageTraceExport - 支援的帳戶類型:選取「僅限這個機構組織目錄中的帳戶」
- 「Name」(名稱):輸入
- 按一下「註冊」。
- 在應用程式總覽頁面中,複製「Application (client) ID」並儲存。
- 從總覽頁面複製並儲存「Directory (tenant) ID」。
將憑證上傳至應用程式
- 在應用程式頁面中,依序前往「Certificates & secrets」(憑證和密鑰) >「Certificates」(憑證)。
- 按一下「上傳憑證」。
- 上傳憑證檔案:
- Windows:上傳
C:\Certs\MessageTraceExport.cer - macOS 和 Linux:上傳
/opt/certs/messagetrace-cert.pem
- Windows:上傳
- 按一下「新增」。
指派 API 權限
匯出指令碼會執行 Get-MessageTraceV2 cmdlet,這需要兩項 Office 365 Exchange Online 應用程式權限:Exchange.ManageAsApp (以應用程式身分驗證) 和 ReportingWebService.Read.All (讀取郵件追蹤資料)。如果缺少 ReportingWebService.Read.All,指令碼會失敗並顯示 403 The caller does not have permission 錯誤。
- 在應用程式頁面中,前往「API permissions」。
- 按一下「新增權限」。
- 選取「貴機構使用的 API」。
- 搜尋並選取「Office 365 Exchange Online」。
- 選取「應用程式權限」。
- 新增下列兩項權限:
- 展開「Exchange」,然後選取「Exchange.ManageAsApp」。
- 展開「ReportingWebService」,然後選取「ReportingWebService.Read.All」。
- 按一下「Add permissions」。
按一下「Grant admin consent for <your organization>」,然後確認。
指派 Exchange 管理員角色
- 在 Microsoft Entra 系統管理中心,依序前往「身分識別」>「角色和管理員」>「所有角色」。
- 搜尋並選取「Exchange 管理員」。
- 按一下「新增作業」。
- 按一下「尚未選取任何成員」,然後搜尋
MessageTraceExport應用程式。 - 選取應用程式,然後按一下「下一步」。
- 選取「有效」做為指派類型。
- 按一下「指派」。
驗證無人值守連線
啟動 PowerShell 並執行:
Windows:
Connect-ExchangeOnline -CertificateThumbprint "<CERTIFICATE_THUMBPRINT>" -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 bucket | 分鐘至小時 | 中 |
選項 1:透過 Webhook 擷取
如果您有可將含有訊息追蹤資料的 HTTP POST 要求傳送至 Google SecOps 的指令碼或應用程式,請使用這個方法。
在 Google SecOps 中建立 Webhook 動態饋給
建立動態饋給
- 依序前往「SIEM 設定」>「動態饋給」。
- 按一下「新增動態消息」。
- 在下一個頁面中,按一下「設定單一動態饋給」。
- 在「動態饋給名稱」欄位中輸入動態饋給名稱 (例如
Office 365 Message Trace - Webhook)。 - 選取「Webhook」做為「來源類型」。
- 選取「Office 365 Message Trace」做為「記錄類型」。
- 點選「下一步」。
- 指定下列輸入參數的值:
- 分割分隔符號 (選用):輸入
\n,分割以換行符號分隔的 JSON 事件 - 資產命名空間:資產命名空間
- 擷取標籤:要套用至這個動態饋給事件的標籤
- 分割分隔符號 (選用):輸入
- 點選「下一步」。
- 在「Finalize」(完成) 畫面中檢查新的動態饋給設定,然後按一下「Submit」(提交)。
產生並儲存密鑰
建立動態饋給後,您必須產生驗證用的密鑰:
- 在動態饋給詳細資料頁面中,按一下「產生密鑰」。
- 對話方塊會顯示密鑰。
複製並妥善儲存密鑰。
取得動態消息端點網址
- 前往動態消息的「詳細資料」分頁。
- 在「端點資訊」部分,複製「動態消息端點網址」。
網址格式為:
https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate或
https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate請儲存這個網址,以供後續步驟使用。
按一下 [完成]。
建立 Google Cloud API 金鑰
Google SecOps 需要 API 金鑰才能進行驗證。在 Google Cloud 控制台中建立受限制的 API 金鑰。
建立 API 金鑰
- 前往 Google Cloud 控制台的「憑證」頁面。
- 選取專案 (與 Google SecOps 執行個體相關聯的專案)。
- 依序按一下「建立憑證」>「API 金鑰」。
- 系統會建立 API 金鑰,並顯示在對話方塊中。
- 按一下「編輯 API 金鑰」即可限制金鑰。
限制 API 金鑰
- 在「API 金鑰」設定頁面中:
- 名稱:輸入描述性名稱 (例如
Google SecOps Webhook API Key - O365 Message Trace)
- 名稱:輸入描述性名稱 (例如
- 在「API 限制」下方:
- 選取「Restrict key」(限制金鑰)。
- 在「選取 API」下拉式選單中,搜尋並選取「Google SecOps API」 (或「Chronicle API」)。
- 按一下 [儲存]。
- 從頁面頂端的「API key」(API 金鑰) 欄位複製 API 金鑰值。
安全地儲存 API 金鑰。
建立 Webhook 匯出指令碼
在設定匯出環境的電腦上,建立下列 PowerShell 指令碼。這項指令碼會從 Exchange Online 擷取郵件追蹤資料,並傳送至 Google SecOps Webhook 端點。
Windows
建立指令碼目錄:
mkdir C:\Scripts建立名為
C:\Scripts\messagetrace-webhook.ps1的檔案,並加入以下內容:# Configuration $endpointUrl = "https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate" $apiKey = "<API_KEY>" $secretKey = "<SECRET_KEY>" $certThumbprint = "<CERTIFICATE_THUMBPRINT>" $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://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate" $apiKey = "<API_KEY>" $secretKey = "<SECRET_KEY>" $certFilePath = "/opt/certs/messagetrace.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鍵。 - 點選右側窗格中的「Create Task」。
- 在「一般」分頁中:
- 「Name」(名稱):輸入
MessageTrace Webhook Export - 選取「無論使用者是否登入,都執行」
- 選取「以最高權限執行」
- 「Name」(名稱):輸入
- 在「Triggers」分頁中:
- 點選「New」(新增)。
- 將「Begin the task」設為「On a schedule」。
- 選取「每日」,將「開始」時間設為
12:00:00 AM(午夜,因此會以整點重複執行),然後設定「每 1 天重複一次」。 - 選取「每隔一段時間重複工作」
1 hour「無限期」。 - 選取 [已啟用]。
- 按一下 [確定]。
在「動作」分頁中:
- 點選「New」(新增)。
- 將「動作」設為「啟動程式」。
在「Program/script」(程式/指令碼) 欄位中輸入:
powershell.exe在「Add arguments」(新增引數) 欄位中輸入:
-NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\messagetrace-webhook.ps1"按一下 [確定]。
在「設定」分頁中:
- 選取「允許工作隨選執行」
- 取消勾選「如果工作執行時間超過」核取方塊
按一下「確定」,然後在系統提示時輸入服務帳戶憑證。
macOS
在
~/Library/LaunchAgents/com.chronicle.messagetrace-webhook.plist建立 launchd plist 檔案:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.chronicle.messagetrace-webhook</string> <key>ProgramArguments</key> <array> <string>/usr/local/bin/pwsh</string> <string>-NoProfile</string> <string>-File</string> <string>/opt/scripts/messagetrace-webhook.ps1</string> </array> <key>StartInterval</key> <integer>3600</integer> <key>StandardOutPath</key> <string>/var/log/messagetrace/launchd-stdout.log</string> <key>StandardErrorPath</key> <string>/var/log/messagetrace/launchd-stderr.log</string> <key>RunAtLoad</key> <true/> </dict> </plist>載入工作:
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 bucket
- 前往 Google Cloud 控制台。
- 選取專案或建立新專案。
- 在導覽選單中,依序前往「Cloud Storage」>「Bucket」。
- 按一下「建立值區」。
請提供下列設定詳細資料:
設定 值 為 bucket 命名 輸入全域不重複的名稱 (例如 office365-messagetrace-logs)位置類型 根據需求選擇 (區域、雙區域、多區域) 位置 選取位置 (例如 us-central1)儲存空間級別 標準 (建議用於經常存取的記錄) 存取控管 統一 (建議) 保護工具 選用:啟用物件版本管理或資料保留政策 點選「建立」。
安裝 Google Cloud CLI
在設定匯出環境的同一部電腦上安裝 Google Cloud CLI。gsutil 指令 (隨附於 Google Cloud CLI) 用於將檔案上傳至 GCS bucket。
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)
- 開啟具有根層級或 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)
- 開啟具有根層級或 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 bucket 的專案:
gcloud config set project <PROJECT_ID>將
<PROJECT_ID>替換為您的 Google Cloud 專案 ID。
如要無人值守 (排程) 使用,請使用服務帳戶金鑰進行驗證。匯出指令碼會使用這個服務帳戶,將檔案上傳至 GCS bucket。這與用於從值區讀取資料的 Google SecOps 服務帳戶不同 (在後續步驟中設定)。
- 前往 Google Cloud 控制台,然後選取您的專案。
- 按一下「Create Service Account」(建立服務帳戶)。
- 在「Service account name」(服務帳戶名稱) 欄位中輸入名稱 (例如
chronicle-gcs-export)。 - 按一下「建立並繼續」。
- 在「將專案存取權授予這個服務帳戶」部分,選取「Storage Object Creator」(Storage 物件建立者) 角色。
- 按一下 [完成]。
- 在服務帳戶清單中,按一下您建立的服務帳戶。
- 前往「金鑰」分頁標籤。
- 依序點選「新增金鑰」>「建立新的金鑰」。
- 選擇「JSON」然後按下 [Create] (建立)。
- 儲存下載的 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 = "<CERTIFICATE_THUMBPRINT>" $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 bucket 名稱
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 bucket 名稱
設定檔案權限:
sudo chmod 700 /opt/scripts/messagetrace-gcs.ps1
排定 GCS 匯出指令碼
Windows
- 開啟「工作排程器」:按下
Win+R鍵,輸入taskschd.msc,然後按下Enter鍵。 - 點選右側窗格中的「Create Task」。
- 在「一般」分頁中:
- 「Name」(名稱):輸入
MessageTrace GCS Export - 選取「無論使用者是否登入,都執行」
- 選取「以最高權限執行」
- 「Name」(名稱):輸入
- 在「Triggers」分頁中:
- 點選「New」(新增)。
- 將「Begin the task」設為「On a schedule」。
- 選取「每日」,將「開始」時間設為
12:00:00 AM(午夜,因此會以整點重複執行),然後設定「每 1 天重複一次」。 - 選取「每隔一段時間重複工作」
1 hour「無限期」。 - 選取 [已啟用]。
- 按一下 [確定]。
在「動作」分頁中:
- 點選「New」(新增)。
- 將「動作」設為「啟動程式」。
在「Program/script」(程式/指令碼) 欄位中輸入:
powershell.exe在「Add arguments」(新增引數) 欄位中輸入:
-NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\messagetrace-gcs.ps1"按一下 [確定]。
在「設定」分頁中:
- 選取「允許工作隨選執行」
- 取消勾選「如果工作執行時間超過」核取方塊
按一下「確定」,然後在系統提示時輸入服務帳戶憑證。
macOS
在
~/Library/LaunchAgents/com.chronicle.messagetrace-gcs.plist建立 launchd plist 檔案:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.chronicle.messagetrace-gcs</string> <key>ProgramArguments</key> <array> <string>/usr/local/bin/pwsh</string> <string>-NoProfile</string> <string>-File</string> <string>/opt/scripts/messagetrace-gcs.ps1</string> </array> <key>StartInterval</key> <integer>3600</integer> <key>StandardOutPath</key> <string>/var/log/messagetrace/launchd-gcs-stdout.log</string> <key>StandardErrorPath</key> <string>/var/log/messagetrace/launchd-gcs-stderr.log</string> <key>RunAtLoad</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 bucket:
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 設定」>「動態饋給」。
- 按一下「新增動態消息」。
- 按一下「設定單一動態饋給」。
- 在「動態饋給名稱」欄位中輸入動態饋給名稱 (例如
Office 365 Message Trace - GCS)。 - 選取「Google Cloud Storage V2」做為「來源類型」。
- 選取「Office 365 Message Trace」做為「記錄類型」。
- 按一下「取得服務帳戶」。
系統會顯示專屬服務帳戶電子郵件地址,例如:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com複製這個電子郵件地址,以便在下一步中使用。
授予 IAM 權限
- 依序前往「Cloud Storage」>「Buckets」。
- 點按 bucket 名稱。
- 前往「權限」分頁標籤。
- 按一下「授予存取權」。
- 請提供下列設定詳細資料:
- 新增主體:貼上 Google SecOps 服務帳戶電子郵件地址
- 指派角色:選取「Storage 物件檢視者」
按一下 [儲存]。
為 GCS 設定 Google SecOps 資訊提供
- 從動態消息建立頁面繼續操作 (或依序前往「SIEM 設定」>「動態消息」>「新增動態消息」)。
- 點選「下一步」。
指定下列輸入參數的值:
儲存空間 bucket URL:輸入 GCS bucket URI,並加上前置路徑:
gs://office365-messagetrace-logs/messagetrace/
- 來源刪除選項:根據偏好選取刪除選項:
- 永不:永不刪除移轉後的任何檔案 (建議用於測試)
- 刪除轉移的檔案:成功轉移檔案後刪除檔案
- 刪除已轉移的檔案和空白目錄:成功轉移後刪除檔案和空白目錄
- 檔案存在時間上限:包含在過去天數內修改的檔案 (預設為 180 天)
- 資產命名空間:資產命名空間
- 擷取標籤:要套用至這個動態饋給事件的標籤
點選「下一步」。
在「Finalize」(完成) 畫面中檢查新的動態饋給設定,然後按一下「Submit」(提交)。
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 專業人員尋求答案。