收集 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 PowerShell 5.1 随附于 Windows 10、Windows 11 和 Windows Server 2016 或更高版本。无需进行额外安装。

  • 如需验证 PowerShell 版本,请打开 PowerShell 并运行以下命令:

    $PSVersionTable.PSVersion
    
  • (可选)如需安装 PowerShell 7 以提高性能,请以管理员身份打开命令提示符PowerShell,然后运行:

    winget install --id Microsoft.PowerShell --source winget
    

macOS

  1. 安装 Homebrew(如果尚未安装)。
  2. 打开终端并运行以下命令:

    brew install powershell/tap/powershell
    
  3. 运行以下命令,验证安装是否成功:

    pwsh --version
    

    输出应显示 PowerShell 7.x.x 或更高版本。

Linux(Debian/Ubuntu)

  1. 打开具有 root 或 sudo 权限的终端。
  2. 运行以下命令:

    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
    
  3. 运行以下命令,验证安装是否成功:

    pwsh --version
    

Linux (RHEL/CentOS/Fedora)

  1. 打开具有 root 或 sudo 权限的终端。
  2. 注册 Microsoft 代码库:

    curl "https://packages.microsoft.com/config/rhel/$(rpm -E %rhel)/prod.repo" | sudo tee /etc/yum.repos.d/microsoft.repo
    
  3. 安装 PowerShell:

    sudo dnf install -y powershell
    
  4. 运行以下命令,验证安装是否成功:

    pwsh --version
    

安装 Exchange Online PowerShell 模块

安装 PowerShell 后,安装 Exchange Online 管理模块。此步骤在所有平台上的操作都相同。

  1. 启动 PowerShell:

    • Windows:以管理员身份打开 PowerShellPowerShell 7
    • macOS 和 Linux:打开终端并运行 pwsh
  2. 运行以下命令:

    Install-Module -Name ExchangeOnlineManagement -Scope CurrentUser -Force
    
  3. 如果系统提示您从不受信任的代码库 (PSGallery) 进行安装,请输入 Y 以确认。

  4. 运行以下命令,验证安装是否成功:

    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 中注册应用

  1. 登录 Microsoft Entra 管理中心
  2. 依次前往身份 > 应用 > 应用注册
  3. 点击 New registration(新注册)。
  4. 提供以下配置详细信息:
    • 名称:输入 MessageTraceExport
    • 支持的账号类型:选择仅此组织目录中的账号
  5. 点击注册
  6. 在应用概览页面上,复制并保存应用(客户端)ID
  7. 从概览页面复制目录(租户)ID 并保存。

将证书上传到应用

  1. 在应用页面上,依次前往证书和密钥 > 证书
  2. 点击上传证书
  3. 上传证书文件:
    • Windows:上传 C:\Certs\MessageTraceExport.cer
    • macOS 和 Linux:上传 /opt/certs/messagetrace-cert.pem
  4. 点击 Add(添加)。

分配 API 权限

导出脚本会运行 Get-MessageTraceV2 cmdlet,该 cmdlet 需要两项 Office 365 Exchange Online 应用权限:Exchange.ManageAsApp(用于以应用身份进行身份验证)和 ReportingWebService.Read.All(用于读取邮件跟踪数据)。如果缺少 ReportingWebService.Read.All,脚本会失败并显示 403 The caller does not have permission 错误。

  1. 在应用页面上,前往 API 权限
  2. 点击添加权限
  3. 选择组织使用的 API
  4. 搜索并选择 Office 365 Exchange Online
  5. 选择应用权限
  6. 添加以下两项权限:
    • 展开 Exchange,然后选择 Exchange.ManageAsApp
    • 展开 ReportingWebService,然后选择 ReportingWebService.Read.All
  7. 点击添加权限
  8. 点击为 <您的组织> 授予管理员同意书,然后确认。

