Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joerodgers/8609d07321a2d55db4ea46422b2402f9 to your computer and use it in GitHub Desktop.
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.
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