【PowerShell】SharePointの複数サイトに一括で権限付与する

# はじめに
**この記事ではWindows PowerShell ISEのバージョン5.1.19041.1645を使用しています。**
今回はSharePointのサイトにそれぞれ権限を付与するためのツールをご紹介します。
サイト数が増えてくると意外と面倒なのが権限設定です。

<font color="Red">**継承を毎回切って再設定しないといけないサイトがある…**</font>
<font color="Red">**UIでも設定できるけど設定フローが意外とある…**</font>

…など数サイトであれば気にならない作業も100, 500, 1000と増えると地獄です。
しかしサイトを複数作った直後等に今回のツールをご使用いただければ、そこら辺は幾分楽になると思います。…多分。そうであってほしい。

ちなみにサイトの一括作成に関しては以下で紹介させていただいております。もし必要であればご参照ください。
[【PowerShell】SharePoint上に複数サイトを一括で作成する](https://qiita.com/W0rker/items/0b5b2b1d4188efd35306 "サイト作成")

# やり方
用意するファイルは以下です。
- ps1ファイル
- ps1ファイルに読み込ませるxmlファイル
- xmlファイルに読み込ませるcsvファイル

## ps1ファイル
ps1ファイルの内容は以下です。

```powershell:siteAddPermission.ps1
#モジュールをコンソールにインポート
if ($null -eq (Get-PSSnapin -Name Microsoft.SharePoint.Powershell -ErrorAction SilentlyContinue)) {
    Add-PsSnapin Microsoft.SharePoint.Powershell
}

#メッセージ関数
function Messages ($category) {
    
    #出力XML
    $scriptPath = "ログを出力する先のパス"
    $xml01 = [System.Xml.XmlDocument](Get-Content -Encoding UTF8 -Raw $scriptPath\output.xml)
    $outputPath = [string]$xml01.outputfile.log

    if($category -eq "Start"){

        #処理時間を定義
        $time = Get-Date
        #処理開始
        $Message = "$time`r`n==処理を開始します==" | out-file $outputPath -Append
        return $Message
    
    }elseif($category -eq "Success"){

        #処理時間を定義
        $time = Get-Date
        #正常終了
        $Message = "$time`r`nスクリプトは正常に実行されました" | out-file $outputPath -Append
        return $Message

    }elseif($category -eq "Error"){

        #処理時間を定義
        $time = Get-Date
        #エラー発生
        $Error01 = "$time`r`nスクリプトに次のエラーが発生しました" | out-file $outputPath -Append
        $Error02 = $error[0] | Format-List -force | out-file $outputPath -Append
        $Error03 = "Error Occurring part  : $siteName" | out-file $outputPath -Append
        $Message = $Error01 + $Error02 +$Error03
        return $Message

    }elseif($category -eq "End"){

        #処理時間を定義
        $time = Get-Date
        #処理終了
        $Message = "$time`r`n==処理を終了します==`r`n" | out-file $outputPath -Append
        return $Message
    }
}

#権限グループ関数
function Groups ($type) {
    
    #SharePoint グループの場合
    if($type -eq "SharePoint グループ") {

        if($permissionName.Contains("所有者")) {

            #ユーザー情報取得
            $ownerGroup = $web.AssociatedOwnerGroup
            return $ownerGroup

        }elseif($permissionName.Contains("メンバー")) {

            #ユーザー情報取得
            $memberGroup = $web.AssociatedMemberGroup
            return $memberGroup

        }elseif($permissionName.Contains("閲覧者")) {

            #ユーザー情報取得
            $visitorGroup = $web.AssociatedVisitorGroup
            return $visitorGroup
        
        #上記のどれにも当てはまらない場合
        }else{
            
            if($permission -eq "フル コントロール") {
                
                #ユーザー情報取得
                $ownerGroup = $web.AssociatedOwnerGroup
                return $ownerGroup

            }elseif($permission -eq "編集") {
                
                #ユーザー情報取得
                $memberGroup = $web.AssociatedMemberGroup
                return $memberGroup

            }elseif($permission -eq "読み取り") {
                
                #ユーザー情報取得
                $visitorGroup = $web.AssociatedVisitorGroup
                return $visitorGroup

            }
        }

    #セキュリティグループの場合
    }elseif($type -eq "セキュリティグループ") {

        #ユーザー情報取得
        $AD = $web.Site.Rootweb.EnsureUser($permissionName)
        return $AD

    }
}

#処理開始
Messages Start

#エラー構文
try {

    #xml読み込み
    $scriptPath = [System.IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Definition)
    $xml = [System.Xml.XmlDocument](Get-Content -Encoding UTF8 -Raw $scriptPath\Config.xml)
    $csvPath = [string]$xml.files.content.item
    $line = @(Import-Csv $csvPath -Encoding Default)
    
    #ループ処理
    for ( $i=0; $i -lt $line.Length ;$i++) {

        #サイト権限付与のための変数を定義
        $siteUrl = $line[$i].SiteUrl
        $siteName = $line[$i].SiteName
        $type = $line[$i].Type
        $permission = $line[$i].Permission
        $permissionName = $line[$i].PermissionName

        #サイト情報取得
        $web = get-spweb $siteUrl -ErrorAction Stop
    
        #既存の権限をコピーして残さない処理
        $copyRoleAssignments = $false
        #権限の継承を中止
        $web.BreakRoleInheritance($copyRoleAssignments)
    
        #権限割り当ての器を作成
        $membersGroupAssignment = new-object Microsoft.SharePoint.SPRoleAssignment(Groups $type)
    
        #追加するアクセス許可レベル
        $membersRoleDefinition = $web.Site.RootWeb.RoleDefinitions[$permission]
        $membersGroupAssignment.RoleDefinitionBindings.Add($membersRoleDefinition)
        $web.RoleAssignments.Add($membersGroupAssignment)

        $web.Update()
        $web.Dispose()
            
     }

    #正常処理
    Messages Success

}catch {

    #異常処理
    Messages Error

}finally {

    #処理終了
    Messages End

}
```
\\$web.BreakRoleInheritance($copyRoleAssignments)の箇所で権限の継承を
一時的に切っています。

## xmlファイル
xmlファイルには後に権限付与するサイト情報を記載したcsvファイルのパスを指定した**config.xml**と実行結果のlogファイルの出力先パスを指定した**outputファイル**の2種類を作成します。
```xml:config.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><files>
 <content>
  <id>1</id>
  <item>csvファイルまでを含むパス</item>
 </content>
</files>
```

```xml:output.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><outputfile>
 <log>logファイルまでを含むパス</log>
</outputfile>
```

## csvファイル
ヘッダーにSiteUrl,SiteName,Type,Permission,PermissionNameを記載します。
左から権限付与したいサイトのURL、サイト名、種類、アクセス許可レベル、名前をそれぞれ入力します。

種類、アクセス許可レベル、名前はアクセス許可設定画面において以下の項目と紐づけています。
![SharePoint権限設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2669464/5ea0c9b1-47b3-7649-84c0-38d825a71dfc.png "各パラメータ対応イメージ")

# おわりに
AD内にユーザーが存在していることが前提ですが、権限の付与については以上です。
正直自分にもわかっていない箇所もあるのですが、ここもっとスマートにできるよ！等ご意見ありましたら
バンバン教えていただけると幸いです…。