Windows の共有アクセス権設定をエクスポート・インポートする方法

# この記事で説明すること
**※この記事で説明する内容は、Windows Server 2012 R2 / Windows 8.1 以降のOSバージョンが対象となります。**

1章では、記事を書いたきっかけを紹介します。（読み飛ばしてOK）
2章ではPowershellの簡単な説明をします。
3章・4章では共有アクセス権設定をエクスポート・インポートする方法を
順を踏んで説明します。

# 1. はじめに
Windows OS でアクセス権設定をする際は、共有アクセス権は「Domain Users」など大きいグループへ大きい権限を付与して、NTFSアクセス権で絞るように設定すると、新人の頃教わりました。
が、しかし、現場に出てみると長年の運用で熟成された複雑怪奇な共有アクセス権・NTFSアクセス権の設定がされていることが多々あります。

こういったケースでは、共有アクセス権設定をマニュアルで移行・復旧する場面で苦労をします。（データ移行時、ファイルレベルでの復旧時等）
DOSコマンドの permcopy で共有アクセス権をコピーする選択肢もありますが、共有アクセス権設定のコピー元となるサーバがオンライン状態で存在する必要があります。データ復旧時にはほとんどの場合存在しないと思いますし、データ移行時も移行計画の制約となりうると思います。

そこで、上記の課題を克服するためには
**「（可能な限り）自動で、なお且つ共有アクセス権設定のコピー元となるサーバがオフライン状態でも設定を再現できる」**必要があると考えました。
そして、これを実現するための手法として、**「共有アクセス権設定をエクスポート・インポートする方法」**を考案するに至りました。
同じような悩みをお持ちの方の参考になりますと幸いです。

この方法は **Powershell** を利用して実現するため、まずは Powershell について簡単に説明したいと思います。

# 2. Powershellとは？
> Windows PowerShell はマイクロソフトが開発した拡張可能なコマンドラインインターフェース (CLI) シェルおよびスクリプト言語である。オブジェクト指向に基づいて設計されており、.NET Frameworkを基盤としている。
https://ja.m.wikipedia.org/wiki/Windows_PowerShell

上の引用通り、PowerShellはMS-DOSと違い、オブジェクト指向で設計されたシェルです。
Powershellのコマンドは命名規則があり、「あのコマンド何だっけ？」という時も、その機能からコマンド名を推測しやすいのも特徴です。また、コマンドのタブ補完機能も有しています。


```
# 例1) ディレクトリの移動
PS D:\Tmp> Set-Location -Path D:\Tmp\share

PS D:\Tmp\share> 
```
```
# 例2) カレントディレクトリのパスを出力
PS D:\Tmp\share> Get-Location

Path        
----        
D:\Tmp\share
```

上の例のように、基本的にコマンドのアクション内容がコマンド名に表れています。

| アクション内容       |       コマンド名|  
|:-----------------|------------------:|
| 設定する          |           Set-〇〇|
| 取得する          |           Get-〇〇|
| 新規に設定する     |           New-〇〇|
| エクスポートする   |        Export-〇〇|
| インポートする     |        Import-〇〇| 


また、コマンドの結果はオブジェクトとして返されるため、以下のように変数に代入してメンバーへアクセスすることも可能です。

```
# 例3) カレントディレクトリのオブジェクトを変数に代入し、メンバーへアクセス
PS D:\Tmp\share> $pwd = Get-Location
PS D:\Tmp\share> $pwd.Path
D:\Tmp\share
```

以上を踏まえて、Powershellによる共有アクセス権設定のエクスポート・インポート方法を紹介していきます。

# 3. 共有アクセス権設定をエクスポートする方法
本章では、共有アクセス権設定をXmlファイルへエクスポートする方法を紹介します。

### 3.1 共有アクセス権設定を出力する
共有アクセス権設定を出力するコマンド **Get-SmbShare** を利用します。サブコマンド **-Special** に **$false** を指定することでデフォルトの共有アクセス権設定（ADMIN\$、C\$、IPC\$等）を省けます。

```
# 例4）共有アクセス権設定を出力
PS D:\Tmp> Get-SmbShare -Special $false

Name  ScopeName Path         Description
----  --------- ----         -----------
share *         D:\tmp\share            
Users *         C:\Users                
```


