134 lines
4.3 KiB
PowerShell
134 lines
4.3 KiB
PowerShell
[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)
|