Export all user permission for all sharepoint sites and library

Raymond Tan 6 Reputation points
2021-10-05T19:09:50.49+00:00

Hi,

Will need help on exporting all user permission for all sharepoint sites and library.

Any cmdlet powershell to advise?

Thanks

SharePoint
SharePoint
A group of Microsoft Products and technologies used for sharing and managing content, knowledge, and applications.
10,211 questions
{count} votes

5 answers

Sort by: Most helpful
  1. Yi Lu_MSFT 17,471 Reputation points
    2021-10-06T09:02:06.423+00:00

    Hi anonymous user-2701
    You could use the following code to export a CSV file with user permissions for a whole site collection:

    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"  
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"  
          
    #Function to call a non-generic method Load  
    Function Invoke-LoadMethod([Microsoft.SharePoint.Client.ClientObject]$Object = $(throw "Please provide a Client Object"),[string]$PropertyName)  
    {  
       $Ctx = $Object.Context  
       $Load = [Microsoft.SharePoint.Client.ClientContext].GetMethod("Load")  
       $Type = $Object.GetType()  
       $ClientLoad = $load.MakeGenericMethod($type)  
          
       $Parameter = [System.Linq.Expressions.Expression]::Parameter(($type), $type.Name)  
       $Expression = [System.Linq.Expressions.Expression]::Lambda([System.Linq.Expressions.Expression]::Convert([System.Linq.Expressions.Expression]::PropertyOrField($Parameter,$PropertyName),[System.Object] ), $($Parameter))  
       $ExpressionArray = [System.Array]::CreateInstance($Expression.GetType(), 1)  
       $ExpressionArray.SetValue($Expression, 0)  
       $ClientLoad.Invoke($ctx,@($Object,$ExpressionArray))  
    }  
         
    #Function to Get Permissions Applied on a particular Object, such as: Web or List  
    Function Get-Permissions([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"  
                    #Get the URL of the Folder  
                    Invoke-LoadMethod -Object $Object -PropertyName "Folder"  
                    $Ctx.ExecuteQuery()  
                    $ObjectTitle = $Object.Folder.Name  
                    $ObjectURL = $("{0}{1}" -f $Ctx.Web.Url.Replace($Ctx.Web.ServerRelativeUrl,''),$Object.Folder.ServerRelativeUrl)  
                }  
                Else #File or List Item  
                {  
                    #Get the URL of the Object  
                    Invoke-LoadMethod -Object $Object -PropertyName "File"  
                    $Ctx.ExecuteQuery()  
                    If($Object.File.Name -ne $Null)  
                    {  
                        $ObjectType = "File"  
                        $ObjectTitle = $Object.File.Name  
                        $ObjectURL = $("{0}{1}" -f $Ctx.Web.Url.Replace($Ctx.Web.ServerRelativeUrl,''),$Object.File.ServerRelativeUrl)  
                    }  
                    else  
                    {  
                        $ObjectType = "List Item"  
                        $ObjectTitle = $Object["Title"]  
                        #Get the URL of the List Item  
                        Invoke-LoadMethod -Object $Object.ParentList -PropertyName "DefaultDisplayFormUrl"  
                        $Ctx.ExecuteQuery()  
                        $DefaultDisplayFormUrl = $Object.ParentList.DefaultDisplayFormUrl  
                        $ObjectURL = $("{0}{1}?ID={2}" -f $Ctx.Web.Url.Replace($Ctx.Web.ServerRelativeUrl,''), $DefaultDisplayFormUrl,$Object.ID)  
                    }  
                }  
            }  
            Default  
            {  
                $ObjectType = "List or Library"  
                $ObjectTitle = $Object.Title  
                #Get the URL of the List or Library  
                $Ctx.Load($Object.RootFolder)  
                $Ctx.ExecuteQuery()             
                $ObjectURL = $("{0}{1}" -f $Ctx.Web.Url.Replace($Ctx.Web.ServerRelativeUrl,''), $Object.RootFolder.ServerRelativeUrl)  
            }  
        }  
         
        #Check if Object has unique permissions  
        Invoke-LoadMethod -Object $Object -PropertyName "HasUniqueRoleAssignments"  
        $Ctx.ExecuteQuery()  
        $HasUniquePermissions = $Object.HasUniqueRoleAssignments  
         
        #Get permissions assigned to the object  
        $RoleAssignments = $Object.RoleAssignments  
        $Ctx.Load($RoleAssignments)  
        $Ctx.ExecuteQuery()  
          
        #Loop through each permission assigned and extract details  
        $PermissionCollection = @()  
        Foreach($RoleAssignment in $RoleAssignments)  
        {  
            $Ctx.Load($RoleAssignment.Member)  
            $Ctx.executeQuery()  
          
            #Get the Principal Type: User, SP Group, AD Group  
            $PermissionType = $RoleAssignment.Member.PrincipalType  
          
            #Get the Permission Levels assigned  
            $Ctx.Load($RoleAssignment.RoleDefinitionBindings)  
            $Ctx.ExecuteQuery()  
            $PermissionLevels = $RoleAssignment.RoleDefinitionBindings | Select -ExpandProperty Name  
       
            #Remove Limited Access  
            $PermissionLevels = ($PermissionLevels | Where { $_ -ne "Limited Access"}) -join ","  
            If($PermissionLevels.Length -eq 0) {Continue}  
       
            #Get SharePoint group members  
            If($PermissionType -eq "SharePointGroup")  
            {  
                #Get Group Members  
                $Group = $Ctx.web.SiteGroups.GetByName($RoleAssignment.Member.LoginName)  
                $Ctx.Load($Group)  
                $GroupMembers= $Group.Users  
                $Ctx.Load($GroupMembers)  
                $Ctx.ExecuteQuery()  
                If($GroupMembers.count -eq 0){Continue}  
                $GroupUsers = ($GroupMembers | Select -ExpandProperty Title) -join ","  
       
                #Add the Data to Object  
                $Permissions = New-Object PSObject  
                $Permissions | Add-Member NoteProperty Object($ObjectType)  
                $Permissions | Add-Member NoteProperty Title($ObjectTitle)  
                $Permissions | Add-Member NoteProperty URL($ObjectURL)  
                $Permissions | Add-Member NoteProperty HasUniquePermissions($HasUniquePermissions)  
                $Permissions | Add-Member NoteProperty Users($GroupUsers)  
                $Permissions | Add-Member NoteProperty Type($PermissionType)  
                $Permissions | Add-Member NoteProperty Permissions($PermissionLevels)  
                $Permissions | Add-Member NoteProperty GrantedThrough("SharePoint Group: $($RoleAssignment.Member.LoginName)")  
                $PermissionCollection += $Permissions  
            }  
            Else  
            {  
                #Add the Data to Object  
                $Permissions = New-Object PSObject  
                $Permissions | Add-Member NoteProperty Object($ObjectType)  
                $Permissions | Add-Member NoteProperty Title($ObjectTitle)  
                $Permissions | Add-Member NoteProperty URL($ObjectURL)  
                $Permissions | Add-Member NoteProperty HasUniquePermissions($HasUniquePermissions)  
                $Permissions | Add-Member NoteProperty Users($RoleAssignment.Member.Title)  
                $Permissions | Add-Member NoteProperty Type($PermissionType)  
                $Permissions | Add-Member NoteProperty Permissions($PermissionLevels)  
                $Permissions | Add-Member NoteProperty GrantedThrough("Direct Permissions")  
                $PermissionCollection += $Permissions  
            }  
        }  
        #Export Permissions to CSV File  
        $PermissionCollection | Export-CSV $ReportFile -NoTypeInformation -Append  
    }  
         
    #Function to get sharepoint online site permissions report  
    Function Generate-SPOSitePermissionRpt()  
    {     
    [cmdletbinding()]  
       
        Param   
        (     
            [Parameter(Mandatory=$false)] [String] $SiteURL,  
            [Parameter(Mandatory=$false)] [String] $ReportFile,          
            [Parameter(Mandatory=$false)] [switch] $Recursive,  
            [Parameter(Mandatory=$false)] [switch] $ScanItemLevel,  
            [Parameter(Mandatory=$false)] [switch] $IncludeInheritedPermissions         
        )   
        Try {  
            #Get Credentials to connect  
            $Cred= Get-Credential  
          
            #Setup the context  
            $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)  
            $Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)  
         
            #Get the Web & Root Web  
            $Web = $Ctx.Web  
            $RootWeb = $Ctx.Site.RootWeb  
            $Ctx.Load($Web)  
            $Ctx.Load($RootWeb)  
            $Ctx.ExecuteQuery()  
         
            Write-host -f Yellow "Getting Site Collection Administrators..."  
            #Get Site Collection Administrators  
            $SiteUsers= $RootWeb.SiteUsers  
            $Ctx.Load($SiteUsers)  
            $Ctx.ExecuteQuery()  
            $SiteAdmins = $SiteUsers | Where { $_.IsSiteAdmin -eq $true}  
               
            $SiteCollectionAdmins = ($SiteAdmins | Select -ExpandProperty Title) -join ","  
            #Add the Data to Object  
            $Permissions = New-Object PSObject  
            $Permissions | Add-Member NoteProperty Object("Site Collection")  
            $Permissions | Add-Member NoteProperty Title($RootWeb.Title)  
            $Permissions | Add-Member NoteProperty URL($RootWeb.URL)  
            $Permissions | Add-Member NoteProperty HasUniquePermissions("TRUE")  
            $Permissions | Add-Member NoteProperty Users($SiteCollectionAdmins)  
            $Permissions | Add-Member NoteProperty Type("Site Collection Administrators")  
            $Permissions | Add-Member NoteProperty Permissions("Site Owner")  
            $Permissions | Add-Member NoteProperty GrantedThrough("Direct Permissions")  
                     
            #Export Permissions to CSV File  
            $Permissions | Export-CSV $ReportFile -NoTypeInformation  
         
            #Function to Get Permissions of All List Items of a given List  
            Function Get-SPOListItemsPermission([Microsoft.SharePoint.Client.List]$List)  
            {  
                Write-host -f Yellow "`t `t Getting Permissions of List Items in the List:"$List.Title  
        
                $Query = New-Object Microsoft.SharePoint.Client.CamlQuery  
                $Query.ViewXml = "<View Scope='RecursiveAll'><Query><OrderBy><FieldRef Name='ID' Ascending='TRUE'/></OrderBy></Query><RowLimit Paged='TRUE'>$BatchSize</RowLimit></View>"  
        
                $ItemCounter = 0  
                #Batch process list items - to mitigate list threshold issue on larger lists  
                Do {   
                    #Get items from the list  
                    $ListItems = $List.GetItems($Query)  
                    $Ctx.Load($ListItems)  
                    $Ctx.ExecuteQuery()  
                  
                    $Query.ListItemCollectionPosition = $ListItems.ListItemCollectionPosition  
         
                    #Loop through each List item  
                    ForEach($ListItem in $ListItems)  
                    {  
                        #Get Objects with Unique Permissions or Inherited Permissions based on 'IncludeInheritedPermissions' switch  
                        If($IncludeInheritedPermissions)  
                        {  
                            Get-Permissions -Object $ListItem  
                        }  
                        Else  
                        {  
                            Invoke-LoadMethod -Object $ListItem -PropertyName "HasUniqueRoleAssignments"  
                            $Ctx.ExecuteQuery()  
                            If($ListItem.HasUniqueRoleAssignments -eq $True)  
                            {  
                                #Call the function to generate Permission report  
                                Get-Permissions -Object $ListItem  
                            }  
                        }  
                        $ItemCounter++  
                        Write-Progress -PercentComplete ($ItemCounter / ($List.ItemCount) * 100) -Activity "Processing Items $ItemCounter of $($List.ItemCount)" -Status "Searching Unique Permissions in List Items of '$($List.Title)'"  
                    }  
                } While ($Query.ListItemCollectionPosition -ne $null)  
            }  
       
            #Function to Get Permissions of all lists from the web  
            Function Get-SPOListPermission([Microsoft.SharePoint.Client.Web]$Web)  
            {  
                #Get All Lists from the web  
                $Lists = $Web.Lists  
                $Ctx.Load($Lists)  
                $Ctx.ExecuteQuery()  
         
                #Exclude system lists  
                $ExcludedLists = @("Access Requests","App Packages","appdata","appfiles","Apps in Testing","Cache Profiles","Composed Looks","Content and Structure Reports","Content type publishing error log","Converted Forms",  
                "Device Channels","Form Templates","fpdatasources","Get started with Apps for Office and SharePoint","List Template Gallery", "Long Running Operation Status","Maintenance Log Library", "Images", "site collection images"  
                ,"Master Docs","Master Page Gallery","MicroFeed","NintexFormXml","Quick Deploy Items","Relationships List","Reusable Content","Reporting Metadata", "Reporting Templates", "Search Config List","Site Assets","Preservation Hold Library"  
                "Site Pages", "Solution Gallery","Style Library","Suggested Content Browser Locations","Theme Gallery", "TaxonomyHiddenList","User Information List","Web Part Gallery","wfpub","wfsvc","Workflow History","Workflow Tasks", "Pages")  
                   
                $Counter = 0  
                #Get all lists from the web    
                ForEach($List in $Lists)  
                {  
                    #Exclude System Lists  
                    If($List.Hidden -eq $False -and $ExcludedLists -notcontains $List.Title)  
                    {  
                        $Counter++  
                        Write-Progress -PercentComplete ($Counter / ($Lists.Count) * 100) -Activity "Processing Lists $Counter of $($Lists.Count) in $($Web.URL)" -Status "Exporting Permissions from List '$($List.Title)'"  
       
                        #Get Item Level Permissions if 'ScanItemLevel' switch present  
                        If($ScanItemLevel)  
                        {  
                            #Get List Items Permissions  
                            Get-SPOListItemsPermission -List $List  
                        }  
       
                        #Get Lists with Unique Permissions or Inherited Permissions based on 'IncludeInheritedPermissions' switch  
                        If($IncludeInheritedPermissions)  
                        {  
                            Get-Permissions -Object $List  
                        }  
                        Else  
                        {  
                            #Check if List has unique permissions  
                            Invoke-LoadMethod -Object $List -PropertyName "HasUniqueRoleAssignments"  
                            $Ctx.ExecuteQuery()  
                            If($List.HasUniqueRoleAssignments -eq $True)  
                            {  
                                #Call the function to check permissions  
                                Get-Permissions -Object $List  
                            }  
                        }  
                    }  
                }  
            }  
         
            #Function to Get Web's Permissions from given URL  
            Function Get-SPOWebPermission([Microsoft.SharePoint.Client.Web]$Web)  
            {  
                #Get all immediate subsites of the site  
                $Ctx.Load($web.Webs)   
                $Ctx.executeQuery()  
          
                #Call the function to Get permissions of the web  
                Write-host -f Yellow "Getting Permissions of the Web: $($Web.URL)..."   
                Get-Permissions -Object $Web  
         
                #Get List Permissions  
                Write-host -f Yellow "`t Getting Permissions of Lists and Libraries..."  
                Get-SPOListPermission($Web)  
       
                #Recursively get permissions from all sub-webs based on the "Recursive" Switch  
                If($Recursive)  
                {  
                    #Iterate through each subsite in the current web  
                    Foreach ($Subweb in $web.Webs)  
                    {  
                        #Get Webs with Unique Permissions or Inherited Permissions based on 'IncludeInheritedPermissions' switch  
                        If($IncludeInheritedPermissions)  
                        {  
                            Get-SPOWebPermission($Subweb)  
                        }  
                        Else  
                        {  
                            #Check if the Web has unique permissions  
                            Invoke-LoadMethod -Object $Subweb -PropertyName "HasUniqueRoleAssignments"  
                            $Ctx.ExecuteQuery()  
         
                            #Get the Web's Permissions  
                            If($Subweb.HasUniqueRoleAssignments -eq $true)  
                            {  
                                #Call the function recursively                             
                                Get-SPOWebPermission($Subweb)  
                            }  
                        }  
                    }  
                }  
            }  
         
            #Call the function with RootWeb to get site collection permissions  
            Get-SPOWebPermission $Web  
         
            Write-host -f Green "`n*** Site Permission Report Generated Successfully!***"  
         }  
        Catch {  
            write-host -f Red "Error Generating Site Permission Report!" $_.Exception.Message  
       }  
    }  
         
    #region ***Parameters***  
    $SiteURL="https://crescenttech.sharepoint.com/sites/Marketing"  
    $ReportFile="C:\SitePermissionRpt.csv"  
    $BatchSize = 500  
    #endregion  
       
    #Call the function to generate permission report  
    Generate-SPOSitePermissionRpt -SiteURL $SiteURL -ReportFile $ReportFile  
    #Generate-SPOSitePermissionRpt -SiteURL $SiteURL -ReportFile $ReportFile -Recursive -ScanItemLevel -IncludeInheritedPermissions  
    

    If an Answer is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  2. Bram Beelprez 1 Reputation point
    2022-02-23T17:06:21.98+00:00

    Hi

    I have some issue with running the script. At line 158, which credentials should be entered here?

    0 comments No comments

  3. Thuan Phan 0 Reputation points
    2023-02-14T06:44:49.86+00:00

    Dear Yi Lu,

    Many thanks for your contribution of this code. It is very useful for me.

    Best regards,

    Thuan.

    0 comments No comments

  4. Bu_rak 0 Reputation points
    2023-02-25T16:43:21.5+00:00

    Hi,

    This is great except I could not find a way around MFA. I see a credentials window pop up but not MFA window. which i think is my problem.

    Where/how should I add '-interactive' so I can put my MFA code. assuming, this is the problem.

    please advise, I appreciate your help.

    on another note, this appears to pull one site at a time,

    would it be okay to add all of the sites I am looking for under '$SiteURL=' and enter in them all?

    0 comments No comments

  5. SR VSP 1,231 Reputation points
    2023-08-02T13:54:50.6266667+00:00

    Thank you so much for this script and it runs successfully. But it gets all Libraries at the site collection level and not fetching at Subsite level. I've have around 10 subsites it only fetches at the top level site collection.

    also the script is failing sometimes due to too many requests. Can we divide something like 10/15 libs at a time and pause the script like 60 seconds ...

    Please advise with any updated script ?

    0 comments No comments