Permission management in SharePoint is always a complex task, especially in large environments. Granting permissions in SharePoint becomes cumbersome when you are trying to clone an existing user’s access rights. Consider this scenario: You have an existing user in a department granted access to various SharePoint web applications, sites, lists, files, etc., and when a new user joins this department, You-SharePoint Administrator get the requirement of adding a new user to all the places with same access rights as the existing team member!
How will you compare the access rights of an existing team member and grant access in bulk? He may be granted permission on various levels with different access rights. It would become very time-consuming to find and grant the same level of permissions to multiple users on multiple SharePoint objects. Existing users may be granted access as part of:
- Farm Administrator group and/or as part of web application policies
- Member of Site collection administrator group
- Permissions granted at site level either as part of SharePoint group or with direct permissions
- Permissions granted to list or libraries by breaking inheritance
- Access rights may be via List item or folder level permissions.
In short, permissions can be granted at the following levels in SharePoint:
Well, To copy permissions from one user to another user on the above levels, I’ve written this PowerShell script. It just scans all possible levels for the given source user’s access rights and grants permission to the target user.
Important: You must run this script as Farm Administrator! Otherwise, you’ll get “Access Denied” error!!
PowerShell script to clone SharePoint User Permissions:
This script iterates through each level as in the above image and copies permissions between given users at List Item/Folder, Lists, Site, Site Collection, Web Application, and Farm levels. Just change the parameters for variables $SourceUser, $TargetUser, and $WebAppURL accordingly and run the script. You’ll find the script outputs logs on the screen, wherever it copies permissions.
Add-PSSnapin
Microsoft.SharePoint.PowerShell
-ErrorAction
SilentlyContinue
#Function to copy user permissions
Function
Copy-UserPermissions
(
$SourceUserID
,
$TargetUserID
,
[Microsoft.SharePoint.SPSecurableObject]
$Object
)
{
#Determine the given Object type and Get URL of it
Switch
(
$Object
.GetType().FullName)
{
"Microsoft.SharePoint.SPWeb"
{
$ObjectType
=
"Site"
;
$ObjectURL
=
$Object
.URL;
$web
=
$Object
}
"Microsoft.SharePoint.SPListItem"
{
If
(
$Object
.Folder
-ne
$null
)
{
$ObjectType
=
"Folder"
;
$ObjectURL
=
"$($Object.Web.Url)/$($Object.Url)"
;
$web
=
$Object
.Web
}
Else
{
$ObjectType
=
"List Item"
;
$ObjectURL
=
"$($Object.Web.Url)/$($Object.Url)"
;
$web
=
$Object
.Web
}
}
#Microsoft.SharePoint.SPList, Microsoft.SharePoint.SPDocumentLibrary, Microsoft.SharePoint.SPPictureLibrary,etc
Default
{
$ObjectType
=
"List/Library"
;
$ObjectURL
=
"$($Object.ParentWeb.Url)/$($Object.RootFolder.URL)"
;
$web
=
$Object
.ParentWeb }
}
#Get Source and Target Users
$SourceUser
=
$Web
.EnsureUser(
$SourceUserID
)
$TargetUser
=
$Web
.EnsureUser(
$TargetUserID
)
#Get Permissions of the Source user on given object - Such as: Web, List, Folder, ListItem
$SourcePermissions
=
$Object
.GetUserEffectivePermissionInfo(
$SourceUser
)
#Iterate through each permission and get the details
ForEach
(
$SourceRoleAssignment
in
$SourcePermissions
.RoleAssignments)
{
#Get all permission levels assigned to User account directly or via SharePOint Group
$SourceUserPermissions
=@()
ForEach
(
$SourceRoleDefinition
in
$SourceRoleAssignment
.RoleDefinitionBindings)
{
#Exclude "Limited Accesses"
If
(
$SourceRoleDefinition
.Name
-ne
"Limited Access"
)
{
$SourceUserPermissions
+=
$SourceRoleDefinition
.Name
}
}
#Check Source Permissions granted directly or through SharePoint Group
If
(
$SourceUserPermissions
)
{
If
(
$SourceRoleAssignment
.Member
-is
[Microsoft.SharePoint.SPGroup]
)
{
$SourcePermissionType
=
"'Member of SharePoint Group - "
+
$SourceRoleAssignment
.Member.Name +
"'"
#Add Target User to the Source User's Group
#Get the Group
$Group
=
[Microsoft.SharePoint.SPGroup]
$SourceRoleAssignment
.Member
#Check if user is already member of the group - If not, Add to group
if
( (
$Group
.Users | where {
$_
.UserLogin
-eq
$TargetUserID
})
-eq
$null
)
{
#Add User to Group
$Group
.AddUser(
$TargetUser
)
#Write-Host Added to Group: $Group.Name
}
}
else
{
$SourcePermissionType
=
"Direct Permission"
#Add Each Direct permission (such as "Full Control", "Contribute") to Target User
ForEach
(
$NewRoleDefinition
in
$SourceUserPermissions
)
{
#Role assignment is a linkage between User object and Role Definition
$NewRoleAssignment
=
New-Object
Microsoft.SharePoint.SPRoleAssignment(
$TargetUser
)
$NewRoleAssignment
.RoleDefinitionBindings.Add(
$web
.RoleDefinitions[
$NewRoleDefinition
])
$object
.RoleAssignments.Add(
$NewRoleAssignment
)
$object
.Update()
}
}
$SourceUserPermissions
=
$SourceUserPermissions
-join
";"
Write-Host
"***$($ObjectType) Permissions Copied: $($SourceUserPermissions) at $($ObjectURL) via $($SourcePermissionType)***"
}
}
}
Function
Clone-SPUser(
$SourceUserID
,
$TargetUserID
,
$WebAppURL
)
{
###Check Whether the Source Users is a Farm Administrator ###
Write-host
"Scanning Farm Administrators Group..."
#Get the SharePoint Central Administration site
$AdminWebApp
=
Get-SPwebapplication
-includecentraladministration
| where {
$_
.IsAdministrationWebApplication}
$AdminSite
=
Get-SPWeb
$AdminWebApp
.Url
$AdminGroupName
=
$AdminSite
.AssociatedOwnerGroup
$FarmAdminGroup
=
$AdminSite
.SiteGroups[
$AdminGroupName
]
#Enumerate in farm administrators groups
ForEach
(
$user
in
$FarmAdminGroup
.users)
{
If
(
$User
.LoginName.Endswith(
$SourceUserID
,1))
#1 to Ignore Case
{
#Add the target user to Farm Administrator Group
$FarmAdminGroup
.AddUser(
$TargetUserID
,
[string]
::Empty,
$TargetUserID
,
[string]
::Empty)
Write-Host
"***Added to Farm Administrators Group!***"
}
}
### Check Web Application User Policies ###
Write-host
"Scanning Web Application Policies..."
$WebApp
=
Get-SPWebApplication
$WebAppURL
Foreach
(
$Policy
in
$WebApp
.Policies)
{
#Check if the search users is member of the group
If
(
$Policy
.UserName.EndsWith(
$SourceUserID
,1))
{
#Write-Host $Policy.UserName
$PolicyRoles
=@()
ForEach
(
$Role
in
$Policy
.PolicyRoleBindings)
{
$PolicyRoles
+=
$Role
}
}
}
#Add Each Policy found
If
(
$PolicyRoles
)
{
$WebAppPolicy
=
$WebApp
.Policies.Add(
$TargetUserID
,
$TargetUserID
)
ForEach
(
$Policy
in
$PolicyRoles
)
{
$WebAppPolicy
.PolicyRoleBindings.Add(
$Policy
)
}
$WebApp
.Update()
Write-host
"***Added to Web application Policies!***"
}
### Drill down to Site Collections, Webs, Lists & Libraries, Folders and List items ###
#Get all Site collections of given web app
$SiteCollections
=
Get-SPSite
-WebApplication
$WebAppURL
-Limit
All
#Convert UserID Into Claims format - If WebApp is claims based! Domain\User to i:0#.w|Domain\User
If
( (
Get-SPWebApplication
$WebAppURL
).UseClaimsAuthentication)
{
$SourceUserID
= (
New-SPClaimsPrincipal
-identity
$SourceUserID
-identitytype
1).ToEncodedString()
$TargetUserID
= (
New-SPClaimsPrincipal
-identity
$TargetUserID
-identitytype
1).ToEncodedString()
}
#Loop through all site collections
Foreach
(
$Site
in
$SiteCollections
)
{
#Prepare the Target user
$TargetUser
=
$Site
.RootWeb.EnsureUser(
$TargetUserID
)
Write-host
"Scanning Site Collection Administrators Group for:"
$site
.Url
###Check Whether the User is a Site Collection Administrator
Foreach
(
$SiteCollAdmin
in
$Site
.RootWeb.SiteAdministrators)
{
If
(
$SiteCollAdmin
.LoginName.EndsWith(
$SourceUserID
,1))
{
#Make the user as Site collection Admin
$TargetUser
.IsSiteAdmin =
$true
$TargetUser
.Update()
Write-host
"***Added to Site Collection Admin Group***"
}
}
#Get all webs
$WebsCollection
=
$Site
.AllWebs
#Loop throuh each Site (web)
Foreach
(
$Web
in
$WebsCollection
)
{
If
(
$Web
.HasUniqueRoleAssignments
-eq
$True
)
{
Write-host
"Scanning Site:"
$Web
.Url
#Call the function to Copy Permissions to TargetUser
Copy-UserPermissions
$SourceUserID
$TargetUserID
$Web
}
#Check Lists with Unique Permissions
Write-host
"Scanning Lists on $($web.url)..."
Foreach
(
$List
in
$web
.Lists)
{
If
(
$List
.HasUniqueRoleAssignments
-eq
$True
-and
(
$List
.Hidden
-eq
$false
))
{
#Call the function to Copy Permissions to TargetUser
Copy-UserPermissions
$SourceUserID
$TargetUserID
$List
}
#Check Folders with Unique Permissions
$UniqueFolders
=
$List
.Folders | where {
$_
.HasUniqueRoleAssignments
-eq
$True
}
#Get Folder permissions
If
(
$UniqueFolders
)
{
Foreach
(
$folder
in
$UniqueFolders
)
{
#Call the function to Copy Permissions to TargetUser
Copy-UserPermissions
$SourceUserID
$TargetUserID
$folder
}
}
#Check List Items with Unique Permissions
$UniqueItems
=
$List
.Items | where {
$_
.HasUniqueRoleAssignments
-eq
$True
}
If
(
$UniqueItems
)
{
#Get Item level permissions
Foreach
(
$item
in
$UniqueItems
)
{
#Call the function to Copy Permissions to TargetUser
Copy-UserPermissions
$SourceUserID
$TargetUserID
$Item
}
}
}
}
}
Write-Host
"Permission are copied successfully!"
}
#Define variables for processing
$WebAppURL
=
"https://sharepoint.crescent.com"
#Provide input for source and Target user Ids
$SourceUser
=
"Crescent\TonyW"
$TargetUser
=
"Crescent\Salaudeen"
#Call the function to clone user access rights
Clone-SPUser
$SourceUser
$TargetUser
$WebAppURL
Copy User Permissions at list level:
This script is broken into two functions: Copy-UserPermissions and Clone-SPSuer for convenience. Let’s say you want to copy permissions at the list level, then you can utilize the Copy-UserPermission function as:
This script clones user permissions at list level (copies at list level only, no drill-down to Folders and Items!).
$WebURL
=
"https://sharepoint.crescent.com/sites/sales"
$web
=
Get-SPWeb
$WebURL
$SourceUser
=
"i:0#.w|Crescent\TonyW"
$TargetUser
=
"i:0#.w|Crescent\Salaudeen"
$list
=
$Web
.Lists[
"Invoice"
]
#$folder = $list.Folders[0]
#$ListItem = $list.Items[0]
#Call the function to copy user permissions programmatically at LIST level
Copy-UserPermissions
$SourceUser
$TargetUser
$list