権限継承を切っているファイルをPowerShellで見つける


背景

SharePoint Online には「リンクの取得」という、ファイルのURLを取得するとそのファイルに固有の権限を付与する(= 親からの権限継承を解除する)少し困った機能があります。

SharePoint Online リンクの取得機能について

何が困るのか?

「リンクの取得」機能をユーザーが使用する際に、この機能によってファイルの権限継承が切れることをユーザーに伝えるようなメッセージが表示されません。

また SharePoint はファイルサーバーに比べて、ファイル個々のフルパスを取得する方法が分かりづらいです。

そのため、アップロードしたファイルのパスをメールや Microsoft Teams に記載しようとしたユーザーによって

「お、リンクが取得できる機能があるのか。どれどれポチっと。(*`・ω・)ゞ 」

と気軽にこの機能が実行されてしまいます。

#もちろんこの場合ユーザーは悪くない!

するとどうなる?

この機能がユーザーによって使われると、サイトの管理者が意図しないところでアイテムレベルでの固有の権限設定が発生してしまいます。

そのため、以下のようなことが起こりえます。

・投稿権限を持つ担当者がファイルをアップロード

・担当者が「リンクの取得」を使ってファイルのURLを取得。このとき、知らずのうちにファイルの編集が可能なURLを生成してしまう。

・メールにこのURLをコピーして配信

・閲覧権限のみ付与されたひとが、メールを受け取ったURLからファイルを開くことでファイルの編集ができてしまう

この機能を知らなかったお客様から「どのファイルに固有権限が付与されてしまったか一覧で把握したい」と依頼されることがあります。

SharePoint には固有の権限が付与されたファイルを一覧表示する機能がない

SharePoint には固有の権限が付与されたファイルを一覧表示する機能がありません。

なのでPowerShell を使って実現します。

SharePoint PnP Cmdlets にある「Measure-PnPList」を使うと、固有の権限が付与されたファイル(正確にはアイテム)を見つけられます。

Measure-PnPList で BrokePermissions パラメータと ItemLevel パラメータを合わせて使用すると以下の情報が返ってきます。

  • 固有の権限を持っているフォルダのURL
  • 固有の権限を持っているアイテムの親フォルダのURL + アイテムのID

「Measure-PnPList」の結果をもとに欲しい情報を取得する

上記の通り、「Measure-PnPList」の結果だけでは該当ファイルのURLや実際に付与されている権限がわかりません。なので、以下のようにして該当の ListItem オブジェクトを取得します。

foreach($web in $webs)
{
    $lists = Get-PnPList -Web $web -Includes "DefaultNewFormUrl"

    foreach($list in $lists)
    {
        #「固有の権限を持つフォルダ」と「固有の権限を持つアイテム」を取得
        $listItemThatHasUniqueRoleAssignments = @()
        $listItemThatHasUniqueRoleAssignments += Measure-PnPList -Web $web -Identity $list.Id.Guid -BrokenPermissions -ItemLevel

        if($listItemThatHasUniqueRoleAssignments.Count -eq 0){ continue }

        foreach($item in $listItemThatHasUniqueRoleAssignments)
        {
            if($item.Contains(":") -eq $false)
            {
                continue
            } 
            elseif($list.DefaultNewFormUrl.EndsWith("/Forms/Upload.aspx") -or $list.DefaultNewFormUrl.EndsWith("/Forms/UploadEx.aspx"))
            {
         $listItemID = $item.Split(":")[1]   
         $listItem = Get-PnPListItem -Web $web -List $list.Id -Id $listItemID

         ## 【欲しい情報をCSVに出力】 ##
            }
        } #foreach($item in $listItemThatHasUniqueRoleAssignments)
    }#foreach($list in $lists)
}#foreach($web in $webs)