分配 Exchange 管理员角色

  1. 在 Microsoft Entra 管理中心内,依次前往身份 > 角色和管理员 > 所有角色
  2. 搜索并选择 Exchange 管理员
  3. 点击添加分配
  4. 点击未选择任何成员,然后搜索 MessageTraceExport 应用。
  5. 选择相应申请,然后点击下一步
  6. 选择有效作为分配类型。
  7. 点击分配

验证无人值守连接

启动 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:$false
    
  • macOS 和 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 提取

如果您有脚本或应用可以向 Google SecOps 发送包含消息跟踪数据的 HTTP POST 请求,请使用此方法。

在 Google SecOps 中创建 Webhook Feed

创建 Feed

  1. 依次前往 SIEM 设置 > Feed
  2. 点击添加新 Feed
  3. 在下一页上,点击配置单个 Feed
  4. Feed 名称字段中,输入 Feed 的名称(例如 Office 365 Message Trace - Webhook)。
  5. 选择 Webhook 作为来源类型
  6. 选择 Office 365 邮件跟踪作为日志类型
  7. 点击下一步
  8. 为以下输入参数指定值:
    • 定界符(可选):输入 \n 以拆分以换行符分隔的 JSON 事件
    • 资产命名空间资产命名空间
    • 注入标签:要应用于此 Feed 中事件的标签
  9. 点击下一步
  10. 最终确定界面中查看新的 Feed 配置,然后点击提交

生成并保存密钥

创建 Feed 后,您必须生成用于身份验证的密钥:

  1. 在 Feed 详情页面上,点击生成密钥
  2. 系统会显示一个对话框,其中包含密钥。
  3. 复制并妥善保存此密钥。

获取 Feed 端点网址

  1. 前往相应 Feed 的详细信息标签页。
  2. 端点信息部分,复制 Feed 端点网址
  3. 网址格式为:

    https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    

    https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    
  4. 保存此网址以供后续步骤使用。

  5. 点击完成

创建 Google Cloud API 密钥

Google SecOps 需要使用 API 密钥进行身份验证。在 Google Cloud Console 中创建受限 API 密钥。

创建 API 密钥

  1. 前往 Google Cloud 控制台的“凭据”页面
  2. 选择您的项目(与您的 Google SecOps 实例关联的项目)。
  3. 依次点击创建凭据> API 密钥
  4. 系统会创建一个 API 密钥,并在对话框中显示该密钥。
  5. 点击修改 API 密钥以限制密钥。

限制 API 密钥

  1. API 密钥设置页面中:
    • 名称:输入一个描述性名称(例如 Google SecOps Webhook API Key - O365 Message Trace
  2. API 限制下:
    1. 选择限制密钥
    2. 选择 API 下拉菜单中,搜索并选择 Google SecOps API(或 Chronicle API)。
  3. 点击保存
  4. 从页面顶部的 API 密钥字段复制 API 密钥值。
  5. 安全地保存 API 密钥。

创建 webhook 导出脚本

在设置了导出环境的机器上创建以下 PowerShell 脚本。此脚本从 Exchange Online 检索邮件跟踪数据,并将其发送到 Google SecOps 网络钩子端点。

Windows

  1. 创建脚本目录:

    mkdir C:\Scripts
    
  2. 创建一个名为 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
    }
    
  3. 替换占位值:

    • <API_KEY>:Google Cloud API 密钥
    • <SECRET_KEY>:Google SecOps 网络钩子密钥
    • <CERTIFICATE_THUMBPRINT>:身份验证设置中的证书指纹
    • <APPLICATION_ID>:Azure AD 应用(客户端)ID
    • yourdomain.onmicrosoft.com:您的 Microsoft 365 租户网域

macOS 和 Linux

  1. 创建脚本目录:

    sudo mkdir -p /opt/scripts
    sudo mkdir -p /var/log/messagetrace
    
  2. 创建一个名为 /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
    }
    
  3. 替换占位值:

    • <API_KEY>:Google Cloud API 密钥
    • <SECRET_KEY>:Google SecOps 网络钩子密钥
    • <APPLICATION_ID>:Azure AD 应用(客户端)ID
    • yourdomain.onmicrosoft.com:您的 Microsoft 365 租户网域
  4. 设置文件权限:

    sudo chmod 700 /opt/scripts/messagetrace-webhook.ps1
    

