Compare SharePoint tenant settings

2024-11-17

TL; DR;

You can find the script on Github here .

Why

From comparing configurations between INT and PROD environments, to migrating SharePoint settings, to troubleshooting issues, there are numerous reasons to compare the settings of two Microsoft 365 tenants.

1. Migration Validation

During tenant-to-tenant migrations, comparing SharePoint settings between two tenants ensures that critical configurations from source are replicated correctly in the target tenant.

2. Compliance and Security Audits

Comparing Microsoft 365 tenants helps identify discrepancies in security and compliance settings to ensure both environments meet organizational or regulatory requirements.

3. Troubleshooting and Issue Resolution

Differences in tenant settings may explain functionality issues or inconsistencies in user experiences between tenants. If it works in your dev tenant, why doesn’t it want to work in the Customer’s?

4. Standardization Across Organizations

In organizations with multiple Microsoft 365 tenants (e.g., after mergers or acquisitions), comparing settings helps align configurations for consistency and streamlined operations.

5. Environment Synchronization

Ensures Microsoft 365 tenants used for testing or development (like a sandbox, TEST, UAT or INT), are configured similarly to production for accurate testing and validation.

6. Identifying Misconfigurations

Quickly highlights SharePoint settings that may have been inadvertently changed or left default when they should be customized.

7. Understanding Impact of Policies

If a new policy or feature is enabled in one tenant, comparing with a baseline tenant helps evaluate its impact or appropriateness.

Compare SharePoint tenant settings using SPO Management Shell

You need to connect to both tenants using the Connect-SPOService cmdlet and get the properties using the Get-SPOTenant cmdlet. Then compare all the properties. Two files will be genrated: one - full list of all the compared SharePoint properties, called FullTenantComparison.csv two - only the differences between the Microsoft 365 tenants, called TenantDifferences

# Define a function to connect to a tenant and get properties
function Get-TenantProperties {
    param (
        [string]$AdminUrl
    )

    Write-Host "Connecting to $AdminUrl..." -ForegroundColor Cyan
    Connect-SPOService -Url $AdminUrl
    $tenantProperties = Get-SPOTenant | Select-Object *
    Disconnect-SPOService
    return $tenantProperties
}

# Define a function to compare two objects
function Compare-TenantProperties {
    param (
        [PSCustomObject]$Tenant1,
        [PSCustomObject]$Tenant2
    )

    $comparison = @()
    foreach ($property in $Tenant1.PSObject.Properties) {
        $propertyName = $property.Name
        $value1 = $Tenant1.$propertyName
        $value2 = $Tenant2.$propertyName

        $comparison += [PSCustomObject]@{
            PropertyName = $propertyName
            Tenant1Value = $value1
            Tenant2Value = $value2
            IsDifferent  = $value1 -ne $value2
        }
    }
    return $comparison
}

# Enter the admin URLs for the two tenants
$Tenant1AdminUrl = "https://tenant1-admin.sharepoint.com"
$Tenant2AdminUrl = "https://tenant2-admin.sharepoint.com"

# Get properties from both tenants
$Tenant1Properties = Get-TenantProperties -AdminUrl $Tenant1AdminUrl
$Tenant2Properties = Get-TenantProperties -AdminUrl $Tenant2AdminUrl

# Compare the properties
$ComparisonResults = Compare-TenantProperties -Tenant1 $Tenant1Properties -Tenant2 $Tenant2Properties

# Filter only the differences
$Differences = $ComparisonResults | Where-Object { $_.IsDifferent -eq $true }

# Output to console
Write-Host "Comparison complete." -ForegroundColor Green

# Export all settings compared
$ComparisonResults | Export-Csv -Path "TenantComparison_Full.csv" -NoTypeInformation -Encoding UTF8
Write-Host "Full comparison exported to TenantComparison_Full.csv" -ForegroundColor Cyan

# Export only differences
$Differences | Export-Csv -Path "TenantComparison_Differences.csv" -NoTypeInformation -Encoding UTF8
Write-Host "Differences exported to TenantComparison_Differences.csv" -ForegroundColor Cyan

Compare SharePoint tenant settings using PnP Powershell

You need to connect to both tenants using the Connect-PnPOnline cmdlet and get the properties using the Get-PnPTenant cmdlet. Then compare all the properties. Two files will be genrated: one - full list of all the compared SharePoint properties, called FullTenantComparison.csv two - only the differences between the Microsoft 365 tenants, called TenantDifferences


# Connect to the first tenant
$Tenant1Url = "https://tenant1-admin.sharepoint.com"
$Tenant2Url = "https://tenant2-admin.sharepoint.com"

Write-Host "Connecting to Tenant 1: $Tenant1Url" -ForegroundColor Cyan
Connect-PnPOnline -Url $Tenant1Url -Interactive
$Tenant1Properties = Get-PnPTenant | Select-Object -Property *

# Connect to the second tenant
Write-Host "Connecting to Tenant 2: $Tenant2Url" -ForegroundColor Cyan
Connect-PnPOnline -Url $Tenant2Url -Interactive
$Tenant2Properties = Get-PnPTenant | Select-Object -Property *

# Compare the tenant properties
Write-Host "Comparing properties..." -ForegroundColor Yellow
$Comparison = @()
$AllProperties = $Tenant1Properties.PSObject.Properties.Name

