【Windows】ファイルサーバ移行検証_アクセス権のエクスポート

PowerShell

はじめに

前回までに既存のファイルサーバからのデータコピーを実施したので、今回はファイルサーバのNTFSアクセス権を一括で取得スクリプトを紹介します。本記事はファイルサーバの移行を想定した検証をしていますが、ファイルサーバがADのドメイン環境下にあればこの必要ないかもしれないです。一方、ADが存在しない環境で動いているファイルサーバの場合、robocopyではアクセス権のデータコピーはできないので、現環境の状態を知ることは重要なことかと思います。

実際にアクセス権まで移行するどうかは設計時点で決めることかと思いますが、更改対象にどの程度設定が入っているかが分からないと、設計の交渉も難しいでしょう。現地で手動で収集するのは現実的ではない場合、スクリプトで一括取得できると大変便利です。

※本記事は下記のファイルサーバ移行検証の一部です。

構成

既存ファイルサーバ(データのコピー元
ホスト名:filesv-win-01
IPアドレス:172.16.1.137
OS:WindowsServer 2022

新規ファイルサーバ(データのコピー先)
ホスト名:filesv-win-02
IPアドレス:172.16.1.138
OS:WindowsServer 2022

エクスポート用のスクリプト

「ローカル用」と「リモート用」を紹介しています。

ローカル用

スクリプトを実行した端末の「E:\share」のNTFSアクセス権を取得するスクリプトです。

結果は「C:\work\export-csv」に格納格納されます。ファイル名に時刻が入るので、複数回実行しても一意のファイル名となります。(上書きされない)

$FolderPath = "E:\share"
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
# エクスポート先のファイルパスを指定します
$OutputFile = "C:\work\export-csv\ExportFolderPermissions_$timestamp.csv"

# ヘッダーを作成
$header = '"Folder","FileName","IdentityReference","FileSystemRights","AccessControlType","InheritanceFlags","PropagationFlags","IsInherited"'

# ヘッダーをファイルに書き込む
Add-Content -Path $OutputFile -Value $header -Encoding utf8

# フォルダのアクセス許可を再帰的に取得して CSV ファイルにエクスポートします
Get-ChildItem -Path $FolderPath -Recurse | ForEach-Object {
    $Item = $_
    if ($Item.PSIsContainer) {
        # フォルダのアクセス許可を取得
        $Acl = Get-Acl -Path $Item.FullName
        foreach ($Access in $Acl.Access) {
            $Output = New-Object PSObject -Property @{
                Folder = $Item.FullName
                FileName = ""
                IdentityReference = $Access.IdentityReference
                FileSystemRights = $Access.FileSystemRights
                AccessControlType = $Access.AccessControlType
                InheritanceFlags = $Access.InheritanceFlags
                PropagationFlags = $Access.PropagationFlags
                IsInherited = $Access.IsInherited
            }
            # データを追加
            $Output | Export-Csv -Path $OutputFile -Append -NoTypeInformation -Encoding utf8
        }
    } else {
        # ファイルのアクセス許可を取得
        $Acl = Get-Acl -Path $Item.FullName
        foreach ($Access in $Acl.Access) {
            $Output = New-Object PSObject -Property @{
                Folder = $Item.DirectoryName
                FileName = $Item.Name
                IdentityReference = $Access.IdentityReference
                FileSystemRights = $Access.FileSystemRights
                AccessControlType = $Access.AccessControlType
                InheritanceFlags = $Access.InheritanceFlags
                PropagationFlags = $Access.PropagationFlags
                IsInherited = $Access.IsInherited
            }
            # データを追加
            $Output | Export-Csv -Path $OutputFile -Append -NoTypeInformation -Encoding utf8
        }
    }
}

以下は出力されたCSVの一例です。

リモート用

以下は「\\172.16.1.137\share」宛に実行したものです。認証の関係でアクセス拒否にならないように注意してください。

# 資格情報の設定
$username = "jasm.ricecake24book.com\fileuser01"
$password = "Share_test01!"
# ドメインを含めたユーザー名とパスワードを指定
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($username, $securePassword)

# ネットワーク共有の既存の接続を解除
$netShare = "\\172.16.1.137\share"
$localPath = "Z:"  # 使用していないドライブレターを指定

# 既存の接続をすべて削除
$netUseOutput = net use
$netUseOutput -split "`n" | ForEach-Object {
    if ($_ -match $netShare -or $_ -match $localPath) {
        $parts = $_ -split '\s+'
        if ($parts.Length -gt 2) {
            $connection = $parts[2]
            net use $connection /delete /y
        }
    }
}

# 確認のため少し待機
Start-Sleep -Seconds 5

# ネットワーク共有をマウント
try {
    net use $localPath $netShare $password /user:$username

    # マウントされたパスを使用
    $FolderPath = "$localPath\"
    $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
    # エクスポート先のファイルパスを指定します
    $OutputFile = "C:\work\export-csv\ExportFolderPermissions_$timestamp.csv"

    # ヘッダーを作成
    $header = '"Folder","FileName","IdentityReference","FileSystemRights","AccessControlType","InheritanceFlags","PropagationFlags","IsInherited"'

    # ヘッダーをファイルに書き込む
    Add-Content -Path $OutputFile -Value $header -Encoding utf8

    # フォルダのアクセス許可を再帰的に取得して CSV ファイルにエクスポートします
    Get-ChildItem -Path $FolderPath -Recurse | ForEach-Object {
        $Item = $_
        if ($Item.PSIsContainer) {
            # フォルダのアクセス許可を取得
            $Acl = Get-Acl -Path $Item.FullName
            foreach ($Access in $Acl.Access) {
                $Output = New-Object PSObject -Property @{
                    Folder = $Item.FullName
                    FileName = ""
                    IdentityReference = $Access.IdentityReference
                    FileSystemRights = $Access.FileSystemRights
                    AccessControlType = $Access.AccessControlType
                    InheritanceFlags = $Access.InheritanceFlags
                    PropagationFlags = $Access.PropagationFlags
                    IsInherited = $Access.IsInherited
                }
                # データを追加
                $Output | Export-Csv -Path $OutputFile -Append -NoTypeInformation -Encoding utf8
            }
        } else {
            # ファイルのアクセス許可を取得
            $Acl = Get-Acl -Path $Item.FullName
            foreach ($Access in $Acl.Access) {
                $Output = New-Object PSObject -Property @{
                    Folder = $Item.DirectoryName
                    FileName = $Item.Name
                    IdentityReference = $Access.IdentityReference
                    FileSystemRights = $Access.FileSystemRights
                    AccessControlType = $Access.AccessControlType
                    InheritanceFlags = $Access.InheritanceFlags
                    PropagationFlags = $Access.PropagationFlags
                    IsInherited = $Access.IsInherited
                }
                # データを追加
                $Output | Export-Csv -Path $OutputFile -Append -NoTypeInformation -Encoding utf8
            }
        }
    }
} finally {
    # マウントを解除
    net use $localPath /delete /y
}

以上でエクスポートの紹介は終わりです。次回はエクスポートしたファイルをインポートするスクリプトを紹介します。