Export full permission list for SHarepoint Online

Bruce Anderson 20 Reputation points
2024-05-18T10:40:06.4266667+00:00

We have a regular requirement going forward to provide to auditors a list of all of our Sharepoint sites, and the users and what permissions they have. I am hoping for a Powershell script, or report that exists somewhere that will do this. I have tried a few scripts that had issues, and cannot find any report. Any assistance would be greatly appreciated.

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

Accepted answer
  1. Ling Zhou_MSFT 14,295 Reputation points Microsoft Vendor
    2024-05-21T01:37:14.0433333+00:00

    Hi @Bruce Anderson,

    Thank you for your reply.

    Based on the error message you provided, it's likely that there was a problem installing PnP PowerShell Module. We recommend that you use PowerShell 7 to run PowerShell commands.

    Please follow the steps below to reinstall it:

    1.Check if the classic PnP PowerShell module is installed with the below command:

    Get-Module SharePointPnPPowerShellOnline -ListAvailable | Select-Object Name,Version | Sort-Object Version -Descending 
    

    This returns the Name and version of legacy PnP PowerShell installed on the machine (If any). Uninstall Any previous PnP PowerShell Modules for SharePoint Online installed:

    Uninstall-Module SharePointPnPPowerShellOnline -Force -AllVersions
    

    2.To install the new PnP PowerShell module, use:

    Install-Module PnP.PowerShell
    

    After reinstallation, please try to run PowerShell again, make sure your TenantAdmin URL is correct.


    If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    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.

    1 person found this answer helpful.
    0 comments No comments

3 additional answers