foreach ($Property in $AllProperties) {
    $Value1 = $Tenant1Properties.$Property
    $Value2 = $Tenant2Properties.$Property
    
    if ($Value1 -ne $Value2) {
        $Comparison += [PSCustomObject]@{
            PropertyName = $Property
            Tenant1Value = $Value1
            Tenant2Value = $Value2
        }
    }
}

# Output the differences
if ($Comparison.Count -gt 0) {
    Write-Host "Differences found:" -ForegroundColor Green
    $Comparison | Format-Table -AutoSize
    
    # Export differences to CSV
    $Comparison | Export-Csv -Path "TenantDifferences.csv" -NoTypeInformation
    Write-Host "Differences exported to TenantDifferences.csv" -ForegroundColor Green
} else {
    Write-Host "No differences found between the two tenants." -ForegroundColor Green
}

# Output all properties for full comparison
$FullComparison = @()
foreach ($Property in $AllProperties) {
    $FullComparison += [PSCustomObject]@{
        PropertyName = $Property
        Tenant1Value = $Tenant1Properties.$Property
        Tenant2Value = $Tenant2Properties.$Property
    }
}

# Export full comparison to CSV
$FullComparison | Export-Csv -Path "FullTenantComparison.csv" -NoTypeInformation
Write-Host "Full comparison exported to FullTenantComparison.csv" -ForegroundColor Green


Compare SharePoint tenant settings using CSOM

First connect to both tenants and export the SharePoint tenant properties by loading Microsoft.Online.SharePoint.TenantAdministration.Tenant object for each Microsoft 365 tenant. Then compare all the properties. Two files will be genrated: one - full list of all the compared SharePoint properties, called FullTenantComparison.csv two - only the differences between the Microsoft 365 tenants, called TenantDifferences


# Load required assemblies
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

# Function to get tenant properties
function Get-TenantProperties {
    param (
        [string]$AdminUrl,
        [string]$Username,
        [string]$Password
    )

    $securePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
    $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Username, $securePassword)

    $context = New-Object Microsoft.SharePoint.Client.ClientContext($AdminUrl)
    $context.Credentials = $credentials

    # Load tenant properties
    $tenant = New-Object Microsoft.Online.SharePoint.TenantAdministration.Tenant($context)
    $context.Load($tenant)
    $context.ExecuteQuery()

    # Extract and return tenant properties
    return $tenant | Get-Member -MemberType Property | ForEach-Object {
        [PSCustomObject]@{
            PropertyName = $_.Name
            PropertyValue = $tenant.($_.Name)
        }
    }
}

# Connect to the first tenant
$Tenant1AdminUrl = "https://tenant1-admin.sharepoint.com"
$Tenant1Username = "admin1@tenant1.onmicrosoft.com"
$Tenant1Password = "YourPassword1"

Write-Host "Retrieving properties from Tenant 1: $Tenant1AdminUrl" -ForegroundColor Cyan
$Tenant1Properties = Get-TenantProperties -AdminUrl $Tenant1AdminUrl -Username $Tenant1Username -Password $Tenant1Password

# Connect to the second tenant
$Tenant2AdminUrl = "https://tenant2-admin.sharepoint.com"
$Tenant2Username = "admin2@tenant2.onmicrosoft.com"
$Tenant2Password = "YourPassword2"

Write-Host "Retrieving properties from Tenant 2: $Tenant2AdminUrl" -ForegroundColor Cyan
$Tenant2Properties = Get-TenantProperties -AdminUrl $Tenant2AdminUrl -Username $Tenant2Username -Password $Tenant2Password

# Compare tenant properties
Write-Host "Comparing properties..." -ForegroundColor Yellow
$Comparison = @()

foreach ($Property in $Tenant1Properties) {
    $Tenant2Value = ($Tenant2Properties | Where-Object { $_.PropertyName -eq $Property.PropertyName }).PropertyValue

    if ($Property.PropertyValue -ne $Tenant2Value) {
        $Comparison += [PSCustomObject]@{
            PropertyName  = $Property.PropertyName
            Tenant1Value  = $Property.PropertyValue
            Tenant2Value  = $Tenant2Value
        }
    }
}

# Output the differences
if ($Comparison.Count -gt 0) {
    Write-Host "Differences found:" -ForegroundColor Green
    $Comparison | Format-Table -AutoSize

    # Export differences to CSV
    $Comparison | Export-Csv -Path "TenantDifferences.csv" -NoTypeInformation
    Write-Host "Differences exported to TenantDifferences.csv" -ForegroundColor Green
} else {
    Write-Host "No differences found between the two tenants." -ForegroundColor Green
}

# Output all properties for full comparison
$FullComparison = $Tenant1Properties | ForEach-Object {
    $Tenant2Value = ($Tenant2Properties | Where-Object { $_.PropertyName -eq $_.PropertyName }).PropertyValue

    [PSCustomObject]@{
        PropertyName  = $_.PropertyName
        Tenant1Value  = $_.PropertyValue
        Tenant2Value  = $Tenant2Value
    }
}

# Export full comparison to CSV
$FullComparison | Export-Csv -Path "FullTenantComparison.csv" -NoTypeInformation
Write-Host "Full comparison exported to FullTenantComparison.csv" -ForegroundColor Green

See Also

Get-SPOTenant

Get-PnPTenant