Background
The eDiscovery service in the Office 365 Compliance and Security center dramatically improves both SharePoint and Exchange eDiscovery services. As Microsoft makes considerable strides in building eDiscovery feature sets, however, some limitations persist. Two of these limitations that we have been asked to address are eDiscovery searches and placing SharePoint sites on hold when specific users contribute to SharePoint sites. Currently, eDiscovery searches are point-in-time.
eDiscovery search results within eDiscovery cases only contain content that has been indexed by SharePoint and/or Exchange. Any new content that is indexed after an eDiscovery search has completed will not be included in the results for an eDiscovery search.
When a hold is placed on a specific user, organizations generally want to place holds correlating to any SharePoint site that user has contributed to.
While these tasks can be performed in the Compliance and Security center, it is time consuming and tedious.
Solution
The point-in-time characteristic of eDiscovery searches and placing holds on SharePoint sites linked to specific user contributions can both be addressed using PowerShell.
Placing all of the SharePoint sites on hold that specific users contribute to is accomplished by first generating a new content search. The content search covers all SharePoint sites using the UPN condition to locate the user you are seeking.
The list of SharePoint sites that are returned in the content search are used to build a new eDiscovery case and legal hold within that case. Each SharePoint site in the content search is then placed on a legal hold, thus ensuring all sites the specific user contributed to is on legal hold.
Perform the following steps before executing the contributor script:
- Download SharePoint Online module: https://www.microsoft.com/en-us/download/details.aspx?id=35588
- Enter your administrator credentials in Line 9
Note: Load the PowerShell Script in ISE, matching line numbers
The Integration of the Author PowerShell script is fairly straight forward. To implement the Author script, follow the steps below.
- Copy all content in the script section and save it to a .PS1 file; author.ps1
-
When prompted, enter your username and password
-
Provide a name for the eDiscovery search
-
Provide the UPN for the user that should be placed on hold
- Navigate to the Security and Compliance center
-
Under Search & investigation > Content Search there should be a new content search
-
The results section will display the number of items that matched your search.
- To see sites that are on hold, navigate to Search & investigation > eDiscovery.
- Select the newly created eDiscovery case
- Select Hold > highlight the case and select edit
-
Under Locations > Site is the list of SharePoint sites that are on hold
Force Sync
To update eDiscovery cases, add the code below to a .PS1 file. Once the PS1 file is created, use the information in this link to create a schedule task.
$Site = Get-ComplianceCase
Foreach ($case in $site){
write-host
$case.Name
Start-ComplianceSearch -Identity $case.Name
}
Author
# Get user credentials
if (!$credentials )
{
$credentials = Get-Credential
}
# Get the user's MySite domain name. We use this to create the admin URL and root URL for OneDrive for Business
$AdminUrl = "https://Cb5lab-admin.sharepoint.com"
# Get other required information
#$inputfile = "C:\temp\User.csv"
$searchName = Read-Host
"Enter the name for the new search"
$searchQuery = Read-Host
"Enter the search query you want to use"
# Connect to Office 365
if (!$s -or !$a)
{
$s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://ps.compliance.protection.outlook.com/powershell-liveid" -Credential
$credentials -Authentication Basic -AllowRedirection -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck)
$a = Import-PSSession
$s -AllowClobber
if (!$s )
{
Write-Error
"Could not create PowerShell session."
return ;
}
}
# Load the SharePoint assemblies from the SharePoint Online Management Shell
# To install, go to http://go.microsoft.com/fwlink/p/?LinkId=255251
if (!$SharePointClient -or
! $SPRuntime -or
! $SPUserProfile )
{
$SharePointClient = [System.Reflection.Assembly]:: LoadWithPartialName("Microsoft.SharePoint.Client")
$SPRuntime = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
$SPUserProfile = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.UserProfiles")
if (!$SharePointClient)
{
Write-Error
"SharePoint Online Management Shell isn't installed, please install from: http://go.microsoft.com/fwlink/p/?LinkId=255251 and then run this script again"
return ;
}
}
if (!$spCreds )
{
$spCreds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials ($credentials.UserName, $credentials.Password)
}
# Add the path of the User Profile Service to the SPO admin URL, then create a new webservice proxy to access it
$proxyaddr = "$AdminUrl/_vti_bin/UserProfileService.asmx?wsdl"
$UserProfileService = New-WebServiceProxy -Uri $proxyaddr -UseDefaultCredential False
$UserProfileService.Credentials = $credentials
# Take care of auth cookies
$strAuthCookie = $spCreds.GetAuthenticationCookie($AdminUrl)
$uri = New-Object System.Uri ($AdminUrl)
$container = New-Object System.Net.CookieContainer
$container.SetCookies ($uri, $strAuthCookie)
$UserProfileService.CookieContainer = $container
Write-Host
"Creating and starting the search"
$search = New-ComplianceSearch -Name $searchName -SharePointLocation all -ContentMatchQuery
$searchQuery
Start-ComplianceSearch
$search.Name
Start-Sleep
90
#=====================================================================================
$Case = Get-ComplianceSearch
$search.Name
if ($Case.Status -ne "Completed" )
{
"Please wait until the search finishes." ;
break ;
}
$CaseResult = $Case.SuccessResults;
if (($Case.Items -le 0) -or [string]::IsNullOrWhiteSpace( $CaseResult )))
{
"The compliance search " + $search.Name + "didn't return any useful results." ;
break;
}
$Case
|
fl
#=====================================================================================
$search = Get-ComplianceSearch
$SearchName
if ( $search . Status -ne "Completed" )
{
"Please wait until the search finishes" ;
break ;
}
$results = $search.SuccessResults;
if (($search.Items -le 0 ) -or [string]::IsNullOrWhiteSpace($results)))
{
"The compliance search " + $SearchName + "didn't return any useful results" ;
"A SharePoint search object wasn't created" ;
break ;
}
$Sites = @();
$lines = $results -split '[\r\n]+' ;
foreach ($line in $lines)
{
if ($line -match 'Location:(\S+),.+Item count: (\d+)' -and $matches [2] -gt 0)
{
$Sites += $matches [1] ;
}
}
$msPrefix = $SearchName + "_SharePointSearch" ;
$I = 1;
$query = $search.KeywordQuery;
if [string]::IsNullOrWhiteSpace($query))
{
$query = $search.ContentMatchQuery;
}
#>
New-ComplianceCase -Name $searchName
Start-Sleep
90
New-CaseHoldPolicy -Case $searchName -SharePointLocation
$Sites -name
$msPrefix$i
New-CaseHoldRule -Name
$msPrefix$i -Policy
$msPrefix$i