使用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 Online的应用权限:
- 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
相关产品推荐
相关产品推荐

