Migrating Custom Permissions Between SharePoint Sites using PnP PowerShell

Migrating custom permissions between SharePoint Online sites is crucial when restructuring content, consolidating sites, or ensuring consistent access control across environments. PnP PowerShell simplifies this task by automating the retrieval and application of permissions efficiently.


Key Considerations Before Migrating Permissions

Source and Destination Sites – Ensure both SharePoint sites exist.
Permission Levels – Migrate only custom permissions (not inherited ones).
Groups and Users – Validate that users and groups exist in the destination site.
Site Collection Admin Access – Ensure you have Full Control permissions.
Permission Inheritance – If needed, break inheritance in the destination site.


Step 1: Connect to Source and Destination Sites

First, establish a connection to both the source and destination SharePoint Online sites.

$sourceSite = "https://yourtenant.sharepoint.com/sites/SourceSite"
$destinationSite = "https://yourtenant.sharepoint.com/sites/DestinationSite"

# Connect to Source Site
Connect-PnPOnline -Url $sourceSite -Interactive

# Connect to Destination Site
Connect-PnPOnline -Url $destinationSite -Interactive

✔ Ensures authentication to perform permission operations.


Step 2: Retrieve Custom Permissions from Source Site

Extract and store custom permission levels, groups, and user permissions.

# Get all permission levels from the source site
$sourcePermissions = Get-PnPRoleDefinition

# Export permissions to a JSON file
$sourcePermissions | ConvertTo-Json -Depth 3 | Out-File "C:\SharePointPermissions.json"

Write-Host " Exported Permissions from Source Site."

✔ Saves permission details for later application.


Step 3: Migrate Custom Permissions to the Destination Site

Apply custom permission levels from the source site to the destination site.

# Import permissions from JSON file
$permissions = Get-Content "C:\SharePointPermissions.json" | ConvertFrom-Json

foreach ($permission in $permissions) {
# Create custom permission level if not exists
$existingRole = Get-PnPRoleDefinition | Where-Object { $_.Name -eq $permission.Name }
if (-not $existingRole) {
New-PnPRoleDefinition -Name $permission.Name -Permissions $permission.BasePermissions
Write-Host " Migrated Custom Permission Level: $($permission.Name)"
}
}

✔ Ensures that custom permissions are recreated in the destination site.


Step 4: Migrate SharePoint Groups and Users

Retrieve and migrate SharePoint groups and their members.

# Get all SharePoint Groups from the Source Site
$groups = Get-PnPGroup

foreach ($group in $groups) {
# Check if the group exists in the destination site
$existingGroup = Get-PnPGroup | Where-Object { $_.Title -eq $group.Title }

if (-not $existingGroup) {
# Create the group in the destination site
New-PnPGroup -Title $group.Title -Owner $group.OwnerTitle -AllowRequestToJoin $false
Write-Host "👥 Created Group: $($group.Title)"

# Add members to the group
$members = Get-PnPGroupMembers -Identity $group.Title
foreach ($member in $members) {
Add-PnPGroupMember -LoginName $member.LoginName -Group $group.Title
Write-Host " Added User: $($member.LoginName) to Group: $($group.Title)"
}
}
}

✔ Replicates SharePoint groups and restores membership.


Step 5: Apply Permissions to Libraries, Lists, and Items

To migrate specific library/list permissions, retrieve custom permissions and apply them.

# Get all lists from the source site
$lists = Get-PnPList

foreach ($list in $lists) {
# Get permissions on the list
$listPermissions = Get-PnPListItemPermission -List $list.Title

foreach ($permission in $listPermissions) {
# Break permission inheritance on the list in the destination site
Set-PnPList -Identity $list.Title -BreakRoleInheritance -CopyRoleAssignments -Force

# Apply permissions to the destination list
Grant-PnPListItemPermission -List $list.Title -User $permission.User -Role $permission.RoleDefinitionBindings
Write-Host "🔐 Applied Permissions to List: $($list.Title)"
}
}

✔ Ensures lists and libraries retain their original access controls.


Step 6: Validate and Generate a Report

Generate a CSV report to validate the permissions applied.

$report = @()
$destinationGroups = Get-PnPGroup

foreach ($group in $destinationGroups) {
$members = Get-PnPGroupMembers -Identity $group.Title
foreach ($member in $members) {
$report += [PSCustomObject]@{
GroupName = $group.Title
User = $member.LoginName
}
}
}

# Export the report
$report | Export-Csv -Path "C:\SharePointPermissionMigrationReport.csv" -NoTypeInformation
Write-Host " Migration Report Generated: C:\SharePointPermissionMigrationReport.csv"

✔ Confirms that permissions were successfully migrated.


Step 7: Cleanup and Final Check

Verify if all permission structures match the source site.

$sourceGroups = Get-PnPGroup
$destinationGroups = Get-PnPGroup

foreach ($group in $sourceGroups) {
if ($destinationGroups.Title -notcontains $group.Title) {
Write-Host " Missing Group in Destination: $($group.Title)"
}
}

✔ Helps detect any missing groups or permissions.

Leave a Reply

Your email address will not be published. Required fields are marked *