You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PowerShell运行合规搜索无结果,疑权限问题求助

问题排查:应用注册执行合规搜索无结果但用户凭据正常

使用Azure应用注册执行PowerShell合规搜索脚本时,脚本无报错但Purview中的内容搜索无结果;使用用户凭据执行则完全正常,怀疑是权限问题但无法定位,恳请协助排查。

完整脚本

# Get Primary Domain Controller (PDC) Server
$pdc = (Get-ADForest | Select-Object -ExpandProperty RootDomain | Get-ADDomain | Select-Object -Property PDCEmulator).PDCEmulator
# Set Destination Varibales for Output Files
$Root_Disk = "Z:"
$PSTArchive = "$($Root_Disk)\PSTArchive"
$SharePath = ""
if (!(Test-Path $PSTArchive)) { New-Item $PSTArchive -ItemType Directory }
$Time = (Get-Date).ToString("yyyyMMddhhmm")
#################################################################################################
# Setup Output Logging
#################################################################################################
# Gets the current date and formats it to Year Month Day Hour Minute format as a time stamp
$time = (Get-Date).ToString("yyyyMMddhhmm")
[string]$script_name = $myInvocation.MyCommand
[string]$script_name
# Checks if path exist if not creates the directory
if (!(Test-Path "C:\scripts\log")) { New-Item "C:\scripts\log" -ItemType Directory }
#specify Log path
$log_directory = "C:\scripts\log\$(($script_name).Substring(0,(($script_name).length-4)))"
# Creates directory if it doesn't exists
if (!(Test-Path $log_directory)) { New-Item -Path $log_directory -ItemType Directory }  
# This sets the default path to C:\scripts\logs\script_name-datetime.log
Write-Host "Default Log file is $($log_directory)-$($time).log"
$log_path = "$($log_directory)-$($time).log"
# Logs all output to log path
Start-Transcript $log_path
Write-Host "

"
Write-Host ([Environment]::UserDomainName + "\" + [Environment]::UserName) " Executed the script at $(Get-Date)`n`n"
#################################################################################################
#################################################################################################
# Set OU path to target employees
$Terminated_Users_OU = ""
# Get terminanted users from AD with extensionAttribute4 set to null
$TerminatedUsers = Get-ADUser -properties extensionAttribute4, enabled -Filter { enabled -eq $false -and -not(extensionAttribute4 -like "*") } -SearchBase $Terminated_Users_OU | Select-Object -First 5
# Connect to Exchange Online
Import-Module ExchangeOnlineManagement
$tenant_name = ""
$app_id = ""
$certificate_thumbprint = ""
Write-Host "Connecting to Exchange Online`n`n" 
Connect-ExchangeOnline -CertificateThumbprint $certificate_thumbprint -AppId $app_id -Organization $tenant_name
Write-Host "Connect to Exhcnage Security `n`n"
Connect-IPPSSession -AppId $app_id -CertificateThumbprint $certificate_thumbprint -Organization $tenant_name
$connection_id = (Get-ConnectionInformation).ConnectionId
# Loop through each terminated user
foreach ($user in $TerminatedUsers) 
{
    # Use Try catch to check for emails
    try
    {
        Get-EXOMailbox -Identity $user.UserPrincipalName -ErrorAction Stop
        # Create PST file name with users UPN
        $Formatted_User_Name = ($user.UserPrincipalName).Substring(0, ($user.UserPrincipalName).indexof("@") - 1)
        # $PSTFileName = "$($user.UserPrincipalName.Replace("@","_"))_Archive.pst"
        $PSTFileName = "$($Formatted_User_Name)_$($Time)_Archive.pst"
        $PSTFilePath = Join-Path -Path $PSTArchive -ChildPath $PSTFileName
        # Start Client Search 
        # Export mailbox to PST file
        try
        {
            Write-Host "Exporting Mailbox to pst for $($user.UserPrincipalName) `n`n"
            #New-MailboxExportRequst -Mailbox $user.UserPrincipalName -FilePath $PSTFilePath -ErrorAction Stop
            
            New-ComplianceSearch "$($user.SamAccountName)_archive_box" -exchangelocation $user.UserPrincipalName | Start-ComplianceSearch 
            Get-ADUser $user.SamAccountName | Set-ADObject -Server $pdc -Replace @{extensionAttribute4 = "Exported" }
        }
        catch
        {
            # Do not flag the user as Exported since the job didn't complete
            Write-Host "Exception happened `n`n"
        }
    }
    catch
    {
        # Flag the user for NoMailBox since it can't be found in exchange online
        Write-Host "User: $($user.UserPrincipalName) has no mailbox"
        Get-ADUser $user.SamAccountName | Set-ADObject -Server $pdc -Replace @{extensionAttribute4 = "NoMailBox" }
    }
}
# Move PST files to designated path
$PSTs = Get-ChildItem -Path $PSTArchive -File
Write-Host "Moving $($PSTs.count) PST Files`n"
foreach ($PST in $PSTs.FullName)
{
    Write-Host "Moving $($PST.FullName) to $($SharePath)`n`n"
    Move-Item -Path $PST -Destination $SharePath -Force
}
# Disconnect from Exchange Online
Write-Host "Disconnecting Session From Exchange Online`n"
Disconnect-ExchangeOnline -ConnectionId $connection_id -Confirm:$false
Stop-Transcript

排查方向

  • 应用注册权限配置:
    • 确认应用已添加Exchange Online的应用权限:Mail.Read、MailboxSettings.Read,且已获取管理员同意。
    • 确认应用已添加Office 365 Security & Compliance的应用权限:ComplianceSearch.Read.All、ComplianceSearch.Write.All、Ediscovery.Read.All,且已获取管理员同意。
  • Exchange角色分配:
    • 应用注册需被分配邮箱导入导出角色和合规搜索角色,执行以下命令验证:
      Get-ManagementRoleAssignment -RoleAssignee "<应用注册显示名称>"
      
  • 搜索状态验证:
    • 脚本执行后,运行Get-ComplianceSearch -Identity "<搜索名称>"查看搜索状态、结果数,确认是搜索完成但无结果,还是搜索未正常执行。
  • 脚本逻辑修正:
    • 当前脚本创建搜索后立即标记用户为已导出,但Start-ComplianceSearch是异步操作,需等待搜索完成再判断结果。可添加等待逻辑:
      $search = New-ComplianceSearch "$($user.SamAccountName)_archive_box" -exchangelocation $user.UserPrincipalName
      $search | Start-ComplianceSearch
      # 循环等待搜索完成
      do {
          Start-Sleep -Seconds 30
          $search = Get-ComplianceSearch $search.Name
          Write-Host "当前搜索状态:$($search.Status)"
      } while ($search.Status -notin "Completed", "Failed")
      
      # 根据结果数处理
      if ($search.Items -eq 0) {
          Write-Host "用户$($user.UserPrincipalName)的合规搜索未找到内容"
          # 可调整标记为无结果状态
          Get-ADUser $user.SamAccountName | Set-ADObject -Server $pdc -Replace @{extensionAttribute4 = "NoSearchResults" }
      } else {
          Get-ADUser $user.SamAccountName | Set-ADObject -Server $pdc -Replace @{extensionAttribute4 = "Exported" }
      }
      
  • 证书与连接验证:
    • 确认执行脚本的机器已导入正确的证书,证书指纹与应用注册配置一致,且证书在有效期内。
    • 验证Connect-IPPSSession连接是否成功,运行Get-ConnectionInformation查看会话状态。

内容的提问来源于stack exchange,提问作者cmeader1053

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 15:44:52