安排导出脚本

将脚本配置为定期自动运行(例如每小时运行一次)。

Windows

  1. 打开任务计划程序:按 Win+R,输入 taskschd.msc,然后按 Enter
  2. 在右侧窗格中,点击创建任务
  3. 常规标签页上:
    • 名称:输入 MessageTrace Webhook Export
    • 选择无论用户是否已登录,都运行
    • 选择以最高权限运行
  4. 触发器标签页上:
    1. 点击 New(新建)。
    2. 开始任务设置为按计划
    3. 选择每天,将开始时间设置为 12:00:00 AM(午夜,以便按整点重复),然后设置每 1 天重复一次
    4. 选择1 hour重复一次任务,持续时间为无限期
    5. 选择已启用
    6. 点击确定
  5. 操作标签页上:

    1. 点击 New(新建)。
    2. 操作设置为启动程序
    3. 程序/脚本字段中,输入:

      powershell.exe
      
    4. 添加实参字段中,输入:

      -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\messagetrace-webhook.ps1"
      
    5. 点击确定

  6. 设置标签页中:

    • 选择允许按需运行任务
    • 清除如果任务运行时间超过复选框
  7. 点击确定,然后在系统提示时输入服务账号凭据。

macOS

  1. ~/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>
    
  2. 加载作业:

    launchctl load ~/Library/LaunchAgents/com.chronicle.messagetrace-webhook.plist
    
  3. 验证作业是否已加载:

    launchctl list | grep messagetrace
    

Linux

  1. 打开 crontab 编辑器:

    crontab -e
    
  2. 添加以下代码行,以便每小时运行一次脚本:

    0 * * * * /usr/bin/pwsh -NoProfile -File /opt/scripts/messagetrace-webhook.ps1 >> /var/log/messagetrace/cron.log 2>&1
    
  3. 保存并退出编辑器。

  4. 验证 Cron 作业是否已注册:

    crontab -l
    

验证日志注入

  1. 手动运行脚本以进行测试:

    Windows

    powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\messagetrace-webhook.ps1"
    

    macOS 和 Linux

    pwsh -NoProfile -File /opt/scripts/messagetrace-webhook.ps1
    
  2. 检查日志文件是否存在错误:

    Windows

    Get-Content "C:\Logs\messagetrace-webhook.log" -Tail 10
    

    macOS 和 Linux

    tail -10 /var/log/messagetrace/messagetrace-webhook.log
    
  3. 在 Google SecOps 中,前往搜索,并验证是否显示了带有 metadata.log_type = "OFFICE_365_MESSAGETRACE" 的日志。

方案 2:Google Cloud Storage V2 提取

如果导出脚本将消息跟踪日志写入 Google Cloud Storage 存储桶,请使用此方法。

