diff --git a/Functions/Get-FolderPermissionMapping.ps1 b/Functions/Get-FolderPermissionMapping.ps1 new file mode 100644 index 0000000..78a7a92 --- /dev/null +++ b/Functions/Get-FolderPermissionMapping.ps1 @@ -0,0 +1,93 @@ +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 + } + } +} \ No newline at end of file