¿Cómo copiar permisos de usuario en SharePoint Online usando PowerShell?

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.