创建 GCS 存储桶

  1. 前往 Google Cloud 控制台
  2. 选择您的项目或创建新项目。
  3. 在导航菜单中,依次前往 Cloud Storage > 存储分区
  4. 点击创建存储分区
  5. 提供以下配置详细信息:

    设置
    为存储桶命名 输入一个全局唯一的名称(例如 office365-messagetrace-logs
    位置类型 根据您的需求进行选择(区域级、双区域、多区域)
    位置 选择营业地点(例如 us-central1
    存储类别 标准(建议用于经常访问的日志)
    访问权限控制 均匀(推荐)
    保护工具 可选:启用对象版本控制或保留政策
  6. 点击创建

安装 Google Cloud CLI

在设置导出环境的同一台机器上安装 Google Cloud CLI。gsutil 命令(随 Google Cloud CLI 一起提供)用于将文件上传到 GCS 存储桶。

Windows

  1. 下载 Google Cloud CLI 安装程序 (GoogleCloudSDKInstaller.exe)。
  2. 运行 GoogleCloudSDKInstaller.exe。在安装选项界面上,保留默认选择。点击安装。安装完成后,保持选中运行 gcloud init,然后点击完成
  3. 打开命令提示符并运行以下命令,验证安装是否成功:

    gcloud --version
    gsutil --version
    

macOS

  1. 打开终端并运行以下命令:

    brew install google-cloud-sdk
    
  2. 验证安装:

    gcloud --version
    gsutil --version
    

Linux(Debian/Ubuntu)

  1. 打开具有 root 或 sudo 权限的终端。
  2. 运行以下命令:

    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
    
  3. 验证安装:

    gcloud --version
    gsutil --version
    

Linux (RHEL/CentOS/Fedora)

  1. 打开具有 root 或 sudo 权限的终端。
  2. 创建代码库文件:

    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
    
  3. 安装 Google Cloud CLI:

    sudo dnf install -y google-cloud-cli
    
  4. 验证安装:

    gcloud --version
    gsutil --version
    

对 Google Cloud CLI 进行身份验证

  1. 运行以下命令进行身份验证:

    gcloud auth login
    
  2. 设置包含您的 GCS 存储桶的项目:

    gcloud config set project <PROJECT_ID>
    

    <PROJECT_ID> 替换为您的 Google Cloud 项目 ID。

对于无人值守(已安排)的使用,请使用服务账号密钥进行身份验证。导出脚本使用此服务账号将文件上传到 GCS 存储桶。它与用于从存储桶读取数据的 Google SecOps 服务账号(在后续步骤中配置)是分开的。

  1. 前往 Google Cloud 控制台,然后选择您的项目。
  2. 点击创建服务账号
  3. 服务账号名称字段中,输入一个名称(例如 chronicle-gcs-export)。
  4. 点击创建并继续
  5. 向此服务账号授予对项目的访问权限部分,选择 Storage Object Creator 角色。
  6. 点击完成
  7. 在服务账号列表中,点击您创建的服务账号。
  8. 前往密钥标签页。
  9. 点击添加密钥 > 创建新密钥
  10. 选择 JSON,然后点击创建
  11. 保存下载的 JSON 密钥文件:
    • WindowsC:\Certs\gcs-service-account.json
    • macOS 和 Linux/opt/certs/gcs-service-account.json
  12. 激活服务账号:

    gcloud auth activate-service-account --key-file=<PATH_TO_KEY_FILE>
    

创建 GCS 导出脚本

Windows

  1. 创建一个名为 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
    }
    
  2. 替换占位值:

    • <CERTIFICATE_THUMBPRINT>:身份验证设置中的证书指纹
    • <APPLICATION_ID>:Azure AD 应用(客户端)ID
    • yourdomain.onmicrosoft.com:您的 Microsoft 365 租户网域
    • office365-messagetrace-logs:您的 GCS 存储桶名称

macOS 和 Linux

  1. 创建一个名为 /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
    }
    
  2. 替换占位值:

    • <APPLICATION_ID>:Azure AD 应用(客户端)ID
    • yourdomain.onmicrosoft.com:您的 Microsoft 365 租户网域
    • office365-messagetrace-logs:您的 GCS 存储桶名称
  3. 设置文件权限:

    sudo chmod 700 /opt/scripts/messagetrace-gcs.ps1
    

安排 GCS 导出脚本

Windows

  1. 打开任务计划程序:按 Win+R,输入 taskschd.msc,然后按 Enter
  2. 在右侧窗格中,点击创建任务
  3. 常规标签页上:
    • 名称:输入 MessageTrace GCS Export
    • 选择无论用户是否已登录,都运行
    • 选择以最高权限运行
  4. 触发器标签页上:
    1. 点击 New(新建)。
    2. 开始任务设置为按计划
    3. 选择每天,将开始时间设置为 12:00:00 AM(午夜,以便按整点重复),然后设置每 1 天重复一次
    4. 选择1 hour重复一次任务,持续时间为无限期
    5. 选择已启用
    6. 点击确定
  5. 操作标签页上:

    1. 点击 New(新建)。
    2. 操作设置为启动程序
    3. 程序/脚本字段中,输入:

      powershell.exe
      
    4. 添加实参字段中,输入:

      -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\messagetrace-gcs.ps1"
      
    5. 点击确定

  6. 设置标签页中:

    • 选择允许按需运行任务
    • 清除如果任务运行时间超过复选框
  7. 点击确定,然后在系统提示时输入服务账号凭据。

