16

實用 PowerShell 小工具 - 產生資料夾權限清單

 3 years ago
source link: https://blog.darkthread.net/blog/list-dir-perm-w-ps/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
實用 PowerShell 小工具

跟同事聊到一個需求,異動 Windows 資料夾權限前希望能保留整個資料夾(含子目錄)的原有權限設定,作為異動前後對照或萬一操作失誤的還原參考。

基本上就是記錄檔案總管資料夾內容的安全性頁籤,將各群組或使用者名稱及其對映的完全控制、修改、讀取和執行... 等權限儲存下來,但要用程式完成:

按慣例,又是 PowerShell 展現威力的時刻。研究後發現,對 PowerShell 是件簡單任務,先 Get-ChildItem -Recurse -Directory 列出所有子資料夾,再 Get-ACL 取得權限設定就行了。有個眉角是子資料夾權限多半來自繼承,可以用推算的,逐一表列的意義不大,我們關心的重點在額外設定的權限,排除來自繼承的權限才不會模糊焦點。

故清單的輸出原則為:最上層目錄列舉所有權限,底下的子目錄若完全繼承上層權限就不顯示,權限與上層不同者也只會顯示多出的權限。

工具程式 List-Acl.ps1 的輸入參數有三個,$path 為查詢對象、$report 是開關參數,用來切換輸出權限物件集合或是 HTML 報表、$showInheritedPerms 也是開關,控制要不要印出繼承權限。

若目錄包含多層或大量子資料夾,遞迴查完得花上好一段時間,為避免使用者看不到進度陷入焦慮,我新學會用 Write-Progress 顯示目前處理的目錄名稱,能大幅提升使用者體驗。

List-Acl 的使用方式有兩種,第一種是輸出權限設定物件再轉換,像是接 ConvertTo-Json 轉成 JSON:

.\List-Acl.ps1 C:\WWW | ConvertTo-Json

第二種是加上 -report 參數輸出成 HTML 報表,所有權限一目瞭然,十分實用:(灰色為繼承權限,藍色為額外設定權限)

.\List-Acl.ps1 C:\WWW -report > D:\Resport.html

完整程式碼如下:

param (
    [Parameter(Mandatory = $true)]
    [string]$path,
    [switch]$report,
    [switch]$showInheritedPerms
)

function FileSysRightText($sysRights) {
    $t = $sysRights.ToString()
    if ([System.Text.RegularExpressions.Regex]::IsMatch($t, "^[-0-9]")) {
        return "Special"
    }
    return $t
}
function Bool2YN($bool) {
    if ($bool) { return "Y" }
    return "N"
}

function GetAclRecord([string]$path, [bool]$incInheritedPerms) {
    Write-Progress -Activity "$path"
    $acl = Get-Acl $path
    $access = $acl.Access
    if (!$incInheritedPerms) {
        $access = $access | Where-Object { !$_.IsInherited }
    }
    if ($access.Count -gt 0) {
        [PSCustomObject]@{
            Path   = $path;
            Access = ($access | ForEach-Object {
                    "$($_.IdentityReference)`t$($_.AccessControlType.ToString()[0])`t$(FileSysRightText $_.FileSystemRights)`t$(Bool2YN $_.IsInherited)"
                })
        }
    }
}

Clear-Host

$list = New-Object System.Collections.ArrayList

$list.Add((GetAclRecord $path $true)) | Out-Null
Get-ChildItem -Path $path -Directory -Recurse | ForEach-Object {
    $list.Add((GetAclRecord $_.FullName $showInheritedPerms)) | Out-Null
}

Clear-Host

if ($report) {
@"
    <!DOCTYPE html>
    <html><head><title>Permission Checklist for $path</title>
    <style>
        html,body,table { font-size: 10pt; font-family: 微軟正黑體; }
        table { border-collapse: collapse; }
        thead td { text-align: center; background-color: royalblue; color: white; }
        td { padding: 3px; border: 1px solid #bbb; }
        td[rowspan] { vertical-align: top; }
        td.Y { color: gray; }
        td.N { color: blue; }
    </style>
    </head><body><h3>$path Permission Checklist</h3>
    <table><thead><tr><td>Path</td><td>User</td><td>Rights</td></tr></thead>
    <tbody>
"@
    $list | Where-Object { $_.Path } | ForEach-Object {
        $acl = $_
        $first = $true
        $acl.Access | ForEach-Object {
            "<tr>"
            if ($first) {
                "<td rowspan=$($acl.Access.Count)>$($acl.Path)</td>"
                $first = $false
            }
            $p = $_.Split("`t")        
            "<td class='$($p[1]) $($p[3])'>$($p[0])</td><td class='$($p[1]) $($p[3])'>$($p[2])</td>"
            "</tr>"
        }
    }
    "</tbody></table></body></html>"
}
else {
    Write-Output $list
}

不到 100 行寫完這個實用小工具,自己也覺得滿意,是我近期的得意作品之一,分享給大家。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK