How to run a (targeted) compliance search for specific Exchange inboxes or OneDrive+SharePoint sites with PowerShell - Part 1
Archived post · originally published · may be out of date
Intro
I recently had to perform a compliance search that required me to target a particular department that included their users, SharePoint sites, and any other mailboxes or content associated with this department (including Shared Mailboxes). If you have previously used the Compliance Search web GUI, it becomes quickly apparent that using the web GUI is an arduous experience as it is slow to use and even more time consuming when selecting individual mailboxes and SharePoint sites especially in a large organization that has hundreds to thousands of such items. Like all good System Administrators, I turned to PowerShell to help streamline my search.
If you are like me you found the following guide and script from Microsoft (Use Content Search to search the mailbox and OneDrive site for a list of users) and unfortunately, also like me, you found that the provided script from Microsoft does not work due to authentication errors caused by MFA being enabled on your account[1]. Instead of reworking Microsoft's script to work with MFA access, I have decided to make a new script that utilizes the PnP PowerShell module instead of the SharePoint Online Management Shell. Secondly, there are issues with the New-ComplianceSearch cmdlet itself.
The Secret
The New-ComplianceSearch documentation provides incorrect information specifically in regard to the -ExchangeLocation and -SharePointLocation parameters with this comment being the source of the problem:
You can enter multiple values separated by commas. If the values contain spaces or otherwise require quotation marks, use the following syntax: `"Value1","Value2",..."ValueN"`.
The correct way to provide multiple mailboxes to the -ExchangeLocation parameter and multiple OneDrive or SharePoint sites to the -SharePointLocation is to use an array, and not to use multiple values all separated by commas as stated by Microsoft. So create an array, populate it with the content you wish to search, and then provide that variable to the New-ComplianceSearch cmdlet either under the -ExchangeLocation or -SharePointLocation parameters depending on what you are searching.
For example, let's say you have 100 specific mailboxes you would like to search then your array variable in PowerShell would look like this:
# Import CSV file
$Mailboxes = Import-Csv .\Mailboxes.csv
#Initialize the array
$ExchangeLocations = @()
#Loop through each item in the CSV to populate the array
foreach ($Mailbox in $Mailboxes) {
$ExchangeLocations += $Mailbox.User
}
The results of $ExchangeLocations will produce the following output below:
User1@owltec.ca
user2@owltec.ca
User3@owltec.ca
.
.
User99@owltec.ca
User100@owltec.ca
After you have confirmed that your array has a proper list of all your required information then provide it to the New-ComplianceSearch cmdlet. For the example we previously used, the final result to create a search would be New-ComplianceSearch -ExchangeLocation $ExchangeLocations.
However, if you do follow Microsoft's guidance and your variable expresses its multiple values as separated by commas (or you just paste in a list of your values separated by commas) then it will not work as the search itself will either contain only one entry or will be blank altogether in the Purview Portal GUI.
User1@owltec.ca,User2@owltec.ca,User3@owltec.ca,..User99@owltec.ca,User100@owltec.ca
The Script
My script was originally designed to create three different compliance searches based on each location (Exchange, OneDrive, and SharePoint) with each portion shared below. Based on my requirements, my script is three separate and self-contained parts that I manually select, tweak and run based on my search requirements; feel free to combine all three parts together to make a more complete script that creates one compliance search.
Prerequisites
- Latest version of PowerShell 7 (7.4.5.0 in my case)
- Install the Exchange Online Management module
Install-Module -Name ExchangeOnlineManagement
- This section is only required to find
PersonalUrlsfor user OneDrives so you can skip this section if you are just searching in Exchange or SharePoint or you already have a list ofPersonalUrlsfor your OneDrive users-
Install the latest PnP-Powershell module
Install-Module -name PnP.PowerShell
-
A registered PnP Entra ID application
-
Connecting to SharePoint via
Connect-PnPOnline -interactivewill result in the following error:WARNING: Connecting with -Interactive used the PnP Management Shell multi-tenant App Id for authentication. As of September 9th, 2024 this option is not available anymore. Refer to https://pnp.github.io/powershell/articles/registerapplication.html on how to register your own application. -
The solution? Very straightforward, just run this command to create your own registered application (make sure to save the
clientIDproduced by this command as we will use this later). When you run this command, it will take you to a sign-on page, then provide your credentials, provide consent, and then the script will create the Entra ID application (the default permissions that are used are perfectly fine for us):Register-PnPEntraIDAppForInteractiveLogin -ApplicationName "PnP Rocks" -Tenant [yourtenant].onmicrosoft.com -Interactive
-
-
- A CSV file containing the list of users you would like to search in Exchange and OneDrive
- Here is the format I used (only one column):
| User |
|---|
| user1@owltec.ca |
| user2@owltec.ca |
| user3@owltec.ca |
- A CSV file containing your list of SharePoint sites you would like to search in SharePoint
- Here is the format I used (only one column):
| URL |
|---|
| https://[yourtenant].onmicrosoft.com/sites/Site1 |
| https://[yourtenant].onmicrosoft.com/sites/Site2 |
| https://[yourtenant].onmicrosoft.com/sites/Site3 |
Exchange
<#
Exchange Search
#>
$SearchName = Read-Host -Prompt "What is the name of your search?"
$Criteria = [YOUR SEARCH CRITERIA]
# Connect to Microsoft Purview
Connect-IPPSSession
# Import CSV file
$Mailboxes = Import-Csv -path [PATHTOYOURCSVFILE]
#Initialize the array
$ExchangeLocations = @()
#Loop through each item in the CSV to populate the array
foreach ($Mailbox in $Mailboxes) {
$ExchangeLocations += $Mailbox.User
}
#Create a new compliance search with the specific users
New-ComplianceSearch -Name ($SearchName + "-Exchange") -ExchangeLocation $ExchangeLocations -ContentMatchQuery $Criteria | Start-ComplianceSearch
OneDrive
OneDrive searches are the only searches that take more effort. Most people have a user's email/UPN that they will need to search and not the associated PersonalURL that is connected to that user's OneDrive. What we will do is use the user's email to find a PersonalURL, create a variable, and then use that variable with our search.
<#
OneDrive Search
#>
$SearchName = Read-Host -Prompt "What is the name of your search?"
$Criteria = [YOUR SEARCH CRITERIA]
# Connect to Microsoft Purview and SharePoint
$Url = "https://[YOURTENANTNAME]-admin.sharepoint.com"
Connect-IPPSSession
Connect-PnPOnline -Url $Url -Interactive -ClientId [YOURCLIENTID]
# Import CSV file
$Mailboxes = Import-Csv -path [PATHTOYOURCSVFILE]
# Initialize the array
$ODLocations = @()
#Loop through each item in the CSV to populate the arrays
foreach ($Mailbox in $Mailboxes) {
$PnPUser = Get-PnPUserProfileProperty -Account $Mailbox.User
$ODLocations += $PnPUser.PersonalUrl
}
#Create a new compliance search with specific user OneDrives
New-ComplianceSearch -Name ($SearchName + "-OneDrive") -SharePointLocation $ODLocations -ContentMatchQuery $Criteria | Start-ComplianceSearch
SharePoint
<#
SharePoint Search
#>
$SearchName = Read-Host -Prompt "What is the name of your search?"
$Criteria = [YOUR SEARCH CRITERIA]
# Connect to Microsoft Purview
Connect-IPPSSession
# Import CSV file
$SPSites = Import-Csv -path [PATHTOYOURCSVFILE]
#Initialize the array
$SPLocations = @()
#Loop through each item in the CSV to populate the array
foreach ($SPSite in $SPSites) {
$SPLocations += $SPSite.URL
}
#Create a new compliance search with the specific SharePoint sites
New-ComplianceSearch -Name ($SearchName + "-SharePoint") -SharePointLocation $SPLocations -ContentMatchQuery $Criteria | Start-ComplianceSearch
This error is related to MFA access requirements. Turning off MFA for an account is not a practical option nowadays but I did try that at one point but that did not work. Another solution I heard is that one could bypass this by using an app password but this an not an option for me as well (and I also have not tried it on my end). Microsoft's script uses the SharePoint Online Management Shell module then uses the SharePoint assemblies from that module to authenticate via auth cookies but generates the following error when run:
"Exception calling "GetAuthenticationCookie" with "1" argument(s): "The sign-in name or password does not match one in the Microsoft account system."↩︎