Last active
April 5, 2022 12:08
-
-
Save JohanSelmosson/7f7c1628e867e1213f7d1d92022f4c8f to your computer and use it in GitHub Desktop.
View Permissions on a folder structure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function GetFolderPermissionInfo { | |
[CmdletBinding()] | |
param ( | |
[Parameter()] | |
[string] | |
$Path = $(get-location).ProviderPath, | |
[switch] | |
$ExportCsv, | |
[string] | |
$CSVPath="ACLReport-$(get-date -Format "yyyy-MM-dd_HHmm").csv", | |
[string[]] | |
$ExcludeFolders | |
) | |
function ListFoldersWithRobocopy { | |
param( | |
[string]$Path, | |
[string[]]$ExcludeFolders | |
) | |
#remove trailing backslash if there is one, Robocopy does not approve of those. | |
$path = $path.TrimEnd('\') | |
#$strExcludeFoldersOption = $null | |
if ($ExcludeFolders) { | |
[string]$strExcludeFoldersOption = "/XD " | |
foreach ($item in $ExcludeFolders) { | |
$strExcludeFoldersOption = $strExcludeFoldersOption + " ""$($item.TrimEnd('\'))""" | |
} | |
} | |
Write-Verbose "scanning this path: $Path" | |
$psi = New-object System.Diagnostics.ProcessStartInfo | |
$psi.CreateNoWindow = $true | |
$psi.UseShellExecute = $false | |
$psi.RedirectStandardOutput = $true | |
$psi.RedirectStandardError = $true | |
$psi.FileName = 'robocopy' | |
# /L Logging only | |
# /S include Subfolders | |
# /NDL No Directory List - don’t log directory names. | |
# /XX eXclude "eXtra" files and dirs (present in destination but not source) | |
# /NC No Class - don’t log file classes. "New file" | |
# /NS No Size - don’t log file sizes. | |
# /NFL No File List | |
# /NJH No Job Header. | |
# /NJS No Job Summary. | |
# /FP Include Full Pathname of files in the output. | |
# /XD Exclude Directory | |
# /XJ Exclude Junction Points | |
# /LOG:c:\folder\filename.log | |
# /TEE Write to both log file and output to console | |
$psi.Arguments = @(' "{0}" NULL {1} /L /S /XX /NC /NS /NFL /NJH /NJS /XJ /FP ') -f $Path.ToString() ,$strExcludeFoldersOption | |
Write-Verbose $psi.Arguments | |
$process = New-Object System.Diagnostics.Process | |
$process.StartInfo = $psi | |
[void]$process.Start() | |
$process.PriorityClass = "BelowNormal" | |
$Output = new-object System.Collections.Generic.HashSet[string] | |
$Reader = $process.StandardOutput | |
while ($null -ne ($line = $reader.ReadLine())) { | |
Write-Verbose "$line" | |
if ($line -like '*\*') { | |
[void]$Output.Add( $line.trim() ) | |
Write-Verbose "Adding $line to the list " | |
} | |
if ($line.trim().Length -ge 260) { | |
Write-Warning "Path is $($line.trim().Length) characters long: $($line.trim())" | |
} | |
} | |
$process.WaitForExit() | |
$Output | |
} | |
if (! (Test-Path -Path $Path -PathType Container)) { | |
Write-Warning "Not a folder, exiting.." | |
break | |
} | |
$DirectoryToSearch = $Path | |
$host.UI.RawUI.WindowTitle = "Searching $DirectoryToSearch" | |
if ($null -ne $ExcludeFolders) { | |
$folders = ListFoldersWithRobocopy -path $DirectoryToSearch -ExcludeFolders $ExcludeFolders | |
} else { | |
$folders = ListFoldersWithRobocopy -path $DirectoryToSearch | |
} | |
#Lists uninherited acl:s + all acls at the top folder | |
$i = 1 | |
$NonInheritedACLs = ForEach ($Folder in $folders) { | |
try { | |
$Acl = Get-Acl -Path $Folder | |
} | |
catch { | |
[PSCustomObject]@{ | |
'Folder Name' = $Folder | |
'Principal' = 'Reading of ACL denied' | |
'AccessControlType' = 'n/a' | |
'Permissions' = 'n/a' | |
'AreAccessRuleProtected' = 'n/a' | |
'InheritanceFlags' = 'n/a' | |
'PropagationFlags' = 'n/a' | |
} | |
continue | |
} | |
ForEach ($Access in $Acl.Access) { | |
if (($Access.IsInherited -ne 'True') -or ($DirectoryToSearch.TrimEnd('\') -eq $folder.TrimEnd('\')) ) { | |
[PSCustomObject]@{ | |
'Folder Name' = $Folder | |
'Principal' = $Access.IdentityReference | |
'AccessControlType' = $Access.AccessControlType | |
'Permissions' = $Access.FileSystemRights | |
'AreAccessRuleProtected' = $ACL.AreAccessRulesProtected # True if inheritance is disabled on the folder | |
'InheritanceFlags' = $Access.InheritanceFlags | |
'PropagationFlags' = $Access.PropagationFlags | |
} | |
} | |
} | |
#print out the progress for every 50th folder processed | |
if ($i % 50 -eq 0) { | |
Write-Progress -activity "Reading ACL:s" -Status "$folder" -PercentComplete $([math]::Round(($i/($folders.count))*100)) | |
} | |
$i++ | |
} | |
Write-Progress -activity "Reading ACL:s" -Completed | |
if ($exportcsv) { | |
Write-Information "Exporting CSV to [$CSVPath]" | |
$NonInheritedACLs | Export-Csv -Path $CSVPath -UseCulture -NoTypeInformation -Encoding UTF8 | |
} | |
return $NonInheritedACLs | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment