Last active
November 2, 2017 19:42
-
-
Save joerodgers/8609d07321a2d55db4ea46422b2402f9 to your computer and use it in GitHub Desktop.
This script will sync a web property bag value to the Site.Classification property on all SPO sites in the tenant.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add-Type -Path "C:\Microsoft.SharePointOnline.CSOM.16.1.6008.1200\lib\net45\Microsoft.SharePoint.Client.dll" | |
Add-Type -Path "C:\Microsoft.SharePointOnline.CSOM.16.1.6008.1200\lib\net45\Microsoft.SharePoint.Client.Runtime.dll" | |
Add-Type -Path "C:\Microsoft.SharePointOnline.CSOM.16.1.6008.1200\lib\net45\Microsoft.Online.SharePoint.Client.Tenant.dll" | |
$tenantAdminUrl = "https://contoso-admin.sharepoint.com" | |
$tenantAdminUsername = "admin@contoso.onmicrosoft.com" | |
$securePassword = ConvertTo-SecureString 'pass@word1' -AsPlainText -Force | |
$script:PropertyName = "contoso_SiteDataClassification" | |
[System.Net.WebRequest]::DefaultWebProxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials | |
function New-ClientContextWithRetry | |
{ | |
[cmdletbinding()] | |
param | |
( | |
[Parameter(Mandatory=$true, ParameterSetName = "CredentialComponents")] | |
[Parameter(Mandatory=$true, ParameterSetName = "SharePointOnlineCredential")] | |
[string]$ContextUrl, | |
[Parameter(Mandatory=$true, ParameterSetName = "CredentialComponents")] | |
[string]$UserName, | |
[Parameter(Mandatory=$true, ParameterSetName = "CredentialComponents")] | |
[System.Security.SecureString]$SecurePassword, | |
[Parameter(Mandatory=$true, ParameterSetName = "SharePointOnlineCredential")] | |
[Microsoft.SharePoint.Client.SharePointOnlineCredentials]$SharePointOnlineCredential | |
) | |
begin | |
{ | |
$retryAttempts = 1 | |
$clientContext = $null | |
} | |
process | |
{ | |
do | |
{ | |
try | |
{ | |
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($ContextUrl) | |
if( $PSCmdlet.ParameterSetName -eq "CredentialComponents" ) | |
{ | |
$clientContext.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword) | |
} | |
else | |
{ | |
$clientContext.Credentials = $SharePointOnlineCredential | |
} | |
$clientContext.Load($clientContext.Web) | |
$clientContext.Load($clientContext.Site) | |
$clientContext.ExecuteQuery() | |
return $clientContext | |
} | |
catch [System.Net.WebException] | |
{ | |
$response = $_.Exception.Response -as [System.Net.HttpWebResponse] | |
if( $response -and ( [int]$response.StatusCode -eq 429 -or [int]$response.StatusCode -eq 503 ) ) | |
{ | |
Write-Warning -Message "$($MyInvocation.MyCommand.Name) - Execution attempt $retryAttempts failed" | |
Write-Warning -Message "$($MyInvocation.MyCommand.Name) - Exception Info: $($_.Exception)" | |
$retryAttempts++ | |
Start-Sleep -Seconds 10 | |
} | |
elseif( $response -and [int]$response.StatusCode -eq 404 ) | |
{ | |
Write-Warning -Message "A site with the URL $ContextUrl was not found in the tenant." | |
return $null | |
} | |
else | |
{ | |
Write-Error -Message "Error connecting to $ContextUrl. Exception $($_.Exception.Message)" | |
return $null | |
} | |
} | |
catch | |
{ | |
Write-Error -Message "$($MyInvocation.MyCommand.Name) - Unexpected execution exception: $($_.Exception.Message)" | |
throw $_.Exception | |
} | |
} | |
while( $retryAttempts -lt 5 ) | |
} | |
end | |
{ | |
} | |
} | |
function Invoke-ClientContextWithRetry | |
{ | |
[cmdletbinding()] | |
param | |
( | |
[parameter(Mandatory=$true)][Microsoft.SharePoint.Client.ClientContext]$ClientContext, | |
[parameter(Mandatory=$false)][int]$Delay = 10, | |
[parameter(Mandatory=$false)][int]$RetryAttemps = 5 | |
) | |
begin | |
{ | |
$executions = 1 | |
} | |
process | |
{ | |
do | |
{ | |
try | |
{ | |
$ClientContext.ExecuteQuery() | |
return | |
} | |
catch [System.Net.WebException] | |
{ | |
$response = $_.Exception.Response -as [System.Net.HttpWebResponse] | |
if( $response -and ([int]$response.StatusCode -eq 429 -or [int]$response.StatusCode -eq 503) ) | |
{ | |
Write-Warning -Message "Execution attempt $executions was throttled, trying again in $Delay seconds." | |
$executions++ | |
Start-Sleep -Seconds $Delay | |
} | |
elseif( $response -and [int]$response.StatusCode -eq 404 ) | |
{ | |
Write-Warning -Message "A site with the URL $($ClientContext.Url) was not found in the tenant." | |
return | |
} | |
else | |
{ | |
Write-Error -Message "An error occurred connecting to $($ClientContext.Url). Exception: $($_.Exception.Message)" | |
return | |
} | |
} | |
catch | |
{ | |
Write-Error -Message "Unexpected execution exception: $($_.Exception.Message)" | |
} | |
} | |
while( $executions -le $RetryAttemps ) | |
Write-Error -Message "$($MyInvocation.MyCommand.Name) - Exceeded retry threshold" | |
} | |
end | |
{ | |
} | |
} | |
function Update-SiteClassificationFromExistingWebProperty | |
{ | |
[cmdletbinding()] | |
param | |
( | |
[parameter(Mandatory=$true)][Microsoft.SharePoint.Client.ClientContext]$ClientContext | |
) | |
begin | |
{ | |
} | |
process | |
{ | |
$ClientContext.Load( $ClientContext.Web.AllProperties ) | |
$ClientContext.Load( $ClientContext.Site ) | |
Invoke-ClientContextWithRetry -ClientContext $ClientContext | |
if( -not $ClientContext.Site.Classification -or $ClientContext.Site.Classification -eq "Not Classified" ) # don't overwrite any existing legit classification values | |
{ | |
$legacyClassificationPropertyValue = $ClientContext.Web.AllProperties[$script:PropertyName] | |
switch($legacyClassificationPropertyValue) | |
{ | |
"Proprietary" | |
{ | |
Write-Host "$(Get-Date) - `tUpdating $($ClientContext.Site.Url) to Proprietary" -ForegroundColor Green | |
$ClientContext.Site.Classification = "Proprietary" | |
} | |
"Confidential" | |
{ | |
Write-Host "$(Get-Date) - `tUpdating $($ClientContext.Site.Url) to Confidential" -ForegroundColor Green | |
$ClientContext.Site.Classification = "Confidential" | |
} | |
"Restricted" | |
{ | |
Write-Host "$(Get-Date) - `tUpdating $($ClientContext.Site.Url) to Restricted" -ForegroundColor Green | |
$ClientContext.Site.Classification = "Restricted" | |
} | |
default | |
{ | |
Write-Host "$(Get-Date) - `tNo legacy classification specified" -ForegroundColor Yellow | |
} | |
} | |
} | |
Invoke-ClientContextWithRetry -ClientContext $ClientContext | |
} | |
end | |
{ | |
} | |
} | |
function Get-SharePointOnlineSite | |
{ | |
<# | |
.Synopsis | |
Returns the specified SharePoint Online site using the designated Identify URL. If no Identify URL is specified, all SharePoint Online sites are returned. | |
If a Filter passed the function, the filter is passed to the service for filtering. | |
.EXAMPLE | |
$spoSites = Get-SharePointOnlineSite -TenantContext $tenantContext | |
.EXAMPLE | |
$teamsite = Get-SharePointOnlineSite -TenantContext $tenantContext -Identity "https://tenant.sharepoint.com/sites/teamsite" -Detailed | |
#> | |
[cmdletbinding()] | |
param | |
( | |
[parameter(Mandatory=$true,ParameterSetName='ParamSet1')] | |
[System.Uri]$Identity, | |
[parameter(Mandatory=$false,ParameterSetName='ParamSet2')] | |
[String]$Filter, | |
[parameter(Mandatory=$true,ParameterSetName='ParamSet1')] | |
[parameter(Mandatory=$true,ParameterSetName='ParamSet2')] | |
[Microsoft.SharePoint.Client.ClientContext]$TenantContext, | |
[parameter(Mandatory=$false,ParameterSetName='ParamSet1')] | |
[parameter(Mandatory=$false,ParameterSetName='ParamSet2')] | |
[switch]$IncludeDetail | |
) | |
begin | |
{ | |
$DefaultSiteRowLimit = 200 | |
$oneDriveForBusinessSiteUrls = @() | |
$resultsProcessed = 0 | |
} | |
process | |
{ | |
if( $PSCmdlet.ParameterSetName -eq "ParamSet1" ) | |
{ | |
$tenant = New-Object Microsoft.Online.SharePoint.TenantAdministration.Tenant($TenantContext) | |
$siteProperties = $tenant.GetSitePropertiesByUrl($Identity, $IncludeDetail) | |
$TenantContext.Load($siteProperties) | |
Invoke-ClientContextWithRetry -ClientContext $TenantContext | |
} | |
else | |
{ | |
$startIndex = 0 | |
$moreSiteDataAvailable = $true | |
$sitePropertiesList = New-Object 'System.Collections.Generic.List[Microsoft.Online.SharePoint.TenantAdministration.SiteProperties]' | |
while( $startIndex -ge 0 ) | |
{ | |
if(-not $Filter) | |
{ | |
$tenant = New-Object Microsoft.Online.SharePoint.TenantAdministration.Tenant($TenantContext) | |
$sitePropertiesEnumerable = $tenant.GetSiteProperties($startIndex, $IncludeDetail) | |
} | |
else | |
{ | |
$tenant = New-Object Microsoft.Online.SharePoint.TenantAdministration.Tenant($TenantContext) | |
$sitePropertiesEnumerable = $tenant.GetSitePropertiesFromSharePointByFilter($Filter, $startIndex, $IncludeDetail) | |
} | |
$TenantContext.Load($sitePropertiesEnumerable) | |
Invoke-ClientContextWithRetry -ClientContext $TenantContext | |
$sitePropertiesList.AddRange($sitePropertiesEnumerable) | |
$startIndex = $sitePropertiesEnumerable.NextStartIndex | |
} | |
$siteProperties = $sitePropertiesList | |
} | |
} | |
end | |
{ | |
$siteProperties | |
} | |
} | |
# Get a context to the tenant admin portal | |
$tenantContext = New-ClientContextWithRetry -ContextUrl $tenantAdminUrl -UserName $tenantAdminUsername -SecurePassword $securePassword | |
if( $tenantContext ) | |
{ | |
# get all the sites in the tenant | |
$siteUrls = Get-SharePointOnlineSite -TenantContext $tenantContext | % { $_.Url } | |
# update each site | |
foreach( $siteUrl in $siteUrls ) | |
{ | |
Write-Host "$(Get-Date) - Processing $siteUrl" | |
$clientContext = New-ClientContextWithRetry -ContextUrl $siteUrl -UserName $tenantAdminUsername -SecurePassword $securePassword | |
if( $clientContext ) | |
{ | |
Update-SiteClassificationFromExistingWebProperty -ClientContext $clientContext | |
$clientContext.Dispose() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment