Add orphaned folder ACL cleanup script
This commit is contained in:
133
Sonstiges/Remove-OrphanedFolderAclEntries.ps1
Normal file
133
Sonstiges/Remove-OrphanedFolderAclEntries.ps1
Normal file
@@ -0,0 +1,133 @@
|
||||
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
|
||||
param(
|
||||
[Parameter(Mandatory = $true, Position = 0)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function Test-OrphanedSid {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[System.Security.Principal.SecurityIdentifier]$Sid
|
||||
)
|
||||
|
||||
try {
|
||||
[void]$Sid.Translate([System.Security.Principal.NTAccount])
|
||||
return $false
|
||||
}
|
||||
catch [System.Security.Principal.IdentityNotMappedException] {
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
function Get-TargetDirectories {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$RootPath
|
||||
)
|
||||
|
||||
$rootItem = Get-Item -LiteralPath $RootPath
|
||||
if (-not $rootItem.PSIsContainer) {
|
||||
throw "Der Pfad '$RootPath' ist kein Ordner."
|
||||
}
|
||||
|
||||
$directories = New-Object System.Collections.Generic.List[System.IO.DirectoryInfo]
|
||||
$directories.Add([System.IO.DirectoryInfo]$rootItem)
|
||||
|
||||
foreach ($directory in Get-ChildItem -LiteralPath $RootPath -Directory -Recurse -Force) {
|
||||
if (($directory.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -ne 0) {
|
||||
Write-Warning "Ueberspringe Reparse-Point: $($directory.FullName)"
|
||||
continue
|
||||
}
|
||||
|
||||
$directories.Add([System.IO.DirectoryInfo]$directory)
|
||||
}
|
||||
|
||||
return $directories
|
||||
}
|
||||
|
||||
function Remove-OrphanedAclEntriesFromDirectory {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[System.IO.DirectoryInfo]$Directory
|
||||
)
|
||||
|
||||
$acl = Get-Acl -LiteralPath $Directory.FullName
|
||||
$rules = $acl.GetAccessRules($true, $false, [System.Security.Principal.SecurityIdentifier])
|
||||
|
||||
$orphanedRules = @()
|
||||
foreach ($rule in $rules) {
|
||||
$sid = [System.Security.Principal.SecurityIdentifier]$rule.IdentityReference
|
||||
if (Test-OrphanedSid -Sid $sid) {
|
||||
$orphanedRules += $rule
|
||||
}
|
||||
}
|
||||
|
||||
if ($orphanedRules.Count -eq 0) {
|
||||
return [pscustomobject]@{
|
||||
Path = $Directory.FullName
|
||||
CheckedRuleCount = $rules.Count
|
||||
RemovedRuleCount = 0
|
||||
RemovedIdentities = @()
|
||||
Changed = $false
|
||||
}
|
||||
}
|
||||
|
||||
$removedIdentities = New-Object System.Collections.Generic.List[string]
|
||||
|
||||
if ($PSCmdlet.ShouldProcess($Directory.FullName, "Remove $($orphanedRules.Count) orphaned ACL entries")) {
|
||||
foreach ($rule in $orphanedRules) {
|
||||
[void]$acl.RemoveAccessRuleSpecific($rule)
|
||||
$removedIdentities.Add($rule.IdentityReference.Value)
|
||||
}
|
||||
|
||||
Set-Acl -LiteralPath $Directory.FullName -AclObject $acl
|
||||
}
|
||||
|
||||
return [pscustomobject]@{
|
||||
Path = $Directory.FullName
|
||||
CheckedRuleCount = $rules.Count
|
||||
RemovedRuleCount = $orphanedRules.Count
|
||||
RemovedIdentities = $removedIdentities.ToArray()
|
||||
Changed = $orphanedRules.Count -gt 0
|
||||
}
|
||||
}
|
||||
|
||||
$resolvedPath = (Resolve-Path -LiteralPath $Path).Path
|
||||
$results = New-Object System.Collections.Generic.List[object]
|
||||
$errorCount = 0
|
||||
|
||||
foreach ($directory in Get-TargetDirectories -RootPath $resolvedPath) {
|
||||
try {
|
||||
$result = Remove-OrphanedAclEntriesFromDirectory -Directory $directory
|
||||
$results.Add($result)
|
||||
|
||||
if ($result.RemovedRuleCount -gt 0) {
|
||||
Write-Host ("[{0}] {1} verwaiste ACL-Eintraege in {2}" -f ($(if ($WhatIfPreference) { 'WHATIF' } else { 'OK' })), $result.RemovedRuleCount, $result.Path)
|
||||
foreach ($identity in $result.RemovedIdentities) {
|
||||
Write-Host (" - {0}" -f $identity)
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
$errorCount++
|
||||
Write-Warning ("Fehler bei {0}: {1}" -f $directory.FullName, $_.Exception.Message)
|
||||
}
|
||||
}
|
||||
|
||||
$checkedDirectories = $results.Count
|
||||
$changedDirectories = ($results | Where-Object { $_.Changed }).Count
|
||||
$removedRules = ($results | Measure-Object -Property RemovedRuleCount -Sum).Sum
|
||||
if ($null -eq $removedRules) {
|
||||
$removedRules = 0
|
||||
}
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'Zusammenfassung'
|
||||
Write-Host ('Gepruefte Ordner : {0}' -f $checkedDirectories)
|
||||
Write-Host ('Geaenderte Ordner: {0}' -f $changedDirectories)
|
||||
Write-Host ('Entfernte ACEs : {0}' -f $removedRules)
|
||||
Write-Host ('Fehler : {0}' -f $errorCount)
|
||||
Reference in New Issue
Block a user