Set-StrictMode -Version Latest function Get-FolderPermissionMapping { <# .SYNOPSIS Audits folder permissions, focusing on explicit entries and "break points" in inheritance. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$Path ) process { # 1. Path Validation if (-not (Test-Path $Path)) { Write-Error "The path '$Path' does not exist or is unreachable." return } # 2. Setup Directory Structure $ReportPath = Join-Path -Path $PSScriptRoot -ChildPath "Reports" if (-not (Test-Path $ReportPath)) { New-Item -Path $ReportPath -ItemType Directory -Force | Out-Null } $Timestamp = Get-Date -Format "yyyyMMdd-HHmm" $FullFilePath = Join-Path -Path $ReportPath -ChildPath "PermissionAudit_$Timestamp.csv" Write-Host "--- Starting Audit on $Path ---" -ForegroundColor Cyan Write-Verbose "Output File: $FullFilePath" # 3. Get Local Shares $LocalShares = Get-CimInstance -ClassName Win32_Share | Select-Object Name, Path # 4. Define the Processing Logic (Reusable for Root and Subfolders) $ProcessFolder = { param($TargetFolder) try { $Acl = Get-Acl -Path $TargetFolder.FullName -ErrorAction Stop # IMPORTANT: We look for ANY entry that is NOT inherited. # These are the "Differences" from the parent. $ExplicitAccess = $Acl.Access | Where-Object { -not $_.IsInherited } if ($ExplicitAccess) { $MatchingShare = $LocalShares | Where-Object { $TargetFolder.FullName -like "$($_.Path)*" } | Select-Object -First 1 $ShareName = if ($MatchingShare) { $MatchingShare.Name } else { "Local/Sub-Folder" } foreach ($Access in $ExplicitAccess) { [PSCustomObject]@{ LocalPath = $TargetFolder.FullName ShareName = $ShareName Identity = $Access.IdentityReference Rights = $Access.FileSystemRights Inheritance = if ($Acl.AreAccessRulesProtected) { "Disabled" } else { "Enabled (Mixed)" } } | Export-Csv -Path $FullFilePath -Append -NoTypeInformation -Encoding utf8 } return $true } } catch { Write-Warning "Could not read ACL for: $($TargetFolder.FullName)" } return $false } # 5. Execution $FoundCount = 0 # Step A: Check the Root Folder first Write-Host "Checking Root: $Path" -ForegroundColor Gray $RootObj = Get-Item -Path $Path if (& $ProcessFolder $RootObj) { $FoundCount++ } # Step B: Scan all subfolders Write-Host "Scanning subfolders (this may take time)..." -ForegroundColor Gray Get-ChildItem -Path $Path -Recurse -Directory -ErrorAction SilentlyContinue | ForEach-Object { if (& $ProcessFolder $_) { $FoundCount++ # Visual feedback every time we find a unique folder Write-Host "[Found Unique] $($_.Name)" -ForegroundColor Green } } if (Test-Path $FullFilePath) { Write-Host "--- Audit Complete! ---" -ForegroundColor Cyan Write-Host "Results saved to: $FullFilePath" -ForegroundColor White } else { Write-Host "Scan finished, but no folders with unique/explicit permissions were found." -ForegroundColor Yellow } } }