Sort by: Most helpful
  1. Ling Zhou_MSFT 14,295 Reputation points Microsoft Vendor
    2024-05-20T07:22:48.8966667+00:00

    Hi @Bruce Anderson,

    Thank you for posting in this community.

    Since SharePoint focuses on permissions, we can only use PowerShell to get a report of permissions for all site collections for which someone has site Admin or site owner permissions. This means that you can only get permission reports for site collections that you have set as site Admin and site owner using your account.

    If your site has a limited number of administrators, you can run PowerShell a couple of times per account to consolidate the generated reports into a permissions report for all sites.

    Please try this PnP PowerShell:

    1.Install PnP PowerShell.

    2.

    #Function to Get Permissions Applied on a particular Object, such as: Web, List, Folder or List Item
    Function Get-PnPPermissions([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
                    $Folder = Get-PnPProperty -ClientObject $Object -Property Folder
                    $ObjectTitle = $Object.Folder.Name
                    $ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''),$Object.Folder.ServerRelativeUrl)
                }
                Else #File or List Item
                {
                    #Get the URL of the Object
                    Get-PnPProperty -ClientObject $Object -Property File, ParentList
                    If($Object.File.Name -ne $Null)
                    {
                        $ObjectType = "File"
                        $ObjectTitle = $Object.File.Name
                        $ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''),$Object.File.ServerRelativeUrl)
                    }
                    else
                    {
                        $ObjectType = "List Item"
                        $ObjectTitle = $Object["Title"]
                        #Get the URL of the List Item
                        $DefaultDisplayFormUrl = Get-PnPProperty -ClientObject $Object.ParentList -Property DefaultDisplayFormUrl                    
                        $ObjectURL = $("{0}{1}?ID={2}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''), $DefaultDisplayFormUrl,$Object.ID)
                    }
                }
            }
            Default
            {
                $ObjectType = "List or Library"
                $ObjectTitle = $Object.Title
                #Get the URL of the List or Library
                $RootFolder = Get-PnPProperty -ClientObject $Object -Property RootFolder    
                $ObjectURL = $("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''), $RootFolder.ServerRelativeUrl)
            }
        }
       
        #Get permissions assigned to the object
        Get-PnPProperty -ClientObject $Object -Property HasUniqueRoleAssignments, RoleAssignments
     
        #Check if Object has unique permissions
        $HasUniquePermissions = $Object.HasUniqueRoleAssignments
         
        #Loop through each permission assigned and extract details
        $PermissionCollection = @()
        Foreach($RoleAssignment in $Object.RoleAssignments)
        {
            #Get the Permission Levels assigned and Member
            Get-PnPProperty -ClientObject $RoleAssignment -Property RoleDefinitionBindings, Member
     
            #Get the Principal Type: User, SP Group, AD Group
            $PermissionType = $RoleAssignment.Member.PrincipalType
        
            #Get the Permission Levels assigned
            $PermissionLevels = $RoleAssignment.RoleDefinitionBindings | Select -ExpandProperty Name
     
            #Remove Limited Access
            $PermissionLevels = ($PermissionLevels | Where { $_ -ne "Limited Access"}) -join ","
     
            #Leave Principals with no Permissions
            If($PermissionLevels.Length -eq 0) {Continue}
     
            #Get SharePoint group members
            If($PermissionType -eq "SharePointGroup")
            {
                #Get Group Members
                $GroupMembers = Get-PnPGroupMember -Identity $RoleAssignment.Member.LoginName
                     
                #Leave Empty Groups
                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-PnPSitePermissionRpt()
    {
    [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 {
            #Connect to the Site
            Connect-PnPOnline -URL $SiteURL -Interactive
            #Get the Web
            $Web = Get-PnPWeb
     
            Write-host -f Yellow "Getting Site Collection Administrators..."
            #Get Site Collection Administrators
            $SiteAdmins = Get-PnPSiteCollectionAdmin
             
            $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($Web.Title)
            $Permissions | Add-Member NoteProperty URL($Web.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-PnPListItemsPermission([Microsoft.SharePoint.Client.List]$List)
            {
                Write-host -f Yellow "`t `t Getting Permissions of List Items in the List:"$List.Title
      
                #Get All Items from List in batches
                $ListItems = Get-PnPListItem -List $List -PageSize 500
      
                $ItemCounter = 0
                #Loop through each List item
                ForEach($ListItem in $ListItems)
                {
                    #Get Objects with Unique Permissions or Inherited Permissions based on 'IncludeInheritedPermissions' switch
                    If($IncludeInheritedPermissions)
                    {
                        Get-PnPPermissions -Object $ListItem
                    }
                    Else
                    {
                        #Check if List Item has unique permissions
                        $HasUniquePermissions = Get-PnPProperty -ClientObject $ListItem -Property HasUniqueRoleAssignments
                        If($HasUniquePermissions -eq $True)
                        {
                            #Call the function to generate Permission report
                            Get-PnPPermissions -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)'"
                }
            }
     
            #Function to Get Permissions of all lists from the given web
            Function Get-PnPListPermission([Microsoft.SharePoint.Client.Web]$Web)
            {
                #Get All Lists from the web
                $Lists = Get-PnPProperty -ClientObject $Web -Property Lists
       
                #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 "Exporting Permissions from List '$($List.Title)' in $($Web.URL)" -Status "Processing Lists $Counter of $($Lists.Count)"
     
                        #Get Item Level Permissions if 'ScanItemLevel' switch present
                        If($ScanItemLevel)
                        {
                            #Get List Items Permissions
                            Get-PnPListItemsPermission -List $List
                        }
     
                        #Get Lists with Unique Permissions or Inherited Permissions based on 'IncludeInheritedPermissions' switch
                        If($IncludeInheritedPermissions)
                        {
                            Get-PnPPermissions -Object $List
                        }
                        Else
                        {
                            #Check if List has unique permissions
                            $HasUniquePermissions = Get-PnPProperty -ClientObject $List -Property HasUniqueRoleAssignments
                            If($HasUniquePermissions -eq $True)
                            {
                                #Call the function to check permissions
                                Get-PnPPermissions -Object $List
                            }
                        }
                    }
                }
            }
       
            #Function to Get Webs's Permissions from given URL
            Function Get-PnPWebPermission([Microsoft.SharePoint.Client.Web]$Web)
            {
                #Call the function to Get permissions of the web
                Write-host -f Yellow "Getting Permissions of the Web: $($Web.URL)..." 
                Get-PnPPermissions -Object $Web
       
                #Get List Permissions
                Write-host -f Yellow "`t Getting Permissions of Lists and Libraries..."
                Get-PnPListPermission($Web)
     
                #Recursively get permissions from all sub-webs based on the "Recursive" Switch
                If($Recursive)
                {
                    #Get Subwebs of the Web
                    $Subwebs = Get-PnPProperty -ClientObject $Web -Property Webs
     
                    #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-PnPWebPermission($Subweb)
                        }
                        Else
                        {
                            #Check if the Web has unique permissions
                            $HasUniquePermissions = Get-PnPProperty -ClientObject $SubWeb -Property HasUniqueRoleAssignments
       
                            #Get the Web's Permissions
                            If($HasUniquePermissions -eq $true)
                            {
                                #Call the function recursively                           
                                Get-PnPWebPermission($Subweb)
                            }
                        }
                    }
                }
            }
     
            #Call the function with RootWeb to get site collection permissions
            Get-PnPWebPermission $Web
       
            Write-host -f Green "`n*** Site Permission Report Generated Successfully!***"
         }
        Catch {
            write-host -f Red "Error Generating Site Permission Report!" $_.Exception.Message
       }
    }
    #Connect to Admin Center
    $TenantAdminURL = "https://contoso-admin.SharePoint.com"
    Connect-PnPOnline -Url $TenantAdminURL -Interactive   
    #Get All Site collections - Exclude: Seach Center, Redirect site, Mysite Host, App Catalog, Content Type Hub, eDiscovery and Bot Sites
    $SitesCollections = Get-PnPTenantSite | Where -Property Template -NotIn ("SRCHCEN#0","REDIRECTSITE#0", "SPSMSITEHOST#0", "APPCATALOG#0", "POINTPUBLISHINGHUB#0", "EDISC#0", "STS#-1")
       
    #Loop through each site collection
    ForEach($Site in $SitesCollections)
    {
        #Connect to site collection
        $SiteConn = Connect-PnPOnline -Url $Site.Url -Interactive
        Write-host "Generating Report for Site:"$Site.Url
     
        #Call the Function for site collection
        $ReportFile = "C:\Temp\$($Site.URL.Replace('https://','').Replace('/','_')).CSV"
        Generate-PnPSitePermissionRpt -SiteURL $Site.URL -ReportFile $ReportFile -Recursive
    }
    
    

    Reference: SharePoint Online: Get Site Permissions Report using PowerShell Note: Microsoft is providing this information as a convenience to you. The sites are not controlled by Microsoft. Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. Please make sure that you completely understand the risk before retrieving any suggestions from the above link. 


    If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    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.

    0 comments No comments

  2. Bruce Anderson 20 Reputation points
    2024-05-20T23:18:27.7133333+00:00

    Many thanks. That would be absolutely suitable, we have the one admin account under which all sites it is an owner. I was able to get PnP Powershell installed without error. But then the below when I run the script. Probably doing something very basic incorrectly...


    Connect-PnPOnline : The term 'Connect-PnPOnline' is not recognized as the name of a cmdlet, function, script file, or

    operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

    0 comments No comments

  3. Bruce Anderson 20 Reputation points
    2024-05-21T06:05:23.9+00:00

    Much appreciated. That worked perfectly.

    0 comments No comments