La administración de permisos en SharePoint Online siempre es una tarea compleja, especialmente en entornos grandes. Otorgar permisos en SharePoint se vuelve engorroso cuando intenta clonar los derechos de acceso de un usuario existente. Considere este escenario: tiene un usuario existente en un departamento al que se le ha otorgado acceso a varios sitios de SharePoint, listas, carpetas, archivos, etc. y cuando un nuevo usuario se une a este departamento, usted, el administrador de SharePoint, obtiene el requisito de agregar un nuevo usuario a todos. los lugares con los mismos derechos de acceso que el miembro del equipo existente!
Entonces, ¿cómo clonar permisos de usuario en SharePoint Online? ¡No hay formas de copiar permisos de un usuario a otro usuario de manera inmediata! Debe recorrer la siguiente jerarquía de permisos, verificar si el usuario de origen tiene permisos y luego agregar el nuevo usuario manualmente. ¿Suena simple? ¡Esperar! ¡Esto será casi imposible cuando tenga un sitio más grande con muchos datos! No puede escanear miles de archivos en una biblioteca de documentos, ¿no es así?
¡Crear un grupo de AD, un grupo de SharePoint o un grupo de Microsoft 365 para administrar los permisos sería una opción! Entonces, simplemente puede agregar el nuevo usuario al grupo respectivo. El uso de herramientas de terceros como ShareGate, ControlPoint, el administrador de permisos de Boost Solutions sería otra opción que implica un costo. Bueno, hay otra opción gratuita. ¡Potencia Shell!
Jerarquía de permisos de SharePoint Online
Cualquier usuario en SharePoint Online obtiene acceso a través de estas formas:
- Agregado como administrador de la colección de sitios (o propietario principal)
- Permisos otorgados a nivel de sitio, ya sea como parte del grupo de SharePoint o con permisos directos
- Permisos otorgados a la lista o bibliotecas al romper la herencia
- Los derechos de acceso pueden ser a través de elementos de lista (archivo) o permisos de nivel de carpeta.
Entonces, si desea copiar los permisos de un usuario existente, debe revisar todos los objetos anteriores y luego otorgar permiso al nuevo usuario, si el usuario existente que desea copiar tiene permisos.
¡Debe ejecutar este script con permisos de administrador de la colección de sitios!
Script de PowerShell para clonar permisos de usuario en SharePoint Online
Usemos PowerShell para clonar los permisos de los usuarios. Este script itera a través de cada nivel de la jerarquía de permisos, como Colección de sitios, Subsitio, Lista y bibliotecas, Carpeta, Elemento de lista. Copia los permisos del usuario de origen dado al usuario de destino si el usuario de origen tiene permisos sobre él. Establezca los parámetros para las variables €SourceUser, €TargetUser y €SiteURL según corresponda y ejecute el script. Encontrará que el script genera texto de registro en la pantalla, dondequiera que copie los permisos.
#Function to copy user permissions Function Copy-PnPUserPermission(€SourceUser, €TargetUser, [Microsoft.SharePoint.Client.SecurableObject]€Object) { #Determine the type of the object Switch(€Object.TypedObject.ToString()) { "Microsoft.SharePoint.Client.Web" { €ObjectType = "Site" ; €ObjectURL = €Object.URL; €ObjectTitle = €Object.Title } "Microsoft.SharePoint.Client.ListItem" { If(€Object.FileSystemObjectType -eq "Folder") { €ObjectType = "Folder" ; €ObjectURL = €Object.FieldValues.FileRef; €ObjectTitle = €Object.FieldValues.FileLeafRef } ElseIf(€Object.FileSystemObjectType -eq "File") { €ObjectType = "File" ; €ObjectURL = €Object.FieldValues.FileRef; €ObjectTitle = €Object.FieldValues.FileLeafRef } Else { €ObjectType = "List Item"; €ObjectURL = €Object.FieldValues.FileRef ;€ObjectTitle = €Object.FieldValues.Title } } Default { €ObjectType = €Object.BaseType #List, DocumentLibrary, etc €ObjectTitle = €Object.Title #Get the URL of the List or Library €RootFolder = Get-PnPProperty -ClientObject €Object -Property RootFolder €ObjectURL = €Object.RootFolder.ServerRelativeUrl } } #Get all users and group permissions assigned to the object €RoleAssignments = Get-PnPProperty -ClientObject €Object -Property RoleAssignments #Get Direct Permissions applied to the Target User on the Object [email protected]() ForEach(€RoleAssignment in €RoleAssignments) { Get-PnPProperty -ClientObject €RoleAssignment -Property RoleDefinitionBindings, Member €TargetUserRA = €RoleAssignment | Where {€_.Member.PrincipalType -eq "User" -and €_.Member.LoginName -eq €TargetUser.LoginName} If(€TargetUserRA) { €TargetUserPermissions = €RoleAssignment.RoleDefinitionBindings | Select -ExpandProperty Name } } #Loop through each user or group associated with the object €TotalRoleAssignments = €Object.RoleAssignments.Count For(€i=0; €i -lt €TotalRoleAssignments; €i++) { €SourceRoleAssignment = €Object.RoleAssignments[€i] #Get all permission levels assigned to User account directly or via SharePoint Group [email protected]() Get-PnPProperty -ClientObject €SourceRoleAssignment -Property RoleDefinitionBindings, Member #Leave the Hidden Permissions If(€SourceRoleAssignment.Member.IsHiddenInUI -eq €False) { #Get the Permission Levels assigned €SourceUserPermissions = €SourceRoleAssignment.RoleDefinitionBindings | Select -ExpandProperty Name #Leave Principals with no Permissions assigned If(€SourceUserPermissions.Length -eq 0) {Continue} #Check Source Permissions granted directly or through SharePoint Group If(€SourceUserPermissions) { #Check if the Principal is SharePoint group If(€SourceRoleAssignment.Member.PrincipalType -eq "SharePointGroup") { #Get the Group Name €GroupName = €SourceRoleAssignment.Member.LoginName #Leave Limited Access Groups If(€GroupName -notlike "*limited access*" -and €GroupName -notlike "*SharingLinks*" -and €GroupName -notlike "*tenant*") { #Check if the Source user is member of the Group €SourceUserIsGroupMember = Get-PnPGroupMember -Identity €GroupName | Where {€_.LoginName -eq €SourceUser.LoginName} If(€SourceUserIsGroupMember -ne €null) { #Check if user is already member of the group - If not, Add to group €TargetUserIsGroupMember = Get-PnPGroupMember -Identity €GroupName | Where {€_.LoginName -eq €TargetUser.LoginName} If(€TargetUserIsGroupMember -eq €null) { ##Add Target User to the Source User's Group Add-PnPGroupMember -LoginName €TargetUser.LoginName -Identity €GroupName Write-Host -f Green "`tAdded user to the Group '€GroupName' on €ObjectType '€ObjectTitle' at '€ObjectURL'" } } } } ElseIf (€SourceRoleAssignment.Member.PrincipalType -eq "User" -and €SourceRoleAssignment.Member.LoginName -eq €SourceUser.LoginName) { #Add Each Direct permission (such as "Full Control", "Contribute") to the Target User ForEach(€SourceRoleDefinition in €SourceUserPermissions) { #Get the Permission Level €RoleDefinition = Get-PnPRoleDefinition -Identity €SourceRoleDefinition If(€RoleDefinition.Hidden -eq €false) { #Check if the Target User does not have the Permission Level already If(€TargetUserPermissions -notcontains €RoleDefinition.Name) { #Grant Source User's Permission Level to the Target User €RoleDefBinding = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection(€Object.Context) €RoleDefBinding.Add(€RoleDefinition) €Permissions = €Object.RoleAssignments.Add(€TargetUser,€RoleDefBinding) €Object.Update() Invoke-PnPQuery Write-Host -f Green "`tGranted €(€RoleDefinition.Name) Permission to the User on €ObjectType '€ObjectTitle' at '€ObjectURL'" } } } } } } } } #Function to Clone Permissions on the Web and its underlying objects such as Lists and Libraries, Folders and List Items Function Clone-PnPPermission { [cmdletbinding()] Param ( [Parameter(Mandatory=€True)] [Microsoft.SharePoint.Client.Web] €Web, [Parameter(Mandatory=€True)] [Microsoft.SharePoint.Client.User] €SourceUser, [Parameter(Mandatory=€True)] [Microsoft.SharePoint.Client.User] €TargetUser, [Parameter(Mandatory=€false)] [bool] €ScanSubsites, [Parameter(Mandatory=€false)] [bool] €ScanFolders, [Parameter(Mandatory=€false)] [bool] €ScanFiles ) #Call the function to clone permissions on the web Write-host -f Yellow "Scanning Permissions of the Web: €(€Web.URL)" Copy-PnPUserPermission -SourceUser €SourceUser -TargetUser €TargetUser -Object €Web #Clone Permissions on Lists Write-host "Scanning Permissions on Lists at €(€web.url)" -f Yellow #Exclude system lists €ExcludedLists = @("Site Assets","Preservation Hold Library","Style Library", "Site Collection Images","Site Pages", "Content and Structure Reports", "Form Templates", "Home Page Links", "Forms", "Workflow Tasks", "MicroFeed") €Lists = Get-PnPProperty -ClientObject €Web -Property Lists €Lists = €Lists | Where {(€_.Hidden -eq €false) -and €ExcludedLists -notcontains €_.Title} Foreach(€List in €Lists) { €ListHasUniquePermissions = Get-PnPProperty -ClientObject €List -Property HasUniqueRoleAssignments If(€List.HasUniqueRoleAssignments) { #Call the function to Copy Permissions to TargetUser on lists Copy-PnPUserPermission -SourceUser €SourceUser -TargetUser €TargetUser -Object €List } #Get List Items (and folders) If(€ScanFolders -or €ScanFiles) { #Get Items from List If(€List.ItemCount -gt 0) { €global:counter = 0; €AllListItems = Get-PnPListItem -List €List -PageSize 500 -Fields ID, FileSystemObjectType, FileLeafRef -ScriptBlock ` { Param(€items) €global:counter += €items.Count; Write-Progress -PercentComplete (€global:Counter / (€List.ItemCount) * 100) ` -Activity "Getting Items from List '€(€List.Title)'" -Status "Processing Items €global:Counter to €(€List.ItemCount)";} Write-Progress -Activity "Completed Retrieving Items from List €(€List.Title)" -Completed } } If(€ScanFolders) { #Clone Permissions on List folders Write-host "Scanning Permissions on Folders on List '€(€List.Title)'" -f Yellow #Get Folders from List Items €Folders = €AllListItems | Where { (€_.FileSystemObjectType -eq "Folder") -and (€_.FieldValues.FileLeafRef -ne "Forms") -and (-Not(€_.FieldValues.FileLeafRef.StartsWith("_")))} If(€Folders.count -gt 0) { €ItemCounter = 1 #Get Folder permissions Foreach(€Folder in €Folders) { Write-Progress -PercentComplete (€ItemCounter / (€Folders.Count) * 100) -Activity "Processing Folders €ItemCounter of €(€Folders.Count)" -Status "Searching Unique Permissions in Folders of List '€(€List.Title)'" €FolderHasUniquePermissions = Get-PnPProperty -ClientObject €Folder -Property HasUniqueRoleAssignments If(€FolderHasUniquePermissions -eq €True) { #Call the function to Copy Permissions to TargetUser Copy-PnPUserPermission -SourceUser €SourceUser -TargetUser €TargetUser -Object €folder } €ItemCounter++ } Write-Progress -Activity "Completed Cloning Folder Permissions on List €(€List.Title)" -Completed } } If(€ScanFiles) { Write-host "Scanning Permissions on Files/Items on List '€(€List.Title)'" -f Yellow #Get Files / List Items with Unique Permissions €ListItems = €AllListItems | Where { (€_.FileSystemObjectType -ne "Folder") } If(€ListItems.count -gt 0) { €ItemCounter = 1 #Get Item level permissions Foreach(€Item in €ListItems) { Write-Progress -PercentComplete (€ItemCounter / (€ListItems.Count) * 100) -Activity "Processing Items €ItemCounter of €(€ListItems.Count)" -Status "Searching Unique Permissions in Files/List Items of '€(€List.Title)'" €ItemHasUniquePermissions = Get-PnPProperty -ClientObject €Item -Property HasUniqueRoleAssignments If(€ItemHasUniquePermissions -eq €True) { #Call the function to Copy Permissions to TargetUser Copy-PnPUserPermission -SourceUser €SourceUser -TargetUser €TargetUser -Object €Item } €ItemCounter++ } Write-Progress -Activity "Completed Cloning Item Permissions on List €(€List.Title)" -Completed } } } } Function Clone-PnPUser { [cmdletbinding()] Param ( [Parameter(Mandatory=€True)] [String] €SiteURL, [Parameter(Mandatory=€True)] [String] €SourceUserEmail, [Parameter(Mandatory=€True)] [String] €TargetUserEmail, [Parameter(Mandatory=€false)] [bool] €ScanSubsites, [Parameter(Mandatory=€false)] [bool] €ScanFolders, [Parameter(Mandatory=€false)] [bool] €ScanFiles ) #Connect to PnP Online Connect-PnPOnline -Url €SiteURL -Interactive #Get the Context of the Root web €Ctx = Get-PnPContext #Prepare the source and target users €SourceUser = Get-PnPUser | Where-Object Email -eq €SourceUserEmail If(€SourceUser -eq €null) { €SourceUser = New-PnPUser -LoginName €SourceUserEmail } €TargetUser = Get-PnPUser | Where-Object Email -eq €TargetUserEmail If(€TargetUser -eq €null) { €TargetUser = New-PnPUser -LoginName €TargetUserEmail } #Check Whether the Source User is a Site Collection Administrator Write-host "Scanning Site Collection Administrators..." -f Yellow €SourceUserIsSiteAdmin = Get-PnPSiteCollectionAdmin | Where {€_.LoginName -eq €SourceUser.LoginName} If(€SourceUserIsSiteAdmin -ne €Null) { #Check if the target user is site collection admin already! €TargetUserIsSiteAdmin = Get-PnPSiteCollectionAdmin | Where {€_.LoginName -eq €TargetUser.LoginName} If(€TargetUserIsSiteAdmin -eq €Null) { #Add the Target user as Site Collection Admin Add-PnPSiteCollectionAdmin -Owners €TargetUser Write-host "Added Site Collection Administrator!" -f Green } } #Clone Permissions on the site and its underlying objects €Web = Get-PnPWeb Clone-PnPPermission -Web €Web -SourceUser €SourceUser -TargetUser €TargetUser -ScanSubsites €ScanSubSites -ScanFolders €ScanFolders -ScanFiles €ScanFiles #Call the function for subsites If(€ScanSubsites) { #Get all subsites €WebsCollection = Get-PnPSubWeb -Includes HasUniqueRoleAssignments #Loop throuh each SubSite (web) Foreach(€SubWeb in €WebsCollection) { If(€SubWeb.HasUniqueRoleAssignments -eq €True) { #Call the function to Copy Permissions to TargetUser Clone-PnPPermission -Web €SubWeb -SourceUser €SourceUser -TargetUser €TargetUser -ScanSubsites €ScanSubSites -ScanFolders €ScanFolders -ScanFiles €ScanFiles } } } Write-Host -f Green "*** Permission Cloned Successfully! *** " } #Define Parameters €SiteURL = "https://Crescent.sharepoint.com/sites/Marketing" €SourceUserEmail ="[email protected]" €TargetUserEmail ="[email protected]" #Call the function to clone user permissions Clone-PnPUser -SiteURL €SiteURL -SourceUserEmail €SourceUserEmail -TargetUserEmail €TargetUserEmail #Clone-PnPUser -SiteURL €SiteURL -SourceUserEmail €SourceUserEmail -TargetUserEmail €TargetUserEmail -ScanSubsites €true -ScanFolders €true -ScanFiles €True
Tenga en cuenta que este script no copia los permisos de grupo de Active Directory o Microsoft 365. Y tiene como ámbito el nivel de la colección de sitios. Por lo tanto, si desea clonar permisos para múltiples colecciones de sitios, debe llamar a la función «Clone-PnPUser» con las URL de sitios relevantes.
Esto sería extremadamente útil cuando un nuevo miembro del equipo reemplaza a un antiguo miembro del equipo. Con este script, todos los permisos del antiguo miembro del equipo pueden transferirse simplemente al nuevo miembro del equipo. No solo los permisos directos, sino que este script también agrega el usuario de destino a todos los grupos de SharePoint de los que forma parte el usuario de origen.