OrphanedSid.psm1
|
#Requires -Version 5.1 # OrphanedSid PowerShell module # Finds access control entries in Active Directory that still grant rights to principals that no # longer exist, removes them with a backup of every ACL touched, and restores an ACL from that # backup. $ModuleRoot = $PSScriptRoot Write-Verbose "Initializing OrphanedSid module from: $ModuleRoot" # Classes first: several private functions constrain a parameter to one of these types, and a type # literal in a param block must already be defined when the file that uses it is parsed. $classFiles = Get-ChildItem -Path (Join-Path $ModuleRoot 'Classes') -Filter '*.ps1' -ErrorAction SilentlyContinue foreach ($class in $classFiles) { Write-Verbose "Loading class: $($class.Name)" . $class.FullName } # Private functions, one per file, grouped in folders by area. Logging\ goes first because every # other function logs through Write-StructuredLog, and its own files depend on # Initialize-LoggingConfiguration having defined the shared state. $privateRoot = Join-Path $ModuleRoot 'Private' $privateFolders = @( 'Logging' 'FileSystem' 'System' 'ActiveDirectory' 'Operations' 'SID' 'Security' 'ACL' 'Backup' 'Utilities' 'Reporting' 'Core' ) $loadedPrivate = foreach ($folder in $privateFolders) { $folderPath = Join-Path $privateRoot $folder foreach ($function in (Get-ChildItem -Path $folderPath -Filter '*.ps1' -ErrorAction SilentlyContinue)) { Write-Verbose "Loading private function: $($function.Name)" . $function.FullName $function.FullName } } # Any Private folder not named above still loads; the explicit list only fixes the order. $remaining = Get-ChildItem -Path $privateRoot -Filter '*.ps1' -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.FullName -notin $loadedPrivate } foreach ($function in $remaining) { Write-Verbose "Loading private function: $($function.Name)" . $function.FullName } # Public functions $publicFunctions = Get-ChildItem -Path (Join-Path $ModuleRoot 'Public') -Filter '*.ps1' -ErrorAction SilentlyContinue foreach ($function in $publicFunctions) { Write-Verbose "Loading public function: $($function.Name)" . $function.FullName } # Module-scope state shared by the private functions. A command sets these for the duration of # one run through Start-OrphanedSidSession and clears them in Stop-OrphanedSidSession. $script:Config = $null $script:MemoryManager = $null $script:Statistics = $null $script:StreamingResults = $null $script:RemovalResults = @() $script:CurrentDomainSID = $null $script:SIDValidationCache = @{} $script:SIDValidationCacheLookups = 0 $script:SIDValidationCacheHits = 0 Export-ModuleMember -Function @( 'Find-OrphanedSid' 'Remove-OrphanedSid' 'Restore-OrphanedSidBackup' ) $ExecutionContext.SessionState.Module.OnRemove = { Write-Verbose 'Cleaning up OrphanedSid module' foreach ($name in 'Config', 'MemoryManager', 'Statistics', 'StreamingResults', 'RemovalResults', 'CurrentDomainSID', 'SIDValidationCache') { Remove-Variable -Name $name -Scope Script -ErrorAction SilentlyContinue } } |