<# .SYNOPSIS Audits a base directory for broken permission inheritance (closed-off folders). .DESCRIPTION Loops through all subfolders, identifies where inheritance is blocked, and exports an inventory to a CSV with a timestamped filename. .PARAMETER BaseDir The root directory path you want to scan. .PARAMETER ReportFolder The directory path where the final CSV report should be saved. .EXAMPLE .\FolderAudit.ps1 -BaseDir "C:\CompanyData" -ReportFolder "C:\AuditReports" #> param ( [Parameter(Mandatory = $true, HelpMessage = "Enter the base directory path to scan.")] [string]$BaseDir, [Parameter(Mandatory = $false, HelpMessage = "Enter the folder path where the report should be saved.")] [string]$ReportFolder = "C:\Temp\AuditReports" # Default backup path if not specified ) # Generate timestamped filename (Format: ddMMyyyy-HHmm) $TimeStamp = Get-Date -Format "ddMMyyyy-HHmm" $ReportName = "Permission_Audit_$TimeStamp.csv" $OutputFile = Join-Path -Path $ReportFolder -ChildPath $ReportName # Verify directories exist if (-not (Test-Path $BaseDir)) { Write-Error "The specified base directory does not exist: $BaseDir" exit } if (-not (Test-Path $ReportFolder)) { Write-Host "Report folder does not exist. Creating it now: $ReportFolder" -ForegroundColor Yellow New-Item -ItemType Directory -Path $ReportFolder -Force | Out-Null } Write-Host "Starting permission audit on: $BaseDir" -ForegroundColor Cyan Write-Host "Results will be saved to: $OutputFile" -ForegroundColor Cyan Write-Host "This may take some time depending on the size of the directory tree..." -ForegroundColor Yellow # Initialize array to hold results $Report = [System.Collections.Generic.List[PSCustomObject]]::new() # Get the base folder itself and all subfolders $Folders = Get-ChildItem -Path $BaseDir -Recurse -Directory -ErrorAction SilentlyContinue # Include the root folder in the audit $AllFolders = @($GetItem = Get-Item $BaseDir) + $Folders foreach ($Folder in $AllFolders) { try { # Get Access Control List (ACL) for the folder $Acl = Get-Acl -Path $Folder.FullName # Check if inheritance is blocked ($true means it IS protected/blocked) if ($Acl.AreAccessRulesProtected) { Write-Host "Found unique permissions: $($Folder.FullName)" -ForegroundColor Magenta # Extract names of users/groups with explicit access $ExplicitAccess = $Acl.Access | Where-Object { $_.IsInherited -eq $false } | ForEach-Object { $_.IdentityReference.Value } $ExplicitAccessString = $ExplicitAccess -join "; " # Append data to our report object $Report.Add([PSCustomObject]@{ "Folder Name" = $Folder.Name "Full Path" = $Folder.FullName "Inheritance Blocked"= $Acl.AreAccessRulesProtected "Explicit Access" = $ExplicitAccessString "Last Modified" = $Folder.LastWriteTime }) } } catch { Write-Warning "Permission denied or error reading: $($Folder.FullName)" } } # Export data to CSV if ($Report.Count -gt 0) { $Report | Export-Csv -Path $OutputFile -NoTypeInformation -Encoding UTF8 Write-Host "`nAudit complete! Found $($Report.Count) folders with unique/closed permissions." -ForegroundColor Green Write-Host "Results exported to: $OutputFile" -ForegroundColor Green } else { Write-Host "`nAudit complete. No folders with blocked inheritance were found." -ForegroundColor Green }