macOS

  1. ~/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>
    
  2. 加载作业:

    launchctl load ~/Library/LaunchAgents/com.chronicle.messagetrace-gcs.plist
    
  3. 验证作业是否已加载:

    launchctl list | grep messagetrace
    

Linux

  1. 打开 crontab 编辑器:

    crontab -e
    
  2. 添加以下代码行,以便每小时运行一次脚本:

    0 * * * * /usr/bin/pwsh -NoProfile -File /opt/scripts/messagetrace-gcs.ps1 >> /var/log/messagetrace/cron-gcs.log 2>&1
    
  3. 保存并退出编辑器。

  4. 验证 Cron 作业是否已注册:

    crontab -l
    

验证 GCS 上传

  1. 手动运行脚本以进行测试:

    Windows

    powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\messagetrace-gcs.ps1"
    

    macOS 和 Linux

    pwsh -NoProfile -File /opt/scripts/messagetrace-gcs.ps1
    
  2. 验证文件是否已上传到 GCS 存储桶:

    gsutil ls gs://office365-messagetrace-logs/messagetrace/
    
  3. 检查日志文件是否存在错误:

    Windows

    Get-Content "C:\Logs\messagetrace-gcs.log" -Tail 10
    

    macOS 和 Linux

    tail -10 /var/log/messagetrace/messagetrace-gcs.log
    

获取 Google SecOps 服务账号

  1. 依次前往 SIEM 设置 > Feed
  2. 点击添加新 Feed
  3. 点击配置单个 Feed
  4. Feed 名称字段中,输入 Feed 的名称(例如 Office 365 Message Trace - GCS)。
  5. 选择 Google Cloud Storage V2 作为来源类型
  6. 选择 Office 365 邮件跟踪作为日志类型
  7. 点击获取服务账号
  8. 系统会显示一个唯一的服务账号电子邮件地址,例如:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  9. 复制此电子邮件地址,以便在下一步中使用。

授予 IAM 权限

  1. 前往 Cloud Storage > 存储分区
  2. 点击您的存储桶名称。
  3. 前往权限标签页。
  4. 点击授予访问权限
  5. 提供以下配置详细信息:
    • 添加主账号:粘贴 Google SecOps 服务账号电子邮件地址
    • 分配角色:选择 Storage Object Viewer
  6. 点击保存

为 GCS 配置 Google SecOps Feed

  1. 从 Feed 创建页面继续操作(或前往 SIEM 设置 > Feed > 添加新 Feed)。
  2. 点击下一步
  3. 为以下输入参数指定值:

    • 存储桶网址:输入带有前缀路径的 GCS 存储桶 URI:

      gs://office365-messagetrace-logs/messagetrace/
      
    • 来源删除选项:根据您的偏好选择删除选项:
      • 永不:转移后永不删除任何文件(建议用于测试)
      • 删除已转移的文件:在成功转移后删除文件
      • 删除已转移的文件和空目录:成功转移后删除文件和空目录
    • 文件存在时间上限:包含在过去指定天数内修改的文件(默认值为 180 天)
    • 资产命名空间资产命名空间
    • 注入标签:要应用于此 Feed 中事件的标签
  4. 点击下一步

  5. 最终确定界面中查看新的 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.ipevent.idm.read_only_udm.principal.asset.ip之间 从变更日志映射
toIP event.idm.read_only_udm.target.ipevent.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 专业人士的解答。