SharePoint Online のライブラリでフォルダーごとに設定したアクセス権の一覧を作成する

SharePoint のチーム サイトは、プロジェクト チームなどで活用するとアクセス権は単純になりますが、組織で活用するとフォルダーごとにアクセス権を設定して、アクセス権が複雑になりがちです。あとからアクセス権の割り当ての一覧を作成するスクリプトを考えました。
組織で使用するとファイル数も多くなり5,000件を超えると Get-PnPListItem では一覧を作成できなくなります。Get-PnPFolderItem を使用してフォルダーに特化してアクセス権を取得できるようにしてみました。

``` PowerShell:Get-RoleAssignments.ps1
Param (
    [Parameter(Mandatory=$True)][string]$SiteURL,
    [Parameter(Mandatory=$True)][string]$LibraryName,
    [Parameter(Mandatory=$True)][string]$OutFile
)

New-Item -ItemType File -Force $OutFile

$folder ="/" + $LibraryName

#

Function get_SubFolders($folderUrl)
{

    $folders = Get-PnPFolderItem -FolderSiteRelativeUrl $folderUrl -ItemType Folder

    # Sub Folders
    foreach ($folder in $folders)
    {

        $ctx.Load($folder.ListItemAllFields)
        $ctx.ExecuteQuery()

        $item = $folder.ListItemAllFields

        Get-PnPProperty -ClientObject $item -Property HasUniqueRoleAssignments

        if ($item.HasUniqueRoleAssignments) {
            $ctx.load($item.RoleAssignments)
            $ctx.load($item.Folder)
            $ctx.ExecuteQuery()

            foreach ($RoleAssignments in $item.RoleAssignments) {
                $ctx.Load($RoleAssignments.Member)
                $ctx.Load($RoleAssignments.RoleDefinitionBindings)
                $ctx.ExecuteQuery()

                foreach($RoleDefinition in $RoleAssignments.RoleDefinitionBindings) {
                    if (!$RoleDefinition.Hidden) {
                        switch ($RoleAssignments.Member.PrincipalType) {
                            SharePointGroup {
                                $RoleDefinition |
                                Select-Object @{Name="Path";       Expression={$item.Folder.ServerRelativeUrl}},
                                              @{Name="Permission"; Expression={$_.Name}},
                                              @{Name="Type";       Expression={"SharePoint Group"}},
                                              @{Name="Role UPN";   Expression={$RoleAssignments.Member.LoginName}},
                                              @{Name="Role";       Expression={$RoleAssignments.Member.Title}} |
                                Export-CSV $OutFile -Append -Force -Encoding UTF8 -NoTypeInformation
                            }
                            default {
                                $RoleDefinition |
                                Select-Object @{Name="Path";       Expression={$item.Folder.ServerRelativeUrl}},
                                              @{Name="Permission"; Expression={$_.Name}} ,
                                              @{Name="Type";       Expression={"Security Group"}},
                                              @{Name="Role UPN";   Expression={$RoleAssignments.Member.TypedObject.Email}},
                                              @{Name="Role";       Expression={$RoleAssignments.Member.Title}} |
                                Export-CSV $OutFile -Append -Force -Encoding UTF8 -NoTypeInformation
                            }
                        }
                    }
                }
            }
        }

        $newFolderUrl = $folderUrl + "/" + $folder.Name
        get_SubFolders($newFolderUrl)
    }
}


# Connect PnP Online
Connect-PnPOnline -Url $SiteURL -UseWebLogin

# Get the Context
$ctx = Get-PnPContext

get_SubFolders($folder)

```