Skip to content

Ensuring Secure OneDrive Sync with SharePoint Online Tenant Sync Client Restriction

Ensuring Secure OneDrive Sync with SharePoint Online Tenant Sync Client Restriction

Section titled “Ensuring Secure OneDrive Sync with SharePoint Online Tenant Sync Client Restriction”

This PowerShell script implements SharePoint Online tenant sync client restrictions to ensure secure OneDrive synchronization across your organization. The script helps prevent unauthorized data access and ensures compliance with organizational security policies.

  • PowerShell: 5.1 or later (Windows PowerShell 7+ recommended)
  • SharePoint Online Management Shell: Latest version
  • Microsoft Graph PowerShell SDK: For modern API interactions
  • Appropriate Permissions: SharePoint Administrator or Global Administrator
Terminal window
# Install required modules
Install-Module -Name Microsoft.Online.SharePoint.PowerShell -Force
Install-Module -Name Microsoft.Graph -Force
Install-Module -Name PnP.PowerShell -Force
  • SharePoint Administrator: For tenant-level configuration
  • Global Administrator: For comprehensive access
  • Application Permissions: For automated execution
Terminal window
param(
[Parameter(Mandatory=$false)]
[string]$TenantUrl = "https://yourtenant-admin.sharepoint.com",
[Parameter(Mandatory=$false)]
[string]$LogFile = "C:\Logs\SharePointSyncRestriction.log",
[Parameter(Mandatory=$false)]
[ValidateSet("Allow", "Block", "Unspecified")]
[string]$DefaultSyncClientRestriction = "Allow",
[Parameter(Mandatory=$false)]
[string[]]$AllowedDomains = @("contoso.com", "partner.com"),
[Parameter(Mandatory=$false)]
[string[]]$BlockedDomains = @("personal-email.com", "suspicious-domain.com"),
[Parameter(Mandatory=$false)]
[switch]$EnforceGrooveBlock = $false,
[Parameter(Mandatory=$false)]
[switch]$GenerateReport = $false,
[Parameter(Mandatory=$false)]
[switch]$TestMode = $false
)
Terminal window
$ScriptVersion = "1.3.0"
$CompanyName = "YourCompany"
$SupportEmail = "support@yourcompany.com"
$MaxRetryAttempts = 3
$RetryDelaySeconds = 30
Terminal window
function Set-SharePointSyncClientRestriction {
param(
[string]$TenantUrl,
[string]$LogPath,
[string]$DefaultRestriction,
[string[]]$AllowedDomains,
[string[]]$BlockedDomains,
[bool]$EnforceGroove,
[bool]$GenerateReport,
[bool]$TestMode
)
try {
# Initialize logging
Initialize-Logging -LogPath $LogPath
Write-Log "Starting SharePoint sync client restriction configuration - Version $ScriptVersion"
Write-Log "Target Tenant: $TenantUrl"
Write-Log "Test Mode: $TestMode"
# Connect to SharePoint Online
if (-not (Connect-SharePointOnline -TenantUrl $TenantUrl)) {
Write-Log "Failed to connect to SharePoint Online" -Level "ERROR"
return $false
}
# Get current configuration
$currentConfig = Get-CurrentSyncConfiguration
Write-Log "Current sync client restriction: $($currentConfig.DefaultRestriction)"
# Configure default restriction
if ($DefaultRestriction -ne $currentConfig.DefaultRestriction) {
Write-Log "Updating default sync client restriction to: $DefaultRestriction"
if (-not $TestMode) {
Set-DefaultSyncRestriction -Restriction $DefaultRestriction
}
}
# Configure domain restrictions
if ($AllowedDomains.Count -gt 0 -or $BlockedDomains.Count -gt 0) {
Write-Log "Configuring domain restrictions"
Set-DomainRestrictions -AllowedDomains $AllowedDomains -BlockedDomains $BlockedDomains -TestMode $TestMode
}
# Configure Groove client blocking if requested
if ($EnforceGroove) {
Write-Log "Configuring Groove client blocking"
Set-GrooveClientBlocking -TestMode $TestMode
}
# Generate report if requested
if ($GenerateReport) {
Write-Log "Generating configuration report"
$report = New-ConfigurationReport -CurrentConfig $currentConfig
Export-Report -Report $report -Path "C:\Reports\SharePointSyncReport-$(Get-Date -Format 'yyyyMMdd-HHmmss').csv"
}
# Validate configuration
if (-not $TestMode) {
$validationResult = Test-Configuration -ExpectedConfig @{
DefaultRestriction = $DefaultRestriction
AllowedDomains = $AllowedDomains
BlockedDomains = $BlockedDomains
}
if ($validationResult.Success) {
Write-Log "Configuration validation successful"
} else {
Write-Log "Configuration validation failed: $($validationResult.ErrorMessage)" -Level "ERROR"
return $false
}
}
Write-Log "SharePoint sync client restriction configuration completed successfully"
return $true
} catch {
Write-Log "Unexpected error in Set-SharePointSyncClientRestriction: $($_.Exception.Message)" -Level "ERROR"
return $false
} finally {
# Disconnect from SharePoint Online
Disconnect-PnPOnline
}
}
Terminal window
function Connect-SharePointOnline {
param([string]$TenantUrl)
try {
Write-Log "Connecting to SharePoint Online: $TenantUrl"
# Try PnP connection first (recommended)
try {
Connect-PnPOnline -Url $TenantUrl -Interactive
Write-Log "Connected using PnP PowerShell"
return $true
} catch {
Write-Log "PnP connection failed, trying traditional method" -Level "WARNING"
}
# Fallback to traditional SharePoint Online connection
$credential = Get-Credential -Message "Enter SharePoint Online administrator credentials"
Connect-SPOService -Url $TenantUrl -Credential $credential
Write-Log "Connected using SharePoint Online Management Shell"
return $true
} catch {
Write-Log "Failed to connect to SharePoint Online: $($_.Exception.Message)" -Level "ERROR"
return $false
}
}
Terminal window
function Get-CurrentSyncConfiguration {
try {
Write-Log "Retrieving current sync client configuration"
# Get tenant sync client restriction
$syncRestriction = Get-SPOTenantSyncClientRestriction
# Get domain restrictions
$domainRestrictions = Get-SPOTenantSyncClientRestriction -ErrorAction SilentlyContinue
return [PSCustomObject]@{
DefaultRestriction = $syncRestriction
AllowedDomains = @()
BlockedDomains = @()
GrooveBlocked = $false
LastModified = Get-Date
}
} catch {
Write-Log "Failed to get current configuration: $($_.Exception.Message)" -Level "ERROR"
return $null
}
}
Terminal window
function Set-DefaultSyncRestriction {
param([string]$Restriction)
try {
Write-Log "Setting default sync client restriction to: $Restriction"
$attempt = 1
while ($attempt -le $MaxRetryAttempts) {
try {
Set-SPOTenantSyncClientRestriction -Restriction $Restriction
Write-Log "Successfully set default sync client restriction"
return $true
} catch {
Write-Log "Attempt $attempt failed: $($_.Exception.Message)" -Level "WARNING"
if ($attempt -lt $MaxRetryAttempts) {
Start-Sleep -Seconds $RetryDelaySeconds
$attempt++
} else {
throw "Failed after $MaxRetryAttempts attempts"
}
}
}
} catch {
Write-Log "Failed to set default sync restriction: $($_.Exception.Message)" -Level "ERROR"
return $false
}
}
Terminal window
function Set-DomainRestrictions {
param(
[string[]]$AllowedDomains,
[string[]]$BlockedDomains,
[bool]$TestMode
)
try {
Write-Log "Configuring domain restrictions"
Write-Log "Allowed domains: $($AllowedDomains -join ', ')"
Write-Log "Blocked domains: $($BlockedDomains -join ', ')"
if ($TestMode) {
Write-Log "TEST MODE: Would configure domain restrictions"
return $true
}
# Configure allowed domains
foreach ($domain in $AllowedDomains) {
try {
Write-Log "Adding allowed domain: $domain"
Add-SPOTenantSyncClientRestriction -AllowedDomain $domain
} catch {
Write-Log "Failed to add allowed domain $domain`: $($_.Exception.Message)" -Level "WARNING"
}
}
# Configure blocked domains
foreach ($domain in $BlockedDomains) {
try {
Write-Log "Adding blocked domain: $domain"
Add-SPOTenantSyncClientRestriction -BlockedDomain $domain
} catch {
Write-Log "Failed to add blocked domain $domain`: $($_.Exception.Message)" -Level "WARNING"
}
}
Write-Log "Domain restrictions configuration completed"
return $true
} catch {
Write-Log "Failed to configure domain restrictions: $($_.Exception.Message)" -Level "ERROR"
return $false
}
}
Terminal window
function Set-GrooveClientBlocking {
param([bool]$TestMode)
try {
Write-Log "Configuring Groove client blocking"
if ($TestMode) {
Write-Log "TEST MODE: Would block Groove client"
return $true
}
# Block legacy Groove client
Set-SPOTenantSyncClientRestriction -BlockMacSync $true
Set-SPOTenantSyncClientRestriction -BlockUnmanagedSyncClient $true
Write-Log "Groove client blocking configured successfully"
return $true
} catch {
Write-Log "Failed to configure Groove client blocking: $($_.Exception.Message)" -Level "ERROR"
return $false
}
}
Terminal window
function Test-Configuration {
param([hashtable]$ExpectedConfig)
try {
Write-Log "Validating configuration"
$currentConfig = Get-CurrentSyncConfiguration
$validationErrors = @()
# Validate default restriction
if ($currentConfig.DefaultRestriction -ne $ExpectedConfig.DefaultRestriction) {
$validationErrors += "Default restriction mismatch: Expected $($ExpectedConfig.DefaultRestriction), Found $($currentConfig.DefaultRestriction)"
}
# Validate allowed domains
$missingAllowed = $ExpectedConfig.AllowedDomains | Where-Object { $_ -notin $currentConfig.AllowedDomains }
if ($missingAllowed.Count -gt 0) {
$validationErrors += "Missing allowed domains: $($missingAllowed -join ', ')"
}
# Validate blocked domains
$missingBlocked = $ExpectedConfig.BlockedDomains | Where-Object { $_ -notin $currentConfig.BlockedDomains }
if ($missingBlocked.Count -gt 0) {
$validationErrors += "Missing blocked domains: $($missingBlocked -join ', ')"
}
if ($validationErrors.Count -gt 0) {
Write-Log "Configuration validation failed:" -Level "ERROR"
foreach ($error in $validationErrors) {
Write-Log " - $error" -Level "ERROR"
}
return [PSCustomObject]@{
Success = $false
ErrorMessage = $validationErrors -join "; "
}
}
return [PSCustomObject]@{
Success = $true
ErrorMessage = ""
}
} catch {
Write-Log "Configuration validation failed: $($_.Exception.Message)" -Level "ERROR"
return [PSCustomObject]@{
Success = $false
ErrorMessage = $_.Exception.Message
}
}
}
Terminal window
function New-ConfigurationReport {
param([PSCustomObject]$CurrentConfig)
try {
Write-Log "Generating configuration report"
$reportData = @()
# Add configuration summary
$reportData += [PSCustomObject]@{
Category = "Configuration"
Item = "Default Sync Restriction"
Value = $CurrentConfig.DefaultRestriction
Status = "Configured"
LastModified = $CurrentConfig.LastModified
}
# Add domain restrictions
foreach ($domain in $CurrentConfig.AllowedDomains) {
$reportData += [PSCustomObject]@{
Category = "Domain Restriction"
Item = "Allowed Domain"
Value = $domain
Status = "Allowed"
LastModified = $CurrentConfig.LastModified
}
}
foreach ($domain in $CurrentConfig.BlockedDomains) {
$reportData += [PSCustomObject]@{
Category = "Domain Restriction"
Item = "Blocked Domain"
Value = $domain
Status = "Blocked"
LastModified = $CurrentConfig.LastModified
}
}
# Add Groove client status
$reportData += [PSCustomObject]@{
Category = "Client Restrictions"
Item = "Groove Client"
Value = if ($CurrentConfig.GrooveBlocked) { "Blocked" } else { "Allowed" }
Status = if ($CurrentConfig.GrooveBlocked) { "Blocked" } else { "Allowed" }
LastModified = $CurrentConfig.LastModified
}
return $reportData
} catch {
Write-Log "Failed to generate configuration report: $($_.Exception.Message)" -Level "ERROR"
return @()
}
}
Terminal window
function Export-Report {
param(
[array]$Report,
[string]$Path
)
try {
Write-Log "Exporting report to: $Path"
# Ensure directory exists
$directory = Split-Path $Path -Parent
if (-not (Test-Path $directory)) {
New-Item -Path $directory -ItemType Directory -Force | Out-Null
}
# Export to CSV
$Report | Export-Csv -Path $Path -NoTypeInformation -Encoding UTF8
Write-Log "Report exported successfully"
# Also export to JSON for programmatic use
$jsonPath = $Path.Replace(".csv", ".json")
$Report | ConvertTo-Json -Depth 3 | Set-Content -Path $jsonPath -Encoding UTF8
} catch {
Write-Log "Failed to export report: $($_.Exception.Message)" -Level "ERROR"
}
}
Terminal window
function Write-Log {
param(
[string]$Message,
[ValidateSet("INFO", "WARNING", "ERROR", "DEBUG")]
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$hostname = $env:COMPUTERNAME
$logEntry = "[$timestamp] [$hostname] [$Level] $Message"
# Write to log file
Add-Content -Path $LogFile -Value $logEntry -Encoding UTF8
# Write to console
switch ($Level) {
"ERROR" { Write-Host $logEntry -ForegroundColor Red }
"WARNING" { Write-Host $logEntry -ForegroundColor Yellow }
"DEBUG" { Write-Host $logEntry -ForegroundColor Gray }
default { Write-Host $logEntry -ForegroundColor Green }
}
}
Terminal window
function Initialize-Logging {
param([string]$LogPath)
try {
# Ensure log directory exists
$logDirectory = Split-Path $LogPath -Parent
if (-not (Test-Path $logDirectory)) {
New-Item -Path $logDirectory -ItemType Directory -Force | Out-Null
}
# Create log file if it doesn't exist
if (-not (Test-Path $LogPath)) {
Set-Content -Path $LogPath -Value "SharePoint Sync Client Restriction Log - Created $(Get-Date)" -Encoding UTF8
}
Write-Log "Logging initialized: $LogPath"
} catch {
Write-Host "Failed to initialize logging: $($_.Exception.Message)" -ForegroundColor Red
}
}
Terminal window
# Create scheduled task for regular monitoring
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy Bypass -File `"C:\Scripts\Set-SharePointSyncRestriction.ps1`" -GenerateReport"
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Sunday -At 2am
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -WakeToRun
Register-ScheduledTask -TaskName "SharePoint Sync Restriction Monitor" -Action $action -Trigger $trigger -Settings $settings -RunLevel Highest
Terminal window
# Azure Automation runbook configuration
$AutomationAccountName = "YourAutomationAccount"
$ResourceGroupName = "YourResourceGroup"
Import-AzAutomationRunbook -Path "Set-SharePointSyncRestriction.ps1" -AutomationAccountName $AutomationAccountName -ResourceGroupName $ResourceGroupName -Name "Set-SharePointSyncRestriction" -Type PowerShell
Publish-AzAutomationRunbook -AutomationAccountName $AutomationAccountName -ResourceGroupName $ResourceGroupName -Name "Set-SharePointSyncRestriction"
  • Least Privilege: Use service accounts with minimum required permissions
  • Secure Storage: Store credentials in Azure Key Vault or Windows Credential Manager
  • Audit Logging: Maintain comprehensive audit trail of all configuration changes
  • Regular Review: Periodically review and update restrictions
  • Data Protection: Ensure compliance with GDPR, CCPA, and other regulations
  • Industry Standards: Meet HIPAA, SOX, or industry-specific requirements
  • Documentation: Maintain detailed configuration documentation
  • Change Management: Implement formal change control procedures
Terminal window
function Test-SharePointSyncHealth {
try {
$config = Get-CurrentSyncConfiguration
# Check if restrictions are properly configured
$healthStatus = [PSCustomObject]@{
TenantUrl = $TenantUrl
DefaultRestriction = $config.DefaultRestriction
LastCheck = Get-Date
Status = "Healthy"
Issues = @()
}
# Add specific checks based on your requirements
return $healthStatus
} catch {
return [PSCustomObject]@{
TenantUrl = $TenantUrl
Status = "Error"
LastCheck = Get-Date
Issues = @($_.Exception.Message)
}
}
}
Terminal window
# Configure email alerts for configuration changes
function Send-ConfigurationAlert {
param(
[string]$Message,
[PSCustomObject]$Details
)
$emailBody = @"
SharePoint Sync Client Restriction Alert
========================================
$Message
Details:
- Tenant: $($Details.TenantUrl)
- Timestamp: $(Get-Date)
- Configuration: $($Details | ConvertTo-Json -Depth 2)
Please review the configuration and take appropriate action.
"@
Send-MailMessage -To "admin@yourcompany.com" -From "alerts@yourcompany.com" -Subject "SharePoint Sync Restriction Alert" -Body $emailBody -SmtpServer "smtp.yourcompany.com"
}
  1. Connection Failures: Check credentials and network connectivity
  2. Permission Errors: Verify account has appropriate SharePoint permissions
  3. Configuration Conflicts: Check for conflicting policies or settings
  4. Script Timeouts: Increase timeout values for large tenants
Terminal window
# Enable detailed logging
$VerbosePreference = "Continue"
$DebugPreference = "Continue"
# Run in test mode first
Set-SharePointSyncClientRestriction -TestMode -Verbose -Debug
  1. Configuration Reset: Use SharePoint admin center to reset settings
  2. Backup Restoration: Restore from configuration backups
  3. Manual Configuration: Configure manually via admin center

This SharePoint Online sync client restriction script provides comprehensive control over OneDrive synchronization across your organization. By implementing tenant-level restrictions, domain filtering, and client blocking, you can ensure data security while maintaining productivity.

The script’s modular design allows for customization based on specific organizational requirements while maintaining security best practices and compliance with regulatory requirements.

Regular monitoring and maintenance of sync restrictions ensure continued effectiveness and help identify potential security issues before they impact your organization’s data protection posture.