次のように、共有アクセス権設定のオブジェクトをパイプで渡し、メンバーの **Path** プロパティでフィルターをかけ、出力する内容を絞ることができます。

```
# 例5）Dドライブ上の共有アクセス権設定のみ出力
PS D:\Tmp> Get-SmbShare -Special $false | ? { $_.Path -like "D:\*" }

Name  ScopeName Path         Description
----  --------- ----         -----------
share *         D:\tmp\share     
```


### 3.2 オブジェクトをXmlファイルへエクスポートする
オブジェクトをXmlファイルへエクスポートするコマンド **Export-Clixml** を利用します。サブコマンド **-Path** に **Xmlを出力するパス** を指定できます。

共有アクセス権設定のオブジェクトをXmlファイルへエクスポートします。

```
# 例6）Dドライブ上の共有アクセス権設定をXmlファイルへエクスポート
PS D:\Tmp> $shareFolder = Get-SmbShare -Special $false | ? { $_.Path -like "D:\*" }

PS D:\Tmp> $shareFolder | Export-Clixml -Path D:\Tmp\SmbShare.xml
```

以上で、共有アクセス権設定をXmlファイルとして保存することができるようになりました。有事の備えとして、移行の仕掛けとして、大切に管理しておきましょう。


# 4. 共有アクセス権設定をインポートする方法
本章では、3章でエクスポートしたXmlファイルを元に共有アクセス権設定をインポートする方法を紹介します。

### 4.1 Xmlファイルからオブジェクトをインポートする
Xmlファイルからオブジェクトをインポートするコマンド **Import-Clixml** を利用します。サブコマンド **-Path** に **Xmlのパス** を指定できます。

共有アクセス権設定のオブジェクトをXmlファイルからインポートします。

```
# 例7）Dドライブ上の共有アクセス権設定をXmlファイルからインポート
PS D:\Tmp> Import-Clixml -Path D:\Tmp\SmbShare.xml

Name  ScopeName Path         Description
----  --------- ----         -----------
share *         D:\tmp\share     
```

インポートした共有アクセス権設定を詳細に出力する場合は、 **Get-SmbShareAccess** コマンドを利用します。インポートした共有アクセス権設定のオブジェクトをパイプで渡すことで、共有アクセス権設定を詳細に出力できます。

```
# 例8）インポートした共有アクセス権設定を詳細に出力
PS D:\Tmp> Import-Clixml -Path D:\Tmp\SmbShare.xml | Get-SmbShareAccess

Name  ScopeName AccountName AccessControlType AccessRight
----  --------- ----------- ----------------- -----------
share *         Everyone    Allow             Full     
```

### 4.2 共有アクセス権設定を反映する
**※共有アクセス権設定の反映を行う共有フォルダが存在しないことが前提となります。コマンドを実行すると、即座に共有されるため、共有アクセス権設定を十分に確認の上実行してください。**

共有アクセス権設定を新規に設定するコマンド **New-SmbShare** を利用します。インポートした共有アクセス権設定のオブジェクトをパイプで渡すことで、共有アクセス権設定を反映できます。


```
# 例9）インポートした共有アクセス権設定を反映
PS D:\Tmp> Import-Clixml -Path D:\Tmp\SmbShare.xml | New-SmbShare

Name  ScopeName Path         Description
----  --------- ----         -----------
share *         D:\Tmp\share            
```

インポートした共有アクセス権設定が反映されていることを詳細に出力して、確認します。

```
# 例10）共有アクセス権設定を詳細に出力
PS D:\Tmp> Get-SmbShare -Special $false |  Get-SmbShareAccess

Name  ScopeName AccountName            AccessControlType AccessRight
----  --------- -----------            ----------------- -----------
Users *         BUILTIN\Administrators Allow             Full       
Users *         Everyone               Allow             Full   
share *         Everyone    　　　　　　Allow             Full       
```

以上で、保存しておいたXmlファイルから共有アクセス権設定を復元するができました。

# あとがき

Powershell の記事という、非常にニッチな情報展開となりましたが、いつの日か、どこかでお役に立つことがありますと幸いです。
まだ AWS 関連の Powershell ネタが残っているのでそれを吐き出したら、PHP、Python ネタに走ろうと思います。

最後までお付き合いありがとうございました。

※本記事の内容に間違いがございましたら、訂正しますのでご指摘いただけますと幸いです。