Búsqueda de sitios web

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


La gestión de permisos en SharePoint Online es siempre una tarea compleja, especialmente en entornos grandes. Otorgar permisos en SharePoint se vuelve engorroso cuando se 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, listas, carpetas, archivos, etc. de SharePoint y cuando un nuevo usuario se une a este departamento, usted, el administrador de SharePoint, tiene 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 de forma 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 tengas un sitio más grande con muchos datos! No se pueden 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 permisos sería una opción! Entonces, simplemente puedes agregar el nuevo usuario al grupo respectivo. El uso de herramientas de terceros como ShareGate, ControlPoint, Boost Solutions Permission manager sería otra opción que implica costos. Bueno, hay otra opción gratuita. ¡Potencia Shell!

Jerarquía de permisos en línea de SharePoint

Cualquier usuario de SharePoint Online obtiene acceso 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 de un grupo de SharePoint o con permisos directos
  • Permisos otorgados a listas o bibliotecas rompiendo la herencia
  • Los derechos de acceso pueden ser a través de permisos a nivel de elemento de lista (archivo) o 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 sobre él.

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 recorre en iteración 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 en consecuencia y ejecute el script. Encontrará que el script genera el texto del 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
    $TargetUserPermissions=@()
    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
        $SourceUserPermissions=@()
        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 ="Salaudeen@Crescent.com"
$TargetUserEmail ="Steve@Crescent.com"
 
#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 esta secuencia de comandos no copia los permisos del grupo de Active Directory o del grupo de Microsoft 365. Y su alcance es el nivel de colección de sitios. Por lo tanto, si desea clonar permisos para varias colecciones de sitios, debe llamar a la función "Clone-PnPUser" con las URL del sitio relevantes.

Esto sería de gran ayuda 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 simplemente transferirse al nuevo miembro del equipo. No solo 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.

Artículos relacionados