GPOZaurr.psm1
function ConvertFrom-DistinguishedName { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER DistinguishedName Parameter description .PARAMETER ToOrganizationalUnit Parameter description .EXAMPLE $DistinguishedName = 'CN=Przemyslaw Klys,OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' ConvertFrom-DistinguishedName -DistinguishedName $DistinguishedName -ToOrganizationalUnit Output: OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz .EXAMPLE $DistinguishedName = 'CN=Przemyslaw Klys,OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' ConvertFrom-DistinguishedName -DistinguishedName $DistinguishedName Output: Przemyslaw Klys .NOTES General notes #> [CmdletBinding()] param([string[]] $DistinguishedName, [switch] $ToOrganizationalUnit, [switch] $ToDC, [switch] $ToDomainCN) if ($ToDomainCN) { $DN = $DistinguishedName -replace '.*?((DC=[^=]+,)+DC=[^=]+)$', '$1' $CN = $DN -replace ',DC=', '.' -replace "DC=" $CN } elseif ($ToOrganizationalUnit) { return [Regex]::Match($DistinguishedName, '(?=OU=)(.*\n?)(?<=.)').Value } elseif ($ToDC) { $DistinguishedName -replace '.*?((DC=[^=]+,)+DC=[^=]+)$', '$1' } else { $Regex = '^CN=(?<cn>.+?)(?<!\\),(?<ou>(?:(?:OU|CN).+?(?<!\\),)+(?<dc>DC.+?))$' $Output = foreach ($_ in $DistinguishedName) { $_ -match $Regex $Matches } $Output.cn } } function ConvertFrom-SID { [cmdletbinding()] param([string[]] $SID, [switch] $OnlyWellKnown, [switch] $OnlyWellKnownAdministrative) $WellKnownAdministrative = @{'S-1-5-18' = 'NT AUTHORITY\SYSTEM' } $wellKnownSIDs = @{'S-1-0' = 'Null AUTHORITY' 'S-1-0-0' = 'NULL SID' 'S-1-1' = 'WORLD AUTHORITY' 'S-1-1-0' = 'Everyone' 'S-1-2' = 'LOCAL AUTHORITY' 'S-1-2-0' = 'LOCAL' 'S-1-2-1' = 'CONSOLE LOGON' 'S-1-3' = 'CREATOR AUTHORITY' 'S-1-3-0' = 'CREATOR OWNER' 'S-1-3-1' = 'CREATOR GROUP' 'S-1-3-2' = 'CREATOR OWNER SERVER' 'S-1-3-3' = 'CREATOR GROUP SERVER' 'S-1-3-4' = 'OWNER RIGHTS' 'S-1-5-80-0' = 'NT SERVICE\ALL SERVICES' 'S-1-4' = 'Non-unique Authority' 'S-1-5' = 'NT AUTHORITY' 'S-1-5-1' = 'NT AUTHORITY\DIALUP' 'S-1-5-2' = 'NT AUTHORITY\NETWORK' 'S-1-5-3' = 'NT AUTHORITY\BATCH' 'S-1-5-4' = 'NT AUTHORITY\INTERACTIVE' 'S-1-5-6' = 'NT AUTHORITY\SERVICE' 'S-1-5-7' = 'NT AUTHORITY\ANONYMOUS LOGON' 'S-1-5-8' = 'NT AUTHORITY\PROXY' 'S-1-5-9' = 'NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS' 'S-1-5-10' = 'NT AUTHORITY\SELF' 'S-1-5-11' = 'NT AUTHORITY\Authenticated Users' 'S-1-5-12' = 'NT AUTHORITY\RESTRICTED' 'S-1-5-13' = 'NT AUTHORITY\TERMINAL SERVER USER' 'S-1-5-14' = 'NT AUTHORITY\REMOTE INTERACTIVE LOGON' 'S-1-5-15' = 'NT AUTHORITY\This Organization' 'S-1-5-17' = 'NT AUTHORITY\IUSR' 'S-1-5-18' = 'NT AUTHORITY\SYSTEM' 'S-1-5-19' = 'NT AUTHORITY\NETWORK SERVICE' 'S-1-5-20' = 'NT AUTHORITY\NETWORK SERVICE' 'S-1-5-32-544' = 'BUILTIN\Administrators' 'S-1-5-32-545' = 'BUILTIN\Users' 'S-1-5-32-546' = 'BUILTIN\Guests' 'S-1-5-32-547' = 'BUILTIN\Power Users' 'S-1-5-32-548' = 'BUILTIN\Account Operators' 'S-1-5-32-549' = 'BUILTIN\Server Operators' 'S-1-5-32-550' = 'BUILTIN\Print Operators' 'S-1-5-32-551' = 'BUILTIN\Backup Operators' 'S-1-5-32-552' = 'BUILTIN\Replicators' 'S-1-5-64-10' = 'NT AUTHORITY\NTLM Authentication' 'S-1-5-64-14' = 'NT AUTHORITY\SChannel Authentication' 'S-1-5-64-21' = 'NT AUTHORITY\Digest Authentication' 'S-1-5-80' = 'NT SERVICE' 'S-1-5-83-0' = 'NT VIRTUAL MACHINE\Virtual Machines' 'S-1-16-0' = 'Untrusted Mandatory Level' 'S-1-16-4096' = 'Low Mandatory Level' 'S-1-16-8192' = 'Medium Mandatory Level' 'S-1-16-8448' = 'Medium Plus Mandatory Level' 'S-1-16-12288' = 'High Mandatory Level' 'S-1-16-16384' = 'System Mandatory Level' 'S-1-16-20480' = 'Protected Process Mandatory Level' 'S-1-16-28672' = 'Secure Process Mandatory Level' 'S-1-5-32-554' = 'BUILTIN\Pre-Windows 2000 Compatible Access' 'S-1-5-32-555' = 'BUILTIN\Remote Desktop Users' 'S-1-5-32-556' = 'BUILTIN\Network Configuration Operators' 'S-1-5-32-557' = 'BUILTIN\Incoming Forest Trust Builders' 'S-1-5-32-558' = 'BUILTIN\Performance Monitor Users' 'S-1-5-32-559' = 'BUILTIN\Performance Log Users' 'S-1-5-32-560' = 'BUILTIN\Windows Authorization Access Group' 'S-1-5-32-561' = 'BUILTIN\Terminal Server License Servers' 'S-1-5-32-562' = 'BUILTIN\Distributed COM Users' 'S-1-5-32-569' = 'BUILTIN\Cryptographic Operators' 'S-1-5-32-573' = 'BUILTIN\Event Log Readers' 'S-1-5-32-574' = 'BUILTIN\Certificate Service DCOM Access' 'S-1-5-32-575' = 'BUILTIN\RDS Remote Access Servers' 'S-1-5-32-576' = 'BUILTIN\RDS Endpoint Servers' 'S-1-5-32-577' = 'BUILTIN\RDS Management Servers' 'S-1-5-32-578' = 'BUILTIN\Hyper-V Administrators' 'S-1-5-32-579' = 'BUILTIN\Access Control Assistance Operators' 'S-1-5-32-580' = 'BUILTIN\Remote Management Users' } foreach ($S in $SID) { if ($OnlyWellKnownAdministrative) { if ($WellKnownAdministrative[$S]) { [PSCustomObject] @{Name = $WellKnownAdministrative[$S] SID = $S Type = 'WellKnownAdministrative' Error = '' } } } elseif ($OnlyWellKnown) { if ($wellKnownSIDs[$S]) { [PSCustomObject] @{Name = $wellKnownSIDs[$S] SID = $S Type = 'WellKnownGroup' Error = '' } } } else { if ($wellKnownSIDs[$S]) { [PSCustomObject] @{Name = $wellKnownSIDs[$S] SID = $S Type = 'WellKnownGroup' Error = '' } } else { try { [PSCustomObject] @{Name = (([System.Security.Principal.SecurityIdentifier]::new($S)).Translate([System.Security.Principal.NTAccount])).Value SID = $S Type = 'Standard' Error = '' } } catch { [PSCustomObject] @{Name = $S SID = $S Error = $_.Exception.Message -replace [environment]::NewLine, ' ' Type = 'Unknown' } } } } } } function Get-ADADministrativeGroups { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER Type Parameter description .PARAMETER Forest Parameter description .PARAMETER ExcludeDomains Parameter description .PARAMETER IncludeDomains Parameter description .PARAMETER ExtendedForestInformation Parameter description .EXAMPLE Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins Output (Where VALUE is Get-ADGroup output): Name Value ---- ----- ByNetBIOS {EVOTEC\Domain Admins, EVOTEC\Enterprise Admins, EVOTECPL\Domain Admins} ad.evotec.xyz {DomainAdmins, EnterpriseAdmins} ad.evotec.pl {DomainAdmins} .NOTES General notes #> [cmdletBinding()] param([parameter(Mandatory)][validateSet('DomainAdmins', 'EnterpriseAdmins')][string[]] $Type, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation) $ADDictionary = [ordered] @{} $ADDictionary['ByNetBIOS'] = [ordered] @{} $ADDictionary['BySID'] = [ordered] @{} $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation foreach ($Domain in $ForestInformation.Domains) { $ADDictionary[$Domain] = [ordered] @{} $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] $DomainInformation = Get-ADDomain -Server $QueryServer if ($Type -contains 'DomainAdmins') { Get-ADGroup -Filter "SID -eq '$($DomainInformation.DomainSID)-512'" -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object { $ADDictionary['ByNetBIOS']["$($DomainInformation.NetBIOSName)\$($_.Name)"] = $_ $ADDictionary[$Domain]['DomainAdmins'] = "$($DomainInformation.NetBIOSName)\$($_.Name)" $ADDictionary['BySID'][$_.SID.Value] = $_ } } if ($Type -contains 'EnterpriseAdmins') { Get-ADGroup -Filter "SID -eq '$($DomainInformation.DomainSID)-519'" -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object { $ADDictionary['ByNetBIOS']["$($DomainInformation.NetBIOSName)\$($_.Name)"] = $_ $ADDictionary[$Domain]['EnterpriseAdmins'] = "$($DomainInformation.NetBIOSName)\$($_.Name)" $ADDictionary['BySID'][$_.SID.Value] = $_ } } } return $ADDictionary } function Get-FileOwner { [cmdletBinding()] param([Array] $Path, [switch] $Recursive, [switch] $JustPath, [switch] $Resolve) Begin {} Process { foreach ($P in $Path) { if ($P -is [System.IO.FileSystemInfo]) { $FullPath = $P.FullName } elseif ($P -is [string]) { $FullPath = $P } if ($FullPath -and (Test-Path -Path $FullPath)) { if ($JustPath) { $FullPath | ForEach-Object -Process { $ACL = Get-Acl -Path $_ $Object = [ordered]@{FullName = $_ Owner = $ACL.Owner } if ($Resolve) { $Identity = Convert-Identity -Identity $ACL.Owner if ($Identity) { $Object['OwnerName'] = $Identity.Name $Object['OwnerSid'] = $Identity.SID $Object['OwnerType'] = $Identity.Type } else { $Object['OwnerName'] = '' $Object['OwnerSid'] = '' $Object['OwnerType'] = '' } } [PSCustomObject] $Object } } else { Get-ChildItem -LiteralPath $FullPath -Recurse:$Recursive | ForEach-Object -Process { $File = $_ $ACL = Get-Acl -Path $File.FullName $Object = [ordered] @{FullName = $_.FullName Extension = $_.Extension CreationTime = $_.CreationTime LastAccessTime = $_.LastAccessTime LastWriteTime = $_.LastWriteTime Attributes = $_.Attributes Owner = $ACL.Owner } if ($Resolve) { $Identity = Convert-Identity -Identity $ACL.Owner if ($Identity) { $Object['OwnerName'] = $Identity.Name $Object['OwnerSid'] = $Identity.SID $Object['OwnerType'] = $Identity.Type } else { $Object['OwnerName'] = '' $Object['OwnerSid'] = '' $Object['OwnerType'] = '' } } [PSCustomObject] $Object } } } } } End {} } function Get-WinADForestDetails { [CmdletBinding()] param([alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [string[]] $ExcludeDomainControllers, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [alias('DomainControllers', 'ComputerName')][string[]] $IncludeDomainControllers, [switch] $SkipRODC, [string] $Filter = '*', [switch] $TestAvailability, [ValidateSet('All', 'Ping', 'WinRM', 'PortOpen', 'Ping+WinRM', 'Ping+PortOpen', 'WinRM+PortOpen')] $Test = 'All', [int[]] $Ports = 135, [int] $PortsTimeout = 100, [int] $PingCount = 1, [switch] $Extended, [System.Collections.IDictionary] $ExtendedForestInformation) if ($Global:ProgressPreference -ne 'SilentlyContinue') { $TemporaryProgress = $Global:ProgressPreference $Global:ProgressPreference = 'SilentlyContinue' } if (-not $ExtendedForestInformation) { $Findings = [ordered] @{} try { if ($Forest) { $ForestInformation = Get-ADForest -ErrorAction Stop -Identity $Forest } else { $ForestInformation = Get-ADForest -ErrorAction Stop } } catch { Write-Warning "Get-WinADForestDetails - Error discovering DC for Forest - $($_.Exception.Message)" return } if (-not $ForestInformation) { return } $Findings['Forest'] = $ForestInformation $Findings['ForestDomainControllers'] = @() $Findings['QueryServers'] = @{} $Findings['DomainDomainControllers'] = @{} [Array] $Findings['Domains'] = foreach ($_ in $ForestInformation.Domains) { if ($IncludeDomains) { if ($_ -in $IncludeDomains) { $_.ToLower() } continue } if ($_ -notin $ExcludeDomains) { $_.ToLower() } } [Array] $Findings['ForestDomainControllers'] = foreach ($Domain in $Findings.Domains) { try { $DC = Get-ADDomainController -DomainName $Domain -Discover -ErrorAction Stop $OrderedDC = [ordered] @{Domain = $DC.Domain Forest = $DC.Forest HostName = [Array] $DC.HostName IPv4Address = $DC.IPv4Address IPv6Address = $DC.IPv6Address Name = $DC.Name Site = $DC.Site } } catch { Write-Warning "Get-WinADForestDetails - Error discovering DC for domain $Domain - $($_.Exception.Message)" continue } if ($Domain -eq $Findings['Forest']['Name']) { $Findings['QueryServers']['Forest'] = $OrderedDC } $Findings['QueryServers']["$Domain"] = $OrderedDC [Array] $AllDC = try { try { $DomainControllers = Get-ADDomainController -Filter $Filter -Server $DC.HostName[0] -ErrorAction Stop } catch { Write-Warning "Get-WinADForestDetails - Error listing DCs for domain $Domain - $($_.Exception.Message)" continue } foreach ($S in $DomainControllers) { if ($IncludeDomainControllers.Count -gt 0) { If (-not $IncludeDomainControllers[0].Contains('.')) { if ($S.Name -notin $IncludeDomainControllers) { continue } } else { if ($S.HostName -notin $IncludeDomainControllers) { continue } } } if ($ExcludeDomainControllers.Count -gt 0) { If (-not $ExcludeDomainControllers[0].Contains('.')) { if ($S.Name -in $ExcludeDomainControllers) { continue } } else { if ($S.HostName -in $ExcludeDomainControllers) { continue } } } $Server = [ordered] @{Domain = $Domain HostName = $S.HostName Name = $S.Name Forest = $ForestInformation.RootDomain Site = $S.Site IPV4Address = $S.IPV4Address IPV6Address = $S.IPV6Address IsGlobalCatalog = $S.IsGlobalCatalog IsReadOnly = $S.IsReadOnly IsSchemaMaster = ($S.OperationMasterRoles -contains 'SchemaMaster') IsDomainNamingMaster = ($S.OperationMasterRoles -contains 'DomainNamingMaster') IsPDC = ($S.OperationMasterRoles -contains 'PDCEmulator') IsRIDMaster = ($S.OperationMasterRoles -contains 'RIDMaster') IsInfrastructureMaster = ($S.OperationMasterRoles -contains 'InfrastructureMaster') OperatingSystem = $S.OperatingSystem OperatingSystemVersion = $S.OperatingSystemVersion OperatingSystemLong = ConvertTo-OperatingSystem -OperatingSystem $S.OperatingSystem -OperatingSystemVersion $S.OperatingSystemVersion LdapPort = $S.LdapPort SslPort = $S.SslPort DistinguishedName = $S.ComputerObjectDN Pingable = $null WinRM = $null PortOpen = $null Comment = '' } if ($TestAvailability) { if ($Test -eq 'All' -or $Test -like 'Ping*') { $Server.Pingable = Test-Connection -ComputerName $Server.IPV4Address -Quiet -Count $PingCount } if ($Test -eq 'All' -or $Test -like '*WinRM*') { $Server.WinRM = (Test-WinRM -ComputerName $Server.HostName).Status } if ($Test -eq 'All' -or '*PortOpen*') { $Server.PortOpen = (Test-ComputerPort -Server $Server.HostName -PortTCP $Ports -Timeout $PortsTimeout).Status } } [PSCustomObject] $Server } } catch { [PSCustomObject]@{Domain = $Domain HostName = '' Name = '' Forest = $ForestInformation.RootDomain IPV4Address = '' IPV6Address = '' IsGlobalCatalog = '' IsReadOnly = '' Site = '' SchemaMaster = $false DomainNamingMasterMaster = $false PDCEmulator = $false RIDMaster = $false InfrastructureMaster = $false LdapPort = '' SslPort = '' DistinguishedName = '' Pingable = $null WinRM = $null PortOpen = $null Comment = $_.Exception.Message -replace "`n", " " -replace "`r", " " } } if ($SkipRODC) { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC | Where-Object { $_.IsReadOnly -eq $false } } else { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC } [Array] $Findings['DomainDomainControllers'][$Domain] } if ($Extended) { $Findings['DomainsExtended'] = @{} $Findings['DomainsExtendedNetBIOS'] = @{} foreach ($DomainEx in $Findings['Domains']) { try { $Findings['DomainsExtended'][$DomainEx] = Get-ADDomain -Server $Findings['QueryServers'][$DomainEx].HostName[0] | ForEach-Object { [ordered] @{AllowedDNSSuffixes = $_.AllowedDNSSuffixes | ForEach-Object -Process { $_ } ChildDomains = $_.ChildDomains | ForEach-Object -Process { $_ } ComputersContainer = $_.ComputersContainer DeletedObjectsContainer = $_.DeletedObjectsContainer DistinguishedName = $_.DistinguishedName DNSRoot = $_.DNSRoot DomainControllersContainer = $_.DomainControllersContainer DomainMode = $_.DomainMode DomainSID = $_.DomainSID.Value ForeignSecurityPrincipalsContainer = $_.ForeignSecurityPrincipalsContainer Forest = $_.Forest InfrastructureMaster = $_.InfrastructureMaster LastLogonReplicationInterval = $_.LastLogonReplicationInterval LinkedGroupPolicyObjects = $_.LinkedGroupPolicyObjects | ForEach-Object -Process { $_ } LostAndFoundContainer = $_.LostAndFoundContainer ManagedBy = $_.ManagedBy Name = $_.Name NetBIOSName = $_.NetBIOSName ObjectClass = $_.ObjectClass ObjectGUID = $_.ObjectGUID ParentDomain = $_.ParentDomain PDCEmulator = $_.PDCEmulator PublicKeyRequiredPasswordRolling = $_.PublicKeyRequiredPasswordRolling | ForEach-Object -Process { $_ } QuotasContainer = $_.QuotasContainer ReadOnlyReplicaDirectoryServers = $_.ReadOnlyReplicaDirectoryServers | ForEach-Object -Process { $_ } ReplicaDirectoryServers = $_.ReplicaDirectoryServers | ForEach-Object -Process { $_ } RIDMaster = $_.RIDMaster SubordinateReferences = $_.SubordinateReferences | ForEach-Object -Process { $_ } SystemsContainer = $_.SystemsContainer UsersContainer = $_.UsersContainer } } $NetBios = $Findings['DomainsExtended'][$DomainEx]['NetBIOSName'] $Findings['DomainsExtendedNetBIOS'][$NetBios] = $Findings['DomainsExtended'][$DomainEx] } catch { Write-Warning "Get-WinADForestDetails - Error gathering Domain Information for domain $DomainEx - $($_.Exception.Message)" continue } } } if ($TemporaryProgress) { $Global:ProgressPreference = $TemporaryProgress } $Findings } else { $Findings = Copy-Dictionary -Dictionary $ExtendedForestInformation [Array] $Findings['Domains'] = foreach ($_ in $Findings.Domains) { if ($IncludeDomains) { if ($_ -in $IncludeDomains) { $_.ToLower() } continue } if ($_ -notin $ExcludeDomains) { $_.ToLower() } } foreach ($_ in [string[]] $Findings.DomainDomainControllers.Keys) { if ($_ -notin $Findings.Domains) { $Findings.DomainDomainControllers.Remove($_) } } foreach ($_ in [string[]] $Findings.QueryServers.Keys) { if ($_ -notin $Findings.Domains -and $_ -ne 'Forest') { $Findings.QueryServers.Remove($_) } } foreach ($_ in [string[]] $Findings.DomainsExtended.Keys) { if ($_ -notin $Findings.Domains) { $Findings.DomainsExtended.Remove($_) $NetBiosName = $Findings.DomainsExtended.$_.'NetBIOSName' if ($NetBiosName) { $Findings.DomainsExtendedNetBIOS.Remove($NetBiosName) } } } [Array] $Findings['ForestDomainControllers'] = foreach ($Domain in $Findings.Domains) { [Array] $AllDC = foreach ($S in $Findings.DomainDomainControllers["$Domain"]) { if ($IncludeDomainControllers.Count -gt 0) { If (-not $IncludeDomainControllers[0].Contains('.')) { if ($S.Name -notin $IncludeDomainControllers) { continue } } else { if ($S.HostName -notin $IncludeDomainControllers) { continue } } } if ($ExcludeDomainControllers.Count -gt 0) { If (-not $ExcludeDomainControllers[0].Contains('.')) { if ($S.Name -in $ExcludeDomainControllers) { continue } } else { if ($S.HostName -in $ExcludeDomainControllers) { continue } } } $S } if ($SkipRODC) { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC | Where-Object { $_.IsReadOnly -eq $false } } else { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC } [Array] $Findings['DomainDomainControllers'][$Domain] } $Findings } } function Set-FileOwner { [cmdletBinding(SupportsShouldProcess)] param([Array] $Path, [switch] $Recursive, [string] $Owner, [string[]] $Exlude, [switch] $JustPath) Begin {} Process { foreach ($P in $Path) { if ($P -is [System.IO.FileSystemInfo]) { $FullPath = $P.FullName } elseif ($P -is [string]) { $FullPath = $P } $OwnerTranslated = [System.Security.Principal.NTAccount]::new($Owner) if ($FullPath -and (Test-Path -Path $FullPath)) { if ($JustPath) { $FullPath | ForEach-Object -Process { $File = $_ $ACL = Get-Acl -Path $File if ($ACL.Owner -notin $Exlude -and $ACL.Owner -ne $OwnerTranslated) { if ($PSCmdlet.ShouldProcess($File, "Replacing owner $($ACL.Owner) to $OwnerTranslated")) { try { $ACL.SetOwner($OwnerTranslated) Set-Acl -Path $File -AclObject $ACL } catch { Write-Warning "Set-FileOwner - Replacing owner $($ACL.Owner) to $OwnerTranslated failed with error: $($_.Exception.Message)" } } } } } else { Get-ChildItem -LiteralPath $FullPath -Recurse:$Recursive | ForEach-Object -Process { $File = $_ $ACL = Get-Acl -Path $File.FullName if ($ACL.Owner -notin $Exlude -and $ACL.Owner -ne $OwnerTranslated) { if ($PSCmdlet.ShouldProcess($File.FullName, "Replacing owner $($ACL.Owner) to $OwnerTranslated")) { try { $ACL.SetOwner($OwnerTranslated) Set-Acl -Path $File.FullName -AclObject $ACL } catch { Write-Warning "Set-FileOwner - Replacing owner $($ACL.Owner) to $OwnerTranslated failed with error: $($_.Exception.Message)" } } } } } } } } End {} } function Convert-Identity { [cmdletBinding(DefaultParameterSetName = 'Identity')] param([parameter(ParameterSetName = 'Identity')][string[]] $Identity, [parameter(ParameterSetName = 'SID', Mandatory)][System.Security.Principal.SecurityIdentifier[]] $SID, [parameter(ParameterSetName = 'Name', Mandatory)][string[]] $Name) Begin { if (-not $Script:GlobalCacheSidConvert) { $Script:GlobalCacheSidConvert = @{'S-1-0' = 'Null AUTHORITY' 'S-1-0-0' = 'NULL SID' 'S-1-1' = 'WORLD AUTHORITY' 'S-1-1-0' = 'Everyone' 'S-1-2' = 'LOCAL AUTHORITY' 'S-1-2-0' = 'LOCAL' 'S-1-2-1' = 'CONSOLE LOGON' 'S-1-3' = 'CREATOR AUTHORITY' 'S-1-3-0' = 'CREATOR OWNER' 'S-1-3-1' = 'CREATOR GROUP' 'S-1-3-2' = 'CREATOR OWNER SERVER' 'S-1-3-3' = 'CREATOR GROUP SERVER' 'S-1-3-4' = 'OWNER RIGHTS' 'S-1-5-80-0' = 'NT SERVICE\ALL SERVICES' 'S-1-4' = 'Non-unique Authority' 'S-1-5' = 'NT AUTHORITY' 'S-1-5-1' = 'NT AUTHORITY\DIALUP' 'S-1-5-2' = 'NT AUTHORITY\NETWORK' 'S-1-5-3' = 'NT AUTHORITY\BATCH' 'S-1-5-4' = 'NT AUTHORITY\INTERACTIVE' 'S-1-5-6' = 'NT AUTHORITY\SERVICE' 'S-1-5-7' = 'NT AUTHORITY\ANONYMOUS LOGON' 'S-1-5-8' = 'NT AUTHORITY\PROXY' 'S-1-5-9' = 'NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS' 'S-1-5-10' = 'NT AUTHORITY\SELF' 'S-1-5-11' = 'NT AUTHORITY\Authenticated Users' 'S-1-5-12' = 'NT AUTHORITY\RESTRICTED' 'S-1-5-13' = 'NT AUTHORITY\TERMINAL SERVER USER' 'S-1-5-14' = 'NT AUTHORITY\REMOTE INTERACTIVE LOGON' 'S-1-5-15' = 'NT AUTHORITY\This Organization' 'S-1-5-17' = 'NT AUTHORITY\IUSR' 'S-1-5-18' = 'NT AUTHORITY\SYSTEM' 'S-1-5-19' = 'NT AUTHORITY\NETWORK SERVICE' 'S-1-5-20' = 'NT AUTHORITY\NETWORK SERVICE' 'S-1-5-32-544' = 'BUILTIN\Administrators' 'S-1-5-32-545' = 'BUILTIN\Users' 'S-1-5-32-546' = 'BUILTIN\Guests' 'S-1-5-32-547' = 'BUILTIN\Power Users' 'S-1-5-32-548' = 'BUILTIN\Account Operators' 'S-1-5-32-549' = 'BUILTIN\Server Operators' 'S-1-5-32-550' = 'BUILTIN\Print Operators' 'S-1-5-32-551' = 'BUILTIN\Backup Operators' 'S-1-5-32-552' = 'BUILTIN\Replicators' 'S-1-5-64-10' = 'NT AUTHORITY\NTLM Authentication' 'S-1-5-64-14' = 'NT AUTHORITY\SChannel Authentication' 'S-1-5-64-21' = 'NT AUTHORITY\Digest Authentication' 'S-1-5-80' = 'NT SERVICE' 'S-1-5-83-0' = 'NT VIRTUAL MACHINE\Virtual Machines' 'S-1-16-0' = 'Untrusted Mandatory Level' 'S-1-16-4096' = 'Low Mandatory Level' 'S-1-16-8192' = 'Medium Mandatory Level' 'S-1-16-8448' = 'Medium Plus Mandatory Level' 'S-1-16-12288' = 'High Mandatory Level' 'S-1-16-16384' = 'System Mandatory Level' 'S-1-16-20480' = 'Protected Process Mandatory Level' 'S-1-16-28672' = 'Secure Process Mandatory Level' 'S-1-5-32-554' = 'BUILTIN\Pre-Windows 2000 Compatible Access' 'S-1-5-32-555' = 'BUILTIN\Remote Desktop Users' 'S-1-5-32-556' = 'BUILTIN\Network Configuration Operators' 'S-1-5-32-557' = 'BUILTIN\Incoming Forest Trust Builders' 'S-1-5-32-558' = 'BUILTIN\Performance Monitor Users' 'S-1-5-32-559' = 'BUILTIN\Performance Log Users' 'S-1-5-32-560' = 'BUILTIN\Windows Authorization Access Group' 'S-1-5-32-561' = 'BUILTIN\Terminal Server License Servers' 'S-1-5-32-562' = 'BUILTIN\Distributed COM Users' 'S-1-5-32-569' = 'BUILTIN\Cryptographic Operators' 'S-1-5-32-573' = 'BUILTIN\Event Log Readers' 'S-1-5-32-574' = 'BUILTIN\Certificate Service DCOM Access' 'S-1-5-32-575' = 'BUILTIN\RDS Remote Access Servers' 'S-1-5-32-576' = 'BUILTIN\RDS Endpoint Servers' 'S-1-5-32-577' = 'BUILTIN\RDS Management Servers' 'S-1-5-32-578' = 'BUILTIN\Hyper-V Administrators' 'S-1-5-32-579' = 'BUILTIN\Access Control Assistance Operators' 'S-1-5-32-580' = 'BUILTIN\Remote Management Users' } } $wellKnownSIDs = @{'S-1-0' = 'WellKnown' 'S-1-0-0' = 'WellKnown' 'S-1-1' = 'WellKnown' 'S-1-1-0' = 'WellKnown' 'S-1-2' = 'WellKnown' 'S-1-2-0' = 'WellKnown' 'S-1-2-1' = 'WellKnown' 'S-1-3' = 'WellKnown' 'S-1-3-0' = 'WellKnown' 'S-1-3-1' = 'WellKnown' 'S-1-3-2' = 'WellKnown' 'S-1-3-3' = 'WellKnown' 'S-1-3-4' = 'WellKnown' 'S-1-5-80-0' = 'WellKnown' 'S-1-4' = 'WellKnown' 'S-1-5' = 'WellKnown' 'S-1-5-1' = 'WellKnown' 'S-1-5-2' = 'WellKnown' 'S-1-5-3' = 'WellKnown' 'S-1-5-4' = 'WellKnown' 'S-1-5-6' = 'WellKnown' 'S-1-5-7' = 'WellKnown' 'S-1-5-8' = 'WellKnown' 'S-1-5-9' = 'WellKnown' 'S-1-5-10' = 'WellKnown' 'S-1-5-11' = 'WellKnown' 'S-1-5-12' = 'WellKnown' 'S-1-5-13' = 'WellKnown' 'S-1-5-14' = 'WellKnown' 'S-1-5-15' = 'WellKnown' 'S-1-5-17' = 'WellKnown' 'S-1-5-18' = 'WellKnownAdministrative' 'S-1-5-19' = 'WellKnown' 'S-1-5-20' = 'WellKnown' 'S-1-5-32-544' = 'WellKnownAdministrative' 'S-1-5-32-545' = 'WellKnown' 'S-1-5-32-546' = 'WellKnown' 'S-1-5-32-547' = 'WellKnown' 'S-1-5-32-548' = 'WellKnown' 'S-1-5-32-549' = 'WellKnown' 'S-1-5-32-550' = 'WellKnown' 'S-1-5-32-551' = 'WellKnown' 'S-1-5-32-552' = 'WellKnown' 'S-1-5-64-10' = 'WellKnown' 'S-1-5-64-14' = 'WellKnown' 'S-1-5-64-21' = 'WellKnown' 'S-1-5-80' = 'WellKnown' 'S-1-5-83-0' = 'WellKnown' 'S-1-16-0' = 'WellKnown' 'S-1-16-4096' = 'WellKnown' 'S-1-16-8192' = 'WellKnown' 'S-1-16-8448' = 'WellKnown' 'S-1-16-12288' = 'WellKnown' 'S-1-16-16384' = 'WellKnown' 'S-1-16-20480' = 'WellKnown' 'S-1-16-28672' = 'WellKnown' 'S-1-5-32-554' = 'WellKnown' 'S-1-5-32-555' = 'WellKnown' 'S-1-5-32-556' = 'WellKnown' 'S-1-5-32-557' = 'WellKnown' 'S-1-5-32-558' = 'WellKnown' 'S-1-5-32-559' = 'WellKnown' 'S-1-5-32-560' = 'WellKnown' 'S-1-5-32-561' = 'WellKnown' 'S-1-5-32-562' = 'WellKnown' 'S-1-5-32-569' = 'WellKnown' 'S-1-5-32-573' = 'WellKnown' 'S-1-5-32-574' = 'WellKnown' 'S-1-5-32-575' = 'WellKnown' 'S-1-5-32-576' = 'WellKnown' 'S-1-5-32-577' = 'WellKnown' 'S-1-5-32-578' = 'WellKnown' 'S-1-5-32-579' = 'WellKnown' 'S-1-5-32-580' = 'WellKnown' } } Process { if ($Identity) { foreach ($Ident in $Identity) { if ($Ident -like '*-*-*') { if ($Script:GlobalCacheSidConvert[$Ident]) { if ($Script:GlobalCacheSidConvert[$Ident] -is [string]) { [ordered] @{Name = $Script:GlobalCacheSidConvert[$Ident] SID = $Ident Type = $wellKnownSIDs[$Ident] Error = '' } } else { $Script:GlobalCacheSidConvert[$Ident] } } else { try { [string] $Name = (([System.Security.Principal.SecurityIdentifier]::new($Ident)).Translate([System.Security.Principal.NTAccount])).Value $ErrorMessage = '' if ($Ident -like "S-1-5-21-*-519" -or $Ident -like "S-1-5-21-*-512") { $Type = 'Administrative' } elseif ($wellKnownSIDs[$Ident]) { $Type = $wellKnownSIDs[$Ident] } else { $Type = 'NotAdministrative' } } catch { [string] $Name = '' $ErrorMessage = $_.Exception.Message $Type = 'Unknown' } $Script:GlobalCacheSidConvert[$Ident] = [PSCustomObject] @{Name = $Name SID = $Ident Type = $Type Error = $ErrorMessage } $Script:GlobalCacheSidConvert[$Ident] } } else { if ($Script:GlobalCacheSidConvert[$Ident]) { $Script:GlobalCacheSidConvert[$Ident] } else { try { $SIDValue = ([System.Security.Principal.NTAccount] $Ident).Translate([System.Security.Principal.SecurityIdentifier]).Value if ($SIDValue -like "S-1-5-21-*-519" -or $SIDValue -like "S-1-5-21-*-512") { $Type = 'Administrative' } elseif ($wellKnownSIDs[$SIDValue]) { $Type = $wellKnownSIDs[$SIDValue] } else { $Type = 'NotAdministrative' } $ErrorMessage = '' } catch { $Type = 'Unknown' $ErrorMessage = $_.Exception.Message } $Script:GlobalCacheSidConvert[$Ident] = [PSCustomObject] @{Name = $Ident SID = $SIDValue Type = $Type Error = $ErrorMessage } $Script:GlobalCacheSidConvert[$Ident] } } } } else { if ($SID) { foreach ($S in $SID) { if ($Script:GlobalCacheSidConvert[$S]) { $Script:GlobalCacheSidConvert[$S] } else { $Script:GlobalCacheSidConvert[$S] = (([System.Security.Principal.SecurityIdentifier]::new($S)).Translate([System.Security.Principal.NTAccount])).Value $Script:GlobalCacheSidConvert[$S] } } } else { foreach ($Ident in $Name) { if ($Script:GlobalCacheSidConvert[$Ident]) { $Script:GlobalCacheSidConvert[$Ident] } else { $Script:GlobalCacheSidConvert[$Ident] = ([System.Security.Principal.NTAccount] $Ident).Translate([System.Security.Principal.SecurityIdentifier]).Value $Script:GlobalCacheSidConvert[$Ident] } } } } } End {} } function ConvertTo-OperatingSystem { [CmdletBinding()] param([string] $OperatingSystem, [string] $OperatingSystemVersion) if ($OperatingSystem -like '*Windows 10*') { $Systems = @{'10.0 (18363)' = "Windows 10 1909" '10.0 (18362)' = "Windows 10 1903" '10.0 (17763)' = "Windows 10 1809" '10.0 (17134)' = "Windows 10 1803" '10.0 (16299)' = "Windows 10 1709" '10.0 (15063)' = "Windows 10 1703" '10.0 (14393)' = "Windows 10 1607" '10.0 (10586)' = "Windows 10 1511" '10.0 (10240)' = "Windows 10 1507" '10.0 (18898)' = 'Windows 10 Insider Preview' '10.0.18363' = "Windows 10 1909" '10.0.18362' = "Windows 10 1903" '10.0.17763' = "Windows 10 1809" '10.0.17134' = "Windows 10 1803" '10.0.16299' = "Windows 10 1709" '10.0.15063' = "Windows 10 1703" '10.0.14393' = "Windows 10 1607" '10.0.10586' = "Windows 10 1511" '10.0.10240' = "Windows 10 1507" '10.0.18898' = 'Windows 10 Insider Preview' } $System = $Systems[$OperatingSystemVersion] if (-not $System) { $System = $OperatingSystem } } elseif ($OperatingSystem -like '*Windows Server*') { $Systems = @{'5.2 (3790)' = 'Windows Server 2003' '6.1 (7601)' = 'Windows Server 2008 R2' '10.0 (18362)' = "Windows Server, version 1903 (Semi-Annual Channel) 1903" '10.0 (17763)' = "Windows Server 2019 (Long-Term Servicing Channel) 1809" '10.0 (17134)' = "Windows Server, version 1803 (Semi-Annual Channel) 1803" '10.0 (14393)' = "Windows Server 2016 (Long-Term Servicing Channel) 1607" '10.0.18362' = "Windows Server, version 1903 (Semi-Annual Channel) 1903" '10.0.17763' = "Windows Server 2019 (Long-Term Servicing Channel) 1809" '10.0.17134' = "Windows Server, version 1803 (Semi-Annual Channel) 1803" '10.0.14393' = "Windows Server 2016 (Long-Term Servicing Channel) 1607" } $System = $Systems[$OperatingSystemVersion] if (-not $System) { $System = $OperatingSystem } } else { $System = $OperatingSystem } if ($System) { $System } else { 'Unknown' } } function Copy-Dictionary { [alias('Copy-Hashtable', 'Copy-OrderedHashtable')] [cmdletbinding()] param([System.Collections.IDictionary] $Dictionary) $ms = [System.IO.MemoryStream]::new() $bf = [System.Runtime.Serialization.Formatters.Binary.BinaryFormatter]::new() $bf.Serialize($ms, $Dictionary) $ms.Position = 0 $clone = $bf.Deserialize($ms) $ms.Close() $clone } function Test-ComputerPort { [CmdletBinding()] param ([alias('Server')][string[]] $ComputerName, [int[]] $PortTCP, [int[]] $PortUDP, [int]$Timeout = 5000) begin { if ($Global:ProgressPreference -ne 'SilentlyContinue') { $TemporaryProgress = $Global:ProgressPreference $Global:ProgressPreference = 'SilentlyContinue' } } process { foreach ($Computer in $ComputerName) { foreach ($P in $PortTCP) { $Output = [ordered] @{'ComputerName' = $Computer 'Port' = $P 'Protocol' = 'TCP' 'Status' = $null 'Summary' = $null 'Response' = $null } $TcpClient = Test-NetConnection -ComputerName $Computer -Port $P -InformationLevel Detailed -WarningAction SilentlyContinue if ($TcpClient.TcpTestSucceeded) { $Output['Status'] = $TcpClient.TcpTestSucceeded $Output['Summary'] = "TCP $P Successful" } else { $Output['Status'] = $false $Output['Summary'] = "TCP $P Failed" $Output['Response'] = $Warnings } [PSCustomObject]$Output } foreach ($P in $PortUDP) { $Output = [ordered] @{'ComputerName' = $Computer 'Port' = $P 'Protocol' = 'UDP' 'Status' = $null 'Summary' = $null } $UdpClient = [System.Net.Sockets.UdpClient]::new($Computer, $P) $UdpClient.Client.ReceiveTimeout = $Timeout $Encoding = [System.Text.ASCIIEncoding]::new() $byte = $Encoding.GetBytes("Evotec") [void]$UdpClient.Send($byte, $byte.length) $RemoteEndpoint = [System.Net.IPEndPoint]::new([System.Net.IPAddress]::Any, 0) try { $Bytes = $UdpClient.Receive([ref]$RemoteEndpoint) [string]$Data = $Encoding.GetString($Bytes) If ($Data) { $Output['Status'] = $true $Output['Summary'] = "UDP $P Successful" $Output['Response'] = $Data } } catch { $Output['Status'] = $false $Output['Summary'] = "UDP $P Failed" $Output['Response'] = $_.Exception.Message } $UdpClient.Close() $UdpClient.Dispose() [PSCustomObject]$Output } } } end { if ($TemporaryProgress) { $Global:ProgressPreference = $TemporaryProgress } } } function Test-WinRM { [CmdletBinding()] param ([alias('Server')][string[]] $ComputerName) $Output = foreach ($Computer in $ComputerName) { $Test = [PSCustomObject] @{Output = $null Status = $null ComputerName = $Computer } try { $Test.Output = Test-WSMan -ComputerName $Computer -ErrorAction Stop $Test.Status = $true } catch { $Test.Status = $false } $Test } $Output } function Get-PrivGPOZaurrLink { [cmdletBinding()] param( [Microsoft.ActiveDirectory.Management.ADObject] $Object, [switch] $Limited, [System.Collections.IDictionary] $GPOCache ) if ($Object.GpLink -and $Object.GpLink.Trim() -ne '') { $Object.GpLink -split { $_ -eq '[' -or $_ -eq ']' } -replace ';0' -replace 'LDAP://' | ForEach-Object -Process { if ($_) { $DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDomainCN $Output = [ordered] @{ DistinguishedName = $Object.DistinguishedName CanonicalName = $Object.CanonicalName Guid = [Regex]::Match( $_, '(?={)(.*)(?<=})').Value -replace '{' -replace '}' } $Search = -join ($DomainCN, $Output['Guid']) if ($GPOCache -and -not $Limited) { $Output['DisplayName'] = $GPOCache[$Search].DisplayName $Output['DomainName'] = $GPOCache[$Search].DomainName $Output['Owner'] = $GPOCache[$Search].Owner $Output['GpoStatus'] = $GPOCache[$Search].GpoStatus $Output['Description'] = $GPOCache[$Search].Description $Output['CreationTime'] = $GPOCache[$Search].CreationTime $Output['ModificationTime'] = $GPOCache[$Search].ModificationTime } $Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDC $Output['GPODistinguishedName'] = $_ [PSCustomObject] $Output } } } elseif ($Object.LinkedGroupPolicyObjects -and $Object.LinkedGroupPolicyObjects.Trim() -ne '') { $Object.LinkedGroupPolicyObjects -split { $_ -eq '[' -or $_ -eq ']' } -replace ';0' -replace 'LDAP://' | ForEach-Object -Process { if ($_) { $DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDomainCN $Output = [ordered] @{ DistinguishedName = $Object.DistinguishedName CanonicalName = $Object.CanonicalName Guid = [Regex]::Match( $_, '(?={)(.*)(?<=})').Value -replace '{' -replace '}' } $Search = -join ($DomainCN, $Output['Guid']) if ($GPOCache -and -not $Limited) { $Output['Name'] = $GPOCache[$Search].DisplayName $Output['DomainName'] = $GPOCache[$Search].DomainName $Output['Owner'] = $GPOCache[$Search].Owner $Output['GpoStatus'] = $GPOCache[$Search].GpoStatus $Output['Description'] = $GPOCache[$Search].Description $Output['CreationTime'] = $GPOCache[$Search].CreationTime $Output['ModificationTime'] = $GPOCache[$Search].ModificationTime } $Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDC $Output['GPODistinguishedName'] = $_ [PSCustomObject] $Output } } } } function Get-PrivPermission { [cmdletBinding()] param( [Microsoft.GroupPolicy.Gpo] $GPO, [string[]] $Principal, [validateset('DistinguishedName', 'Name', 'Sid')][string] $PrincipalType = 'Sid', [switch] $SkipWellKnown, [switch] $SkipAdministrative, [switch] $IncludeOwner, [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType, [switch] $IncludeGPOObject, [System.Collections.IDictionary] $ADAdministrativeGroups, [validateSet('Unknown', 'NotWellKnown', 'NotWellKnownAdministrative', 'NotAdministrative', 'Administrative', 'All', 'Default')][string[]] $Type, [System.Collections.IDictionary] $Accounts ) Begin { Write-Verbose "Get-PrivPermission - Processing $($GPO.DisplayName) from $($GPO.DomainName)" } Process { $SecurityRights = $GPO.GetSecurityInfo() $SecurityRights | ForEach-Object -Process { #Get-GPPermissions -Guid $GPO.ID -DomainName $GPO.DomainName -All -Server $QueryServer | ForEach-Object -Process { $GPOPermission = $_ if ($ExcludePermissionType -contains $GPOPermission.Permission) { return } if ($IncludePermissionType) { if ($IncludePermissionType -notcontains $GPOPermission.Permission) { return } } if ($SkipWellKnown.IsPresent -or $Type -contains 'NotWellKnown') { if ($GPOPermission.Trustee.SidType -eq 'WellKnownGroup') { return } } if ($SkipAdministrative.IsPresent -or $Type -contains 'NotAdministrative') { $IsAdministrative = $ADAdministrativeGroups['BySID'][$GPOPermission.Trustee.Sid.Value] if ($IsAdministrative) { return } } if ($Type -contains 'Administrative' -and $Type -notcontains 'All') { $IsAdministrative = $ADAdministrativeGroups['BySID'][$GPOPermission.Trustee.Sid.Value] if (-not $IsAdministrative) { return } } if ($Type -contains 'NotWellKnownAdministrative' -and $Type -notcontains 'All') { # We check for SYSTEM account # Maybe we should make it a function and provide more if ($GPOPermission.Trustee.Sid -eq 'S-1-5-18') { return } } if ($Type -contains 'Unknown' -and $Type -notcontains 'All') { # May need updates if there's more types if ($GPOPermission.Trustee.SidType -ne 'Unknown') { return } } if ($Principal) { if ($PrincipalType -eq 'Sid') { if ($Principal -notcontains $GPOPermission.Trustee.Sid.Value) { return } } elseif ($PrincipalType -eq 'DistinguishedName') { if ($Principal -notcontains $GPOPermission.Trustee.DSPath) { return } } elseif ($PrincipalType -eq 'Name') { $UserMerge = -join ($GPOPermission.Trustee.Domain, '\', $GPOPermission.Trustee.Name) if ($Principal -notcontains $UserMerge -and $Principal -notcontains $GPOPermission.Trustee.Name) { return } } } $ReturnObject = [ordered] @{ DisplayName = $GPO.DisplayName # : ALL | Enable RDP GUID = $GPO.ID DomainName = $GPO.DomainName # : ad.evotec.xyz Enabled = $GPO.GpoStatus Description = $GPO.Description CreationDate = $GPO.CreationTime ModificationTime = $GPO.ModificationTime PermissionType = if ($GPOPermission.Denied -eq $true) { 'Deny' } else { 'Allow' } Permission = $GPOPermission.Permission # : GpoEditDeleteModifySecurity Inherited = $GPOPermission.Inherited # : False Domain = $GPOPermission.Trustee.Domain #: EVOTEC DistinguishedName = $GPOPermission.Trustee.DSPath #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz Name = $GPOPermission.Trustee.Name #: Domain Admins Sid = $GPOPermission.Trustee.Sid.Value #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512 SidType = $GPOPermission.Trustee.SidType #: Group } if ($Accounts) { $A = -join ($GPOPermission.Trustee.Domain, '\', $GPOPermission.Trustee.Name) if ($A -and $Accounts[$A]) { $ReturnObject['UserPrincipalName'] = $Accounts[$A].UserPrincipalName $ReturnObject['AccountEnabled'] = $Accounts[$A].Enabled $ReturnObject['DistinguishedName'] = $Accounts[$A].DistinguishedName $ReturnObject['PasswordLastSet'] = if ($Accounts[$A].PasswordLastSet) { $Accounts[$A].PasswordLastSet } else { '' } $ReturnObject['LastLogonDate'] = if ($Accounts[$A].LastLogonDate ) { $Accounts[$A].LastLogonDate } else { '' } if (-not $ReturnObject['Sid']) { $ReturnObject['Sid'] = $Accounts[$A].Sid.Value } if ($Accounts[$A].ObjectClass -eq 'group') { $ReturnObject['SidType'] = 'Group' } elseif ($Accounts[$A].ObjectClass -eq 'user') { $ReturnObject['SidType'] = 'User' } elseif ($Accounts[$A].ObjectClass -eq 'computer') { $ReturnObject['SidType'] = 'Computer' } else { $ReturnObject['SidType'] = 'EmptyOrUnknown' } } else { $ReturnObject['UserPrincipalName'] = '' $ReturnObject['AccountEnabled'] = '' $ReturnObject['PasswordLastSet'] = '' $ReturnObject['LastLogonDate'] = '' } } if ($IncludeGPOObject) { $ReturnObject['GPOObject'] = $GPO $ReturnObject['GPOSecurity'] = $SecurityRights $ReturnObject['GPOSecurityPermissionItem'] = $GPOPermission } [PSCustomObject] $ReturnObject } if ($IncludeOwner.IsPresent) { if ($GPO.Owner) { $SplittedOwner = $GPO.Owner.Split('\') $DomainOwner = $SplittedOwner[0] #: EVOTEC $DomainUserName = $SplittedOwner[1] #: Domain Admins $SID = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"].Sid.Value if ($SID) { $SIDType = 'Group' $DistinguishedName = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"].DistinguishedName } else { $SIDType = '' $DistinguishedName = '' } } else { $DomainOwner = $GPO.Owner $DomainUserName = '' $SID = '' $SIDType = 'EmptyOrUnknown' $DistinguishedName = '' } $ReturnObject = [ordered] @{ DisplayName = $GPO.DisplayName # : ALL | Enable RDP GUID = $GPO.Id DomainName = $GPO.DomainName # : ad.evotec.xyz Enabled = $GPO.GpoStatus Description = $GPO.Description CreationDate = $GPO.CreationTime ModificationTime = $GPO.ModificationTime Permission = 'GpoOwner' # : GpoEditDeleteModifySecurity Inherited = $false # : False Domain = $DomainOwner DistinguishedName = $DistinguishedName #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz Name = $DomainUserName Sid = $SID #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512 SidType = $SIDType # #: Group } if ($Accounts) { $A = $GPO.Owner if ($A -and $Accounts[$A]) { $ReturnObject['UserPrincipalName'] = $Accounts[$A].UserPrincipalName $ReturnObject['AccountEnabled'] = $Accounts[$A].Enabled $ReturnObject['DistinguishedName'] = $Accounts[$A].DistinguishedName $ReturnObject['PasswordLastSet'] = if ($Accounts[$A].PasswordLastSet) { $Accounts[$A].PasswordLastSet } else { '' } $ReturnObject['LastLogonDate'] = if ($Accounts[$A].LastLogonDate ) { $Accounts[$A].LastLogonDate } else { '' } if (-not $ReturnObject['Sid']) { $ReturnObject['Sid'] = $Accounts[$A].Sid.Value } if ($Accounts[$A].ObjectClass -eq 'group') { $ReturnObject['SidType'] = 'Group' } elseif ($Accounts[$A].ObjectClass -eq 'user') { $ReturnObject['SidType'] = 'User' } elseif ($Accounts[$A].ObjectClass -eq 'computer') { $ReturnObject['SidType'] = 'Computer' } else { $ReturnObject['SidType'] = 'EmptyOrUnknown' } } else { $ReturnObject['UserPrincipalName'] = '' $ReturnObject['AccountEnabled'] = '' $ReturnObject['PasswordLastSet'] = '' $ReturnObject['LastLogonDate'] = '' } } if ($IncludeGPOObject) { $ReturnObject['GPOObject'] = $GPO $ReturnObject['GPOSecurity'] = $SecurityRights $ReturnObject['GPOSecurityPermissionItem'] = $null } [PSCustomObject] $ReturnObject } } End { } } function Get-XMLGPO { [cmdletBinding()] param( [XML] $XMLContent, [Microsoft.GroupPolicy.Gpo] $GPO, [switch] $PermissionsOnly, [switch] $OwnerOnly, [System.Collections.IDictionary] $ADAdministrativeGroups ) if ($XMLContent.GPO.LinksTo) { $Linked = $true $LinksCount = ([Array] $XMLContent.GPO.LinksTo).Count } else { $Linked = $false $LinksCount = 0 } # Find proper values for enabled/disabled user/computer settings if ($XMLContent.GPO.Computer.Enabled -eq 'False') { $ComputerEnabled = $false } elseif ($XMLContent.GPO.Computer.Enabled -eq 'True') { $ComputerEnabled = $true } if ($XMLContent.GPO.User.Enabled -eq 'False') { $UserEnabled = $false } elseif ($XMLContent.GPO.User.Enabled -eq 'True') { $UserEnabled = $true } # Translate Enabled to same as GPO GUI if ($UserEnabled -eq $True -and $ComputerEnabled -eq $true) { $Enabled = 'Enabled' } elseif ($UserEnabled -eq $false -and $ComputerEnabled -eq $false) { $Enabled = 'All settings disabled' } elseif ($UserEnabled -eq $true -and $ComputerEnabled -eq $false) { $Enabled = 'Computer configuration settings disabled' } elseif ($UserEnabled -eq $false -and $ComputerEnabled -eq $true) { $Enabled = 'User configuration settings disabled' } if (-not $PermissionsOnly) { if ($XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text') { $AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text')"] $WellKnown = ConvertFrom-SID -SID $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' -OnlyWellKnown if ($AdministrativeGroup) { $OwnerType = 'Administrative' } elseif ($WellKnown.Name) { $OwnerType = 'WellKnown' } else { $OwnerType = 'NotAdministrative' } } else { $OwnerType = 'EmptyOrUnknown' } } if ($PermissionsOnly) { [PsCustomObject] @{ 'DisplayName' = $XMLContent.GPO.Name 'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text' 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}' 'Enabled' = $Enabled 'Name' = $XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text' 'Sid' = $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' #'SidType' = if (($XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text').Length -le 10) { 'WellKnown' } else { 'Other' } 'PermissionType' = 'Allow' 'Inherited' = $false 'Permissions' = 'Owner' 'GPODistinguishedName' = $GPO.Path } $XMLContent.GPO.SecurityDescriptor.Permissions.TrusteePermissions | ForEach-Object -Process { if ($_) { [PsCustomObject] @{ 'DisplayName' = $XMLContent.GPO.Name 'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text' 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}' 'Enabled' = $Enabled 'Name' = $_.trustee.name.'#Text' 'Sid' = $_.trustee.SID.'#Text' #'SidType' = if (($XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text').Length -le 10) { 'WellKnown' } else { 'Other' } 'PermissionType' = $_.type.PermissionType 'Inherited' = if ($_.Inherited -eq 'false') { $false } else { $true } 'Permissions' = $_.Standard.GPOGroupedAccessEnum 'GPODistinguishedName' = $GPO.Path } } } } elseif ($OwnerOnly) { [PsCustomObject] @{ 'DisplayName' = $XMLContent.GPO.Name 'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text' 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}' 'Enabled' = $Enabled 'Owner' = $XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text' 'OwnerSID' = $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' 'OwnerType' = $OwnerType 'GPODistinguishedName' = $GPO.Path } } else { [PsCustomObject] @{ 'DisplayName' = $XMLContent.GPO.Name 'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text' 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}' 'Linked' = $Linked 'LinksCount' = $LinksCount 'Enabled' = $Enabled 'ComputerEnabled' = $ComputerEnabled 'UserEnabled' = $UserEnabled 'ComputerSettingsAvailable' = if ($null -eq $XMLContent.GPO.Computer.ExtensionData) { $false } else { $true } 'UserSettingsAvailable' = if ($null -eq $XMLContent.GPO.User.ExtensionData) { $false } else { $true } 'ComputerSettingsStatus' = if ($XMLContent.GPO.Computer.VersionDirectory -eq 0 -and $XMLContent.GPO.Computer.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" } 'ComputerSetttingsVersionIdentical' = if ($XMLContent.GPO.Computer.VersionDirectory -eq $XMLContent.GPO.Computer.VersionSysvol) { $true } else { $false } 'ComputerSettings' = $XMLContent.GPO.Computer.ExtensionData.Extension 'UserSettingsStatus' = if ($XMLContent.GPO.User.VersionDirectory -eq 0 -and $XMLContent.GPO.User.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" } 'UserSettingsVersionIdentical' = if ($XMLContent.GPO.User.VersionDirectory -eq $XMLContent.GPO.User.VersionSysvol) { $true } else { $false } 'UserSettings' = $XMLContent.GPO.User.ExtensionData.Extension 'CreationTime' = [DateTime] $XMLContent.GPO.CreatedTime 'ModificationTime' = [DateTime] $XMLContent.GPO.ModifiedTime 'ReadTime' = [DateTime] $XMLContent.GPO.ReadTime 'WMIFilter' = $GPO.WmiFilter.name 'WMIFilterDescription' = $GPO.WmiFilter.Description 'GPODistinguishedName' = $GPO.Path 'SDDL' = if ($Splitter -ne '') { $XMLContent.GPO.SecurityDescriptor.SDDL.'#text' -join $Splitter } else { $XMLContent.GPO.SecurityDescriptor.SDDL.'#text' } 'Owner' = $XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text' 'OwnerSID' = $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' 'OwnerType' = $OwnerType 'ACL' = @( [PsCustomObject] @{ 'Name' = $XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text' 'Sid' = $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' 'PermissionType' = 'Allow' 'Inherited' = $false 'Permissions' = 'Owner' } $XMLContent.GPO.SecurityDescriptor.Permissions.TrusteePermissions | ForEach-Object -Process { if ($_) { [PsCustomObject] @{ 'Name' = $_.trustee.name.'#Text' 'Sid' = $_.trustee.SID.'#Text' 'PermissionType' = $_.type.PermissionType 'Inherited' = if ($_.Inherited -eq 'false') { $false } else { $true } 'Permissions' = $_.Standard.GPOGroupedAccessEnum } } } ) 'Auditing' = if ($XMLContent.GPO.SecurityDescriptor.AuditingPresent.'#text' -eq 'true') { $true } else { $false } 'Links' = $XMLContent.GPO.LinksTo | ForEach-Object -Process { if ($_) { [PSCustomObject] @{ CanonicalName = $_.SOMPath Enabled = $_.Enabled NoOverride = $_.NoOverride } } } <# SOMName SOMPath Enabled NoOverride ------- ------- ------- ---------- ad ad.evotec.xyz true false #> #| Select-Object -ExpandProperty SOMPath } } #break } function New-ADForestDrives { [cmdletbinding()] param( [string] $ForestName, [string] $ObjectDN ) if (-not $Global:ADDrivesMapped) { if ($ForestName) { $Forest = Get-ADForest -Identity $ForestName } else { $Forest = Get-ADForest } if ($ObjectDN) { # This doesn't work because no Domain and no $Server $DNConverted = (ConvertFrom-DistinguishedName -DistinguishedName $ObjectDN -ToDC) -replace '=' -replace ',' if (-not(Get-PSDrive -Name $DNConverted -ErrorAction SilentlyContinue)) { try { if ($Server) { $null = New-PSDrive -Name $DNConverted -Root '' -PSProvider ActiveDirectory -Server $Server.Hostname[0] -Scope Global -WhatIf:$false Write-Verbose "New-ADForestDrives - Mapped drive $Domain / $($Server.Hostname[0])" } else { $null = New-PSDrive -Name $DNConverted -Root '' -PSProvider ActiveDirectory -Server $Domain -Scope Global -WhatIf:$false } } catch { Write-Warning "New-ADForestDrives - Couldn't map new AD psdrive for $Domain / $($Server.Hostname[0])" } } } else { foreach ($Domain in $Forest.Domains) { try { $Server = Get-ADDomainController -Discover -DomainName $Domain $DomainInformation = Get-ADDomain -Server $Server.Hostname[0] } catch { Write-Warning "New-ADForestDrives - Can't process domain $Domain - $($_.Exception.Message)" continue } $ObjectDN = $DomainInformation.DistinguishedName $DNConverted = (ConvertFrom-DistinguishedName -DistinguishedName $ObjectDN -ToDC) -replace '=' -replace ',' if (-not(Get-PSDrive -Name $DNConverted -ErrorAction SilentlyContinue)) { try { if ($Server) { $null = New-PSDrive -Name $DNConverted -Root '' -PSProvider ActiveDirectory -Server $Server.Hostname[0] -Scope Global -WhatIf:$false Write-Verbose "New-ADForestDrives - Mapped drive $Domain / $Server" } else { $null = New-PSDrive -Name $DNConverted -Root '' -PSProvider ActiveDirectory -Server $Domain -Scope Global -WhatIf:$false } } catch { Write-Warning "New-ADForestDrives - Couldn't map new AD psdrive for $Domain / $Server $($_.Exception.Message)" } } } } $Global:ADDrivesMapped = $true } } function Remove-PrivPermission { [cmdletBinding(SupportsShouldProcess)] param( [string] $Principal, [validateset('DistinguishedName', 'Name', 'Sid')][string] $PrincipalType = 'DistinguishedName', [PSCustomObject] $GPOPermission, [alias('PermissionType')][Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType ) if ($GPOPermission.Name) { $Text = "Removing SID: $($GPOPermission.Sid), Name: $($GPOPermission.Name), SidType: $($GPOPermission.SidType) from domain $($GPOPermission.DomainName)" } else { $Text = "Removing SID: $($GPOPermission.Sid), Name: EMPTY, SidType: $($GPOPermission.SidType) from domain $($GPOPermission.DomainName)" } if ($PrincipalType -eq 'DistinguishedName') { if ($GPOPermission.DistinguishedName -eq $Principal -and $GPOPermission.Permission -eq $IncludePermissionType) { if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, $Text)) { try { Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.Name) / Type: $($GPOPermission.PermissionType)" $GPOPermission.GPOSecurity.Remove($GPOPermission.GPOSecurityPermissionItem) $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } catch { Write-Warning "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType failed for $($Principal) with error: $($_.Exception.Message)" } } } } elseif ($PrincipalType -eq 'Sid') { if ($GPOPermission.Sid -eq $Principal -and $GPOPermission.Permission -eq $IncludePermissionType) { if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, $Text)) { try { Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.Name) / Type: $($GPOPermission.PermissionType)" $GPOPermission.GPOSecurity.Remove($GPOPermission.GPOSecurityPermissionItem) $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } catch { if ($_.Exception.Message -like '*The request is not supported. (Exception from HRESULT: 0x80070032)*') { Write-Warning "Remove-GPOZaurrPermission - Bummer! The request is not supported, but lets fix it differently." # This is basically atomic approach. We will totally remove any permissions for that user on ACL level to get rid of this situation. # This situation should only happen if DENY is on FULL Control $ACL = Get-ADACL -ADObject $GPOPermission.GPOObject.Path -Bundle #-Verbose:$VerbosePreference if ($ACL) { Remove-ADACL -ACL $ACL -Principal $Principal -AccessControlType Deny -Verbose:$VerbosePreference } # I've noticed that in situation where Edit settings, delete, modify security is set and then set to Deny we need to fix it once more $ACL = Get-ADACL -ADObject $GPOPermission.GPOObject.Path -Bundle if ($ACL) { Remove-ADACL -ACL $ACL -Principal $Principal -AccessControlType Allow -Verbose:$VerbosePreference } } else { Write-Warning "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType failed for $($Principal) with error: $($_.Exception.Message)" } } } } } elseif ($PrincipalType -eq 'Name') { if ($GPOPermission.Name -eq $Principal -and $GPOPermission.Permission -eq $IncludePermissionType) { if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, $Text)) { try { Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.Name) / Type: $($GPOPermission.PermissionType)" $GPOPermission.GPOSecurity.Remove($GPOPermission.GPOSecurityPermissionItem) $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } catch { Write-Warning "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType failed for $($Principal) with error: $($_.Exception.Message)" } } } } } $Script:GPOPropetiesComputers = [ordered] @{ 'Account' = '' 'Audit' = '' 'AuditSetting' = '' 'AutoEnrollmentSettings' = '' 'Blocked' = '' 'certSettingsTrustedPublishers' = '' 'DataSourcesSettings' = '' 'DomainProfile' = '' 'Dot3SvcSetting' = '' 'EFSRecoveryAgent' = '' 'EFSSettings' = '' 'EnvironmentVariables' = '' 'EventLog' = '' 'File' = '' 'FilesSettings' = '' 'Folders' = '' 'General' = '' 'Global' = '' 'GlobalSettings' = '' 'InboundFirewallRules' = '' 'IntermediateCACertificate' = '' 'InternetZoneRule' = '' 'LocalUsersAndGroups' = '' 'MsiApplication' = '' 'NetworkOptions' = '' 'NetworkShares' = '' 'NTServices' = '' 'OutboundFirewallRules' = '' 'PathRule' = '' 'Policy' = '' 'PowerOptions' = '' 'PrinterConnection' = '' 'Printers' = '' 'PrivateProfile' = '' 'PublicProfile' = '' 'Registry' = '' 'RegistrySetting' = '' 'RegistrySettings' = '' 'RestrictedGroups' = '' 'RootCertificate' = '' 'RootCertificateSettings' = '' 'ScheduledTasks' = '' 'Script' = '' 'SecurityOptions' = '' 'ShortcutSettings' = '' 'SystemServices' = '' 'TrustedPublishersCertificate' = '' 'type' = '' 'UserRightsAssignment' = '' 'WLanSvcSetting' = '' } $Script:GPOPropertiesUsers = [ordered] @{ 'AutoDetectConfigSettings' = '' 'AutoEnrollmentSettings' = '' 'AutomaticConfiguration' = '' 'AutoSetupSetting' = '' 'Blocked' = '' 'BrowserTitle' = '' 'CustomSetupSetting' = '' 'DataSourcesSettings' = '' 'DefinesConnectionSettings' = '' 'DefinesEscOffSettings' = '' 'DefinesEscOnSettings' = '' 'DeleteChannels' = '' 'DriveMapSettings' = '' 'EscOffLocalSites' = '' 'EscOffSecurityZoneAndPrivacy' = '' 'EscOffTrustedSites' = '' 'EscOnLocalSites' = '' 'EscOnSecurityZoneAndPrivacy' = '' 'EscOnTrustedSites' = '' 'FavoriteURL' = '' 'FilesSettings' = '' 'Folder' = '' 'FolderOptions' = '' 'Folders' = '' 'General' = '' 'HomePage' = '' 'ImportedContentRatings' = '' 'InternetOptions' = '' 'LocalUsersAndGroups' = '' 'MsiApplication' = '' 'NetworkOptions' = '' 'PathRule' = '' 'PlaceFavoritesAtTop' = '' 'Policy' = '' 'PowerOptions' = '' 'PreferenceMode' = '' 'PrinterConnection' = '' 'Printers' = '' 'Programs' = '' 'ProxySettings' = '' 'RegionalOptionsSettings' = '' 'RegistrySetting' = '' 'RegistrySettings' = '' 'RestartSetupSetting' = '' 'ScheduledTasks' = '' 'Script' = '' 'SearchBar' = '' 'ShortcutSettings' = '' 'StartMenuSettings' = '' 'ToolsSetting' = '' 'TrustedPublisherLockdown' = '' 'type' = '' } function Add-GPOPermission { [cmdletBinding()] param( [validateset('WellKnownAdministrative', 'Administrative', 'AuthenticatedUsers', 'Default')][string] $Type = 'Default', [Microsoft.GroupPolicy.GPPermissionType] $IncludePermissionType, [alias('Principal')][Array] $Trustee, [alias('PrincipalType')][validateset('DistinguishedName', 'Name', 'Sid')][string] $TrusteeType = 'DistinguishedName' ) if ($Type -eq 'Default') { @{ Action = 'Add' Type = 'Standard' Trustee = $Trustee IncludePermissionType = $IncludePermissionType TrusteeType = $TrusteeType } } elseif ($Type -eq 'AuthenticatedUsers') { @{ Action = 'Add' Type = 'AuthenticatedUsers' IncludePermissionType = $IncludePermissionType } } elseif ($Type -eq 'Administrative') { @{ Action = 'Add' Type = 'Administrative' IncludePermissionType = $IncludePermissionType } } } function Add-GPOZaurrPermission { [cmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'GPOGUID')] param( [Parameter(ParameterSetName = 'GPOName', Mandatory)] [string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID', Mandatory)] [alias('GUID', 'GPOID')][string] $GPOGuid, [Parameter(ParameterSetName = 'ADObject', Mandatory)] [alias('OrganizationalUnit', 'DistinguishedName')][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject, [validateset('WellKnownAdministrative', 'Administrative', 'AuthenticatedUsers', 'Default')][string] $Type = 'Default', [string] $Principal, [alias('IncludePermissionType')][Microsoft.GroupPolicy.GPPermissionType[]] $PermissionType, [switch] $Inheritable, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [System.Collections.IDictionary] $ADAdministrativeGroups, [int] $LimitProcessing ) Begin { #$Count = 0 $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation if (-not $ADAdministrativeGroups) { $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } $ForestInformation = Get-ADForest } Process { if ($GPOName) { $Splat = @{ GPOName = $GPOName } } elseif ($GPOGUID) { $Splat = @{ GPOGUID = $GPOGUID } } else { $Splat = @{ } } $Splat['IncludeGPOObject'] = $true $Splat['Forest'] = $Forest $Splat['IncludeDomains'] = $Domain #$Splat['ExcludeDomains'] = $ExcludeDomains #$Splat['ExtendedForestInformation'] = $ExtendedForestInformation #$Splat['ExcludePermissionType'] = $ExcludePermissionType #$Splat['IncludePermissionType'] = $PermissionType- $Splat['SkipWellKnown'] = $SkipWellKnown.IsPresent $Splat['SkipAdministrative'] = $SkipAdministrative.IsPresent # Get-GPOZaurrPermission @Splat #Set-GPPermission -PermissionLevel $PermissionType -TargetName $Principal -TargetType Group -Verbose -DomainName 'ad.evotec.xyz' -Name $GPOName -Replace #-WhatIf $AdministrativeExists = @{ DomainAdmins = $false EnterpriseAdmins = $false } #continue [Array] $GPOPermissions = Get-GPOZaurrPermission @Splat [Array] $LimitedPermissions = foreach ($GPOPermission in $GPOPermissions) { #$GPOPermission = $_ # continue if ($Type -eq 'Default') { if ($GPOPermission.Name -eq $Principal -and $GPOPermission.Permission -eq $PermissionType) { #Write-Verbose "Add-GPOZaurrPermission - Permission $PermissionType already set for $($GPOPermission.Name) / $($GPOPermission.DomainName)" $GPOPermission break } } elseif ($Type -eq 'Administrative') { if ($GPOPermission.Permission -eq $PermissionType) { $AdministrativeGroup = $ADAdministrativeGroups['BySID'][$GPOPermission.SID] if ($AdministrativeGroup) { if ($GPOPermission.SID -like '*-512') { #Write-Verbose "Add-GPOZaurrPermission - Permission $PermissionType already set for $($GPOPermission.Name) / $($GPOPermission.DomainName)" $AdministrativeExists['DomainAdmins'] = $true } elseif ($GPOPermission.SID -like '*-519') { #Write-Verbose "Add-GPOZaurrPermission - Permission $PermissionType already set for $($GPOPermission.Name) / $($GPOPermission.DomainName)" $AdministrativeExists['EnterpriseAdmins'] = $true } } } } elseif ($Type -eq 'WellKnownAdministrative') { if ($GPOPermission.Name -eq $Principal -and $GPOPermission.Permission -eq $PermissionType) { #Write-Verbose "Add-GPOZaurrPermission - Permission $PermissionType already set for $($GPOPermission.Name) / $($GPOPermission.DomainName)" $GPOPermission break } } elseif ($Type -eq 'AuthenticatedUsers') { if ($GPOPermission.Name -eq $Principal -and $GPOPermission.Permission -eq $PermissionType) { #Write-Verbose "Add-GPOZaurrPermission - Permission $PermissionType already set for $($GPOPermission.Name) / $($GPOPermission.DomainName)" $GPOPermission break } } # Write-Verbose "Test" # $GPOPermission #$GPOPermission.GPOSecurity.Add #void Add(Microsoft.GroupPolicy.GPPermission item) #void ICollection[GPPermission].Add(Microsoft.GroupPolicy.GPPermission item) #int IList.Add(System.Object value) # $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } if ($GPOPermissions.Count -gt 0) { if ($LimitedPermissions.Count -gt 0) { #$LimitedPermissions } else { if ($Type -eq 'Administrative') { if ($AdministrativeExists['DomainAdmins'] -eq $false) { $Principal = $ADAdministrativeGroups[$GPOPermission.DomainName]['DomainAdmins'] Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal)" $AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent) $GPOPermissions[0].GPOSecurity.Add($AddPermission) $GPOPermissions[0].GPOObject.SetSecurityInfo( $GPOPermissions[0].GPOSecurity) } if ($AdministrativeExists['EnterpriseAdmins'] -eq $false) { $Principal = $ADAdministrativeGroups[$ForestInformation.RootDomain]['EnterpriseAdmins'] Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal)" $AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent) $GPOPermissions[0].GPOSecurity.Add($AddPermission) $GPOPermissions[0].GPOObject.SetSecurityInfo( $GPOPermissions[0].GPOSecurity) } } elseif ($Type -eq 'Default') { try { Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal)" $AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent) $GPOPermissions[0].GPOSecurity.Add($AddPermission) $GPOPermissions[0].GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } catch { Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)" } } <# [Microsoft.GroupPolicy.GPPermission]::new OverloadDefinitions ------------------- Microsoft.GroupPolicy.GPPermission new(string trustee, Microsoft.GroupPolicy.GPPermissionType rights, bool inheritable) Microsoft.GroupPolicy.GPPermission new(System.Security.Principal.IdentityReference identity, Microsoft.GroupPolicy.GPPermissionType rights, bool inheritable) #> } } else { Write-Warning "Add-GPOZaurrPermission - GPO $($GPOPermissions[0].GPOName) has no permissions. Weird." } } End { } } function Backup-GPOZaurr { [cmdletBinding(SupportsShouldProcess)] param( [int] $LimitProcessing, [validateset('All', 'Empty', 'Unlinked')][string[]] $Type = 'All', [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [string[]] $GPOPath, [string] $BackupPath, [switch] $BackupDated ) Begin { if ($BackupDated) { $BackupFinalPath = "$BackupPath\$((Get-Date).ToString('yyyy-MM-dd_HH_mm_ss'))" } else { $BackupFinalPath = $BackupPath } Write-Verbose "Backup-GPOZaurr - Backing up to $BackupFinalPath" $null = New-Item -ItemType Directory -Path $BackupFinalPath -Force $Count = 0 } Process { Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -GPOPath $GPOPath | ForEach-Object { if ($Type -contains 'All') { Write-Verbose "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)" $Count++ try { $BackupInfo = Backup-GPO -Guid $_.GUID -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer $BackupInfo } catch { Write-Warning "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } if ($LimitProcessing -eq $Count) { break } } if ($Type -notcontains 'All' -and $Type -contains 'Empty') { if ($_.ComputerSettingsAvailable -eq $false -and $_.UserSettingsAvailable -eq $false) { Write-Verbose "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)" $Count++ try { $BackupInfo = Backup-GPO -Guid $_.GUID -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer $BackupInfo } catch { Write-Warning "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } if ($LimitProcessing -eq $Count) { break } } } if ($Type -notcontains 'All' -and $Type -contains 'Unlinked') { if ($_.Linked -eq $false) { Write-Verbose "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)" $Count++ try { $BackupInfo = Backup-GPO -Guid $_.GUID -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer $BackupInfo } catch { Write-Warning "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } if ($LimitProcessing -eq $Count) { break } } } } } End { } } function Get-GPOZaurr { [cmdletBinding()] param( [string] $GPOName, [alias('GUID', 'GPOID')][string] $GPOGuid, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [string[]] $GPOPath, [switch] $PermissionsOnly, [switch] $OwnerOnly, [switch] $Limited, [System.Collections.IDictionary] $ADAdministrativeGroups ) Begin { if (-not $ADAdministrativeGroups) { Write-Verbose "Get-GPOZaurr - Getting ADAdministrativeGroups" $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } if (-not $GPOPath) { $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } } Process { if (-not $GPOPath) { foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation.QueryServers[$Domain]['HostName'][0] if ($GPOName) { Get-GPO -Name $GPOName -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object { Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain" if (-not $Limited) { try { $XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop } catch { Write-Warning "Get-GPOZaurr - Failed to get GPOReport: $($_.Exception.Message). Skipping." continue } Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups } else { $_ } } } elseif ($GPOGuid) { Get-GPO -Guid $GPOGuid -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object { Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain" if (-not $Limited) { try { $XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop } catch { Write-Warning "Get-GPOZaurr - Failed to get GPOReport: $($_.Exception.Message). Skipping." continue } Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups } else { $_ } } } else { Get-GPO -All -Server $QueryServer -Domain $Domain -ErrorAction SilentlyContinue | ForEach-Object { Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain" if (-not $Limited) { try { $XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop } catch { Write-Warning "Get-GPOZaurr - Failed to get GPOReport: $($_.Exception.Message). Skipping." continue } Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups } else { $_ } } } } } else { foreach ($Path in $GPOPath) { Get-ChildItem -LiteralPath $Path -Recurse -Filter *.xml | ForEach-Object { $XMLContent = [XML]::new() $XMLContent.Load($_.FullName) Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -PermissionsOnly:$PermissionsOnly.IsPresent } } } } End { } } function Get-GPOZaurrAD { [cmdletbinding(DefaultParameterSetName = 'Default')] param( [Parameter(ParameterSetName = 'GPOName')] [string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID')] [alias('GUID', 'GPOID')][string] $GPOGuid, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation ) Begin { $ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } Process { foreach ($Domain in $ForestInformation.Domains) { if ($PSCmdlet.ParameterSetName -eq 'GPOGUID') { if ($GPOGuid) { if ($GPOGUID -notlike '*{*') { $GUID = -join ("{", $GPOGUID, '}') } else { $GUID = $GPOGUID } $Splat = @{ Filter = "(objectClass -eq 'groupPolicyContainer') -and (Name -eq '$GUID')" Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0] } } else { Write-Warning "Get-GPOZaurrAD - GPOGUID parameter is empty. Provide name and try again." continue } } elseif ($PSCmdlet.ParameterSetName -eq 'GPOName') { if ($GPOName) { $Splat = @{ Filter = "(objectClass -eq 'groupPolicyContainer') -and (DisplayName -eq '$GPOName')" Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0] } } else { Write-Warning "Get-GPOZaurrAD - GPOName parameter is empty. Provide name and try again." continue } } else { $Splat = @{ Filter = "(objectClass -eq 'groupPolicyContainer')" Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0] } } Get-ADObject @Splat -Properties DisplayName, Name, Created, Modified, gPCFileSysPath, gPCFunctionalityVersion, gPCWQLFilter, gPCMachineExtensionNames, Description, CanonicalName, DistinguishedName | ForEach-Object -Process { #, Deleted -IncludeDeletedObjects #if ($_) { $DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_.DistinguishedName -ToDomainCN $Output = [ordered]@{ } <# $Search = -join ($DomainCN, $Output['Guid']) if ($GPOCache -and -not $Limited) { $Output['DisplayName'] = $GPOCache[$Search].DisplayName $Output['DomainName'] = $GPOCache[$Search].DomainName $Output['Owner'] = $GPOCache[$Search].Owner $Output['GpoStatus'] = $GPOCache[$Search].GpoStatus $Output['Description'] = $GPOCache[$Search].Description $Output['CreationTime'] = $GPOCache[$Search].CreationTime $Output['ModificationTime'] = $GPOCache[$Search].ModificationTime } #> $Output['DisplayName'] = $_.DisplayName $Output['DomainName'] = $DomainCN $Output['Description'] = $_.Description $Output['GUID'] = $_.Name -replace '{' -replace '}' $Output['Path'] = $_.gPCFileSysPath $Output['FunctionalityVersion'] = $_.gPCFunctionalityVersion $Output['Created'] = $_.Created $Output['Modified'] = $_.Modified $Output['GPOCanonicalName'] = $_.CanonicalName $Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_.DistinguishedName -ToDC $Output['GPODistinguishedName'] = $_.DistinguishedName [PSCustomObject] $Output <# CanonicalName : ad.evotec.xyz/System/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9} Created : 20.05.2018 09:55:29 Description : DisplayName : Default Domain Policy DistinguishedName : CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=Policies,CN=System,DC=ad,DC=evotec,DC=xyz gPCFileSysPath : \\ad.evotec.xyz\sysvol\ad.evotec.xyz\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9} gPCFunctionalityVersion : 2 gPCMachineExtensionNames : [{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{53D6AB1B-2488-11D1-A28C-00C04FB94F17}][{827D319E-6EAC-11D2-A4EA-00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}][{B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A}{53D6AB1B-2488-11D1-A28C-00C04FB94F17}] Modified : 26.04.2020 18:53:56 Name : {31B2F340-016D-11D2-945F-00C04FB984F9} ObjectClass : groupPolicyContainer ObjectGUID : 679a6dd9-30fb-438c-a35f-e5fe8167703e #> #} } } } End { } } function Get-GPOZaurrBackupInformation { [cmdletBinding()] param( [string[]] $BackupFolder ) Begin { } Process { foreach ($Folder in $BackupFolder) { if ($Folder) { if ((Test-Path -LiteralPath "$Folder\manifest.xml")) { [xml] $Xml = Get-Content -LiteralPath "$Folder\manifest.xml" $Xml.Backups.BackupInst | ForEach-Object -Process { [PSCustomObject] @{ DisplayName = $_.GPODisplayName.'#cdata-section' DomainName = $_.GPODomain.'#cdata-section' Guid = $_.GPOGUid.'#cdata-section' -replace '{' -replace '}' DomainGuid = $_.GPODomainGuid.'#cdata-section' -replace '{' -replace '}' DomainController = $_.GPODomainController.'#cdata-section' BackupTime = [DateTime]::Parse($_.BackupTime.'#cdata-section') ID = $_.ID.'#cdata-section' -replace '{' -replace '}' Comment = $_.Comment.'#cdata-section' } } } else { Write-Warning "Get-GPOZaurrBackupInformation - No backup information available" } } } } End { } } function Get-GPOZaurrLink { [cmdletbinding()] param( [parameter(ParameterSetName = 'ADObject', ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject, # weirdly enough site doesn't really work this way unless you give it 'CN=Configuration,DC=ad,DC=evotec,DC=xyz' as SearchBase [parameter(ParameterSetName = 'Filter')][string] $Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')", [parameter(ParameterSetName = 'Filter')][string] $SearchBase, [parameter(ParameterSetName = 'Filter')][Microsoft.ActiveDirectory.Management.ADSearchScope] $SearchScope, [parameter(ParameterSetName = 'Linked', Mandatory)][validateset('Root', 'DomainControllers', 'Site', 'Other')][string] $Linked, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [switch] $Limited, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [System.Collections.IDictionary] $GPOCache, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('ForestName')][string] $Forest, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [string[]] $ExcludeDomains, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('Domain', 'Domains')][string[]] $IncludeDomains, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [System.Collections.IDictionary] $ExtendedForestInformation ) Begin { $ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation if (-not $GPOCache -and -not $Limited) { $GPOCache = @{ } foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] Get-GPO -All -DomainName $Domain -Server $QueryServer | ForEach-Object { $GPOCache["$Domain$($_.ID.Guid)"] = $_ } } } } Process { if (-not $ADObject) { if ($Linked) { foreach ($Domain in $ForestInformation.Domains) { $Splat = @{ #Filter = $Filter Properties = 'distinguishedName', 'gplink', 'CanonicalName' # Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')" Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0] } if ($Linked -contains 'DomainControllers') { $SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer'] #if ($SearchBase -notlike "*$DomainDistinguishedName") { # we check if SearchBase is part of domain distinugishname. If it isn't we skip # continue #} $Splat['Filter'] = "(objectClass -eq 'organizationalUnit')" $Splat['SearchBase'] = $SearchBase Get-ADObject @Splat | ForEach-Object -Process { Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache } } if ($Linked -contains 'Root') { $SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName'] #if ($SearchBase -notlike "*$DomainDistinguishedName") { # we check if SearchBase is part of domain distinugishname. If it isn't we skip # continue # } $Splat['Filter'] = "objectClass -eq 'domainDNS'" $Splat['SearchBase'] = $SearchBase Get-ADObject @Splat | ForEach-Object -Process { Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache } } if ($Linked -contains 'Site') { # Sites are defined only in primary domain if ($ForestInformation['DomainsExtended'][$Domain]['DNSRoot'] -eq $ForestInformation['DomainsExtended'][$Domain]['Forest']) { $SearchBase = -join ("CN=Configuration,", $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']) # if ($SearchBase -notlike "*$DomainDistinguishedName") { # we check if SearchBase is part of domain distinugishname. If it isn't we skip #continue #} $Splat['Filter'] = "(objectClass -eq 'site')" $Splat['SearchBase'] = $SearchBase Get-ADObject @Splat | ForEach-Object -Process { Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache } } } if ($Linked -contains 'Other') { $SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName'] #if ($SearchBase -notlike "*$DomainDistinguishedName") { # we check if SearchBase is part of domain distinugishname. If it isn't we skip # continue #} $Splat['Filter'] = "(objectClass -eq 'organizationalUnit')" $Splat['SearchBase'] = $SearchBase Get-ADObject @Splat | ForEach-Object -Process { if ($_.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']) { # other skips Domain Root } elseif ($_.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']) { # other skips Domain Controllers } else { Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache } } } } } else { foreach ($Domain in $ForestInformation.Domains) { $Splat = @{ Filter = $Filter Properties = 'distinguishedName', 'gplink', 'CanonicalName' Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0] } if ($PSBoundParameters.ContainsKey('SearchBase')) { $DomainDistinguishedName = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName'] if ($SearchBase -notlike "*$DomainDistinguishedName") { # we check if SearchBase is part of domain distinugishname. If it isn't we skip continue } $Splat['SearchBase'] = $SearchBase } if ($PSBoundParameters.ContainsKey('SearchScope')) { $Splat['SearchScope'] = $SearchScope } Get-ADObject @Splat | ForEach-Object { Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache } } } } else { foreach ($Object in $ADObject) { Get-PrivGPOZaurrLink -Object $Object -Limited:$Limited.IsPresent -GPOCache $GPOCache } } } End { } } function Get-GPOZaurrOwner { [cmdletbinding(DefaultParameterSetName = 'Default')] param( [Parameter(ParameterSetName = 'GPOName')][string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID')][alias('GUID', 'GPOID')][string] $GPOGuid, [switch] $IncludeSysvol, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [System.Collections.IDictionary] $ADAdministrativeGroups ) Begin { $ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation if (-not $ADAdministrativeGroups) { $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } } Process { $getGPOZaurrADSplat = @{ Forest = $Forest IncludeDomains = $IncludeDomains ExcludeDomains = $ExcludeDomains ExtendedForestInformation = $ForestInformation } if ($GPOName) { $getGPOZaurrADSplat['GPOName'] = $GPOName } elseif ($GPOGuid) { $getGPOZaurrADSplat['GPOGUID'] = $GPOGuid } Get-GPOZaurrAD @getGPOZaurrADSplat | ForEach-Object -Process { Write-Verbose "Get-GPOZaurrOwner - Processing GPO: $($_.DisplayName) from domain: $($_.DomainName)" $ACL = Get-ADACLOwner -ADObject $_.GPODistinguishedName -Resolve -ADAdministrativeGroups $ADAdministrativeGroups $Object = [ordered] @{ DisplayName = $_.DisplayName DomainName = $_.DomainName GUID = $_.GUID DistinguishedName = $_.GPODistinguishedName Owner = $ACL.OwnerName OwnerSid = $ACL.OwnerSid OwnerType = $ACL.OwnerType } if ($IncludeSysvol) { $FileOwner = Get-FileOwner -JustPath -Path $_.Path -Resolve $Object['SysvolOwner'] = $FileOwner.OwnerName $Object['SysvolSid'] = $FileOwner.OwnerSid $Object['SysvolType'] = $FileOwner.OwnerType $Object['SysvolPath'] = $_.Path } [PSCUstomObject] $Object } } End { } } function Get-GPOZaurrPassword { [cmdletBinding()] param( [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [string[]] $GPOPath ) if (-not $GPOPath) { if (-not $ExtendedForestInformation) { $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains } else { $ForestInformation = $ExtendedForestInformation } [Array] $GPOPath = foreach ($Domain in $ForestInformation.Domains) { -join ('\\', $Domain, '\SYSVOL\', $Domain, '\Policies') } } if (-not $GPOPath) { return } foreach ($Path in $GPOPath) { #Extract the all XML files in the Folders $Items = Get-ChildItem -LiteralPath $Path -Recurse -Filter *.xml $Output = foreach ($XMLFileName in $Items) { #Convert XML in a String file [string]$XMLString = Get-Content ($XMLFileName.FullName) #Check if Cpassword Exist in the file if ($XMLString.Contains("cpassword")) { #Take the Cpassword Value from XML String file [string]$Cpassword = [regex]::matches($XMLString, '(cpassword=).+?(?=\")') $Cpassword = $Cpassword.split('(\")')[1] #Check if Cpassword has a value if ($Cpassword.Length -gt 20 -and $Cpassword -notlike '*cpassword*') { $Mod = ($Cpassword.length % 4) switch ($Mod) { '1' { $Cpassword = $Cpassword.Substring(0, $Cpassword.Length - 1) } '2' { $Cpassword += ('=' * (4 - $Mod)) } '3' { $Cpassword += ('=' * (4 - $Mod)) } } $Base64Decoded = [Convert]::FromBase64String($Cpassword) $AesObject = [System.Security.Cryptography.AesCryptoServiceProvider]::new() #Use th AES Key [Byte[]] $AesKey = @(0x4e, 0x99, 0x06, 0xe8, 0xfc, 0xb6, 0x6c, 0xc9, 0xfa, 0xf4, 0x93, 0x10, 0x62, 0x0f, 0xfe, 0xe8, 0xf4, 0x96, 0xe8, 0x06, 0xcc, 0x05, 0x79, 0x90, 0x20, 0x9b, 0x09, 0xa4, 0x33, 0xb6, 0x6c, 0x1b) $AesIV = New-Object Byte[]($AesObject.IV.Length) $AesObject.IV = $AesIV $AesObject.Key = $AesKey $DecryptorObject = $AesObject.CreateDecryptor() [Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length) #Convert Hash variable in a String valute $Password = [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock) } else { $Password = '' } #[string]$GPOguid = [regex]::matches($XMLFileName.DirectoryName, '(?<=\{).+?(?=\})') #$GPODetail = Get-GPO -guid $GPOguid [xml] $XMLContent = $XMLString #if (-not $XMLContent.gpo.Computer.ExtensionData.Extension.LocalUsersAndGroups.User.Properties.cpassword -and -not $XMLContent.gpo.User.ExtensionData.Extension.DriveMapSettings.Drive.Properties.cpassword) { #Write-Host '' #} if ($Password) { $PasswordStatus = $true } else { $PasswordStatus = $false } [PsCustomObject] @{ 'Name' = $XMLContent.GPO.Name 'Links' = $XMLContent.GPO.LinksTo #| Select-Object -ExpandProperty SOMPath 'Enabled' = $XMLContent.GPO.GpoStatus 'PasswordStatus' = $PasswordStatus #'GPO' = $XMLContent.gpo.Computer.ExtensionData.Extension.LocalUsersAndGroups 'User' = $XMLContent.gpo.Computer.ExtensionData.Extension.LocalUsersAndGroups.User.name 'Cpassword' = $XMLContent.gpo.Computer.ExtensionData.Extension.LocalUsersAndGroups.User.Properties.cpassword 'CpasswordMap' = $XMLContent.gpo.User.ExtensionData.Extension.DriveMapSettings.Drive.Properties.cpassword 'Password' = $Password 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText 'Domain' = $XMLContent.GPO.Identifier.Domain 'ComputerSettingsAvailable' = if ($null -eq $XMLContent.GPO.Computer.ExtensionData) { $false } else { $true } 'ComputerSettingsStatus' = if ($XMLContent.GPO.Computer.VersionDirectory -eq 0 -and $XMLContent.GPO.Computer.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" } 'ComputerEnabled' = [bool] $XMLContent.GPO.Computer.Enabled 'ComputerSetttingsVersionIdentical' = if ($XMLContent.GPO.Computer.VersionDirectory -eq $XMLContent.GPO.Computer.VersionSysvol) { $true } else { $false } 'ComputerSettings' = $XMLContent.GPO.Computer.ExtensionData.Extension 'UserSettingsAvailable' = if ($null -eq $XMLContent.GPO.User.ExtensionData) { $false } else { $true } 'UserEnabled' = [bool] $XMLContent.GPO.User.Enabled 'UserSettingsStatus' = if ($XMLContent.GPO.User.VersionDirectory -eq 0 -and $XMLContent.GPO.User.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" } 'UserSettingsVersionIdentical' = if ($XMLContent.GPO.User.VersionDirectory -eq $XMLContent.GPO.User.VersionSysvol) { $true } else { $false } 'UserSettings' = $XMLContent.GPO.User.ExtensionData.Extension 'CreationTime' = [DateTime] $XMLContent.GPO.CreatedTime 'ModificationTime' = [DateTime] $XMLContent.GPO.ModifiedTime 'ReadTime' = [DateTime] $XMLContent.GPO.ReadTime 'WMIFilter' = $GPO.WmiFilter.name 'WMIFilterDescription' = $GPO.WmiFilter.Description 'Path' = $GPO.Path #'SDDL' = if ($Splitter -ne '') { $XMLContent.GPO.SecurityDescriptor.SDDL.'#text' -join $Splitter } else { $XMLContent.GPO.SecurityDescriptor.SDDL.'#text' } 'ACL' = $XMLContent.GPO.SecurityDescriptor.Permissions.TrusteePermissions | ForEach-Object -Process { [PSCustomObject] @{ 'User' = $_.trustee.name.'#Text' 'Permission Type' = $_.type.PermissionType 'Inherited' = $_.Inherited 'Permissions' = $_.Standard.GPOGroupedAccessEnum } } } #Write-Host "I find a Password [ " $Password " ] The GPO named:" $GPODetail" and th file is:" $XMLFileName } #if($XMLContent.Contains("cpassword") } $Output } } function Get-GPOZaurrPermission { [cmdletBinding(DefaultParameterSetName = 'GPO' )] param( [Parameter(ParameterSetName = 'GPOName')] [string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID')] [alias('GUID', 'GPOID')][string] $GPOGuid, [string[]] $Principal, [validateset('DistinguishedName', 'Name', 'Sid')][string] $PrincipalType = 'Sid', [validateSet('Unknown', 'NotWellKnown', 'NotWellKnownAdministrative', 'NotAdministrative', 'Administrative', 'All')][string[]] $Type = 'All', [switch] $SkipWellKnown, [switch] $SkipAdministrative, [switch] $ResolveAccounts, [switch] $IncludeOwner, [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType, [switch] $IncludeGPOObject, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation ) Begin { $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation if ($Type -eq 'Unknown') { if ($SkipAdministrative -or $SkipWellKnown) { Write-Warning "Get-GPOZaurrPermission - Using SkipAdministrative or SkipWellKnown while looking for Unknown doesn't make sense as only Unknown will be displayed." } } if ($ResolveAccounts) { $Accounts = @{ } foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] $DomainInformation = Get-ADDomain -Server $QueryServer $Users = Get-ADUser -Filter * -Server $QueryServer -Properties PasswordLastSet, LastLogonDate, UserPrincipalName foreach ($User in $Users) { $U = -join ($DomainInformation.NetBIOSName, '\', $User.SamAccountName) $Accounts[$U] = $User } $Groups = Get-ADGroup -Filter * -Server $QueryServer foreach ($Group in $Groups) { $G = -join ($DomainInformation.NetBIOSName, '\', $Group.SamAccountName) $Accounts[$G] = $Group } } } } Process { foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] if ($GPOName) { $getGPOSplat = @{ Name = $GPOName Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } elseif ($GPOGuid) { $getGPOSplat = @{ Guid = $GPOGuid Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } else { $getGPOSplat = @{ All = $true Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } Get-GPO @getGPOSplat | ForEach-Object -Process { $getPrivPermissionSplat = @{ Principal = $Principal PrincipalType = $PrincipalType Accounts = $Accounts Type = $Type GPO = $_ SkipWellKnown = $SkipWellKnown.IsPresent SkipAdministrative = $SkipAdministrative.IsPresent IncludeOwner = $IncludeOwner.IsPresent IncludeGPOObject = $IncludeGPOObject.IsPresent IncludePermissionType = $IncludePermissionType ExcludePermissionType = $ExcludePermissionType ADAdministrativeGroups = $ADAdministrativeGroups } Get-PrivPermission @getPrivPermissionSplat } } } End { } } function Get-GPOZaurrPermissionConsistency { [cmdletBinding()] param( [Parameter(ParameterSetName = 'GPOName')][string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID')][alias('GUID', 'GPOID')][string] $GPOGuid, [Parameter(ParameterSetName = 'Type')][validateSet('Consistent', 'Inconsistent', 'All')][string[]] $Type = 'All', [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [switch] $IncludeGPOObject, [switch] $VerifyInside ) Begin { $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } Process { foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] if ($GPOName) { $getGPOSplat = @{ Name = $GPOName Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } elseif ($GPOGuid) { $getGPOSplat = @{ Guid = $GPOGuid Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } else { $getGPOSplat = @{ All = $true Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } Get-GPO @getGPOSplat | ForEach-Object -Process { try { $IsConsistent = $_.IsAclConsistent() $ErrorMessage = '' } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Get-GPOZaurrPermissionConsistency - Failed to get consistency: $($_.Exception.Message)." $IsConsistent = 'Not available.' } $SysVolpath = -join ('\\', $Domain, '\sysvol\', $Domain, '\Policies\{', $_.ID.GUID, '}') if ($VerifyInside) { $FolderPermissions = Get-WinADSharePermission -Path $SysVolpath [Array] $NotInheritedPermissions = foreach ($File in $FolderPermissions) { if ($File.Path -ne $SysVolpath -and $File.IsInherited -eq $false) { $File } } if ($NotInheritedPermissions.Count -eq 0) { $ACLConsistentInside = $true } else { $ACLConsistentInside = $false } } else { $ACLConsistentInside = $null } $Object = [ordered] @{ DisplayName = $_.DisplayName # : New Group Policy Object DomainName = $_.DomainName # : ad.evotec.xyz ACLConsistent = $IsConsistent ACLConsistentInside = $ACLConsistentInside Owner = $_.Owner # : EVOTEC\Enterprise Admins Path = $_.Path SysVolPath = $SysvolPath Id = $_.Id # : 8a7bc515-d7fd-4d1f-90b8-e47c15f89295 GpoStatus = $_.GpoStatus # : AllSettingsEnabled Description = $_.Description # : CreationTime = $_.CreationTime # : 04.03.2020 17:19:42 ModificationTime = $_.ModificationTime# : 06.05.2020 10:30:36 UserVersion = $_.UserVersion # : AD Version: 0, SysVol Version: 0 ComputerVersion = $_.ComputerVersion # : AD Version: 1, SysVol Version: 1 WmiFilter = $_.WmiFilter # : Error = $ErrorMessage } if ($IncludeGPOObject) { $Object['IncludeGPOObject'] = $_ } if ($VerifyInside) { $Object['ACLConsistentInsideDetails'] = $NotInheritedPermissions } [PSCustomObject] $Object } <# } elseif ($GPOGuid) { Get-GPO -Guid $GPOGuid -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object -Process { try { $IsConsistent = $_.IsAclConsistent() $ErrorMessage = '' } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Get-GPOZaurrPermissionConsistency - Failed to get consistency: $($_.Exception.Message)." $IsConsistent = 'Not available.' } $SysVolpath = -join ('\\', $Domain, '\sysvol\', $Domain, '\Policies\{', $_.ID.GUID, '}') if ($Advanced) { $FolderPermissions = Get-WinADSharePermission -Path $SysVolpath [Array] $NotInheritedPermissions = foreach ($File in $FolderPermissions) { if ($File.Path -ne $SysVolpath -and $File.IsInherited -eq $false) { $File } } if ($NotInheritedPermissions.Count -eq 0) { $ACLConsistentInside = $true } else { $ACLConsistentInside = $false } } else { $ACLConsistentInside = $null } $Object = [ordered] @{ DisplayName = $_.DisplayName # : New Group Policy Object DomainName = $_.DomainName # : ad.evotec.xyz ACLConsistent = $IsConsistent ACLConsistentInside = $ACLConsistentInside Owner = $_.Owner # : EVOTEC\Enterprise Admins Path = $_.Path SysVolPath = $SysvolPath Id = $_.Id # : 8a7bc515-d7fd-4d1f-90b8-e47c15f89295 GpoStatus = $_.GpoStatus # : AllSettingsEnabled Description = $_.Description # : CreationTime = $_.CreationTime # : 04.03.2020 17:19:42 ModificationTime = $_.ModificationTime# : 06.05.2020 10:30:36 UserVersion = $_.UserVersion # : AD Version: 0, SysVol Version: 0 ComputerVersion = $_.ComputerVersion # : AD Version: 1, SysVol Version: 1 WmiFilter = $_.WmiFilter # : Error = $ErrorMessage } if ($Advanced) { $Object['ACLConsistentInsideDetails'] = $NotInheritedPermissions } if ($IncludeGPOObject) { $Object['IncludeGPOObject'] = $_ } [PSCustomObject] $Object } } else { Get-GPO -All -Domain $Domain -Server $QueryServer | ForEach-Object -Process { try { $IsConsistent = $_.IsAclConsistent() $ErrorMessage = '' } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Get-GPOZaurrPermissionConsistency - Failed to get consistency: $($_.Exception.Message)." $IsConsistent = 'Not available.' } if ($Type -eq 'Consistent') { if (-not $IsConsistent) { return } } elseif ($Type -eq 'Inconsistent') { if ($IsConsistent -eq $true) { return } } $SysVolpath = -join ('\\', $Domain, '\sysvol\', $Domain, '\Policies\{', $_.ID.GUID, '}') if ($Advanced) { $FolderPermissions = Get-WinADSharePermission -Path $SysVolpath [Array] $NotInheritedPermissions = foreach ($File in $FolderPermissions) { if ($File.Path -ne $SysVolpath -and $File.IsInherited -eq $false) { $File } } if ($NotInheritedPermissions.Count -eq 0) { $ACLConsistentInside = $true } else { $ACLConsistentInside = $false } } else { $ACLConsistentInside = $null } $Object = [ordered] @{ DisplayName = $_.DisplayName # : New Group Policy Object DomainName = $_.DomainName # : ad.evotec.xyz ACLConsistent = $IsConsistent ACLConsistentInside = $ACLConsistentInside Owner = $_.Owner # : EVOTEC\Enterprise Admins Path = $_.Path SysVolPath = $SysvolPath Id = $_.Id # : 8a7bc515-d7fd-4d1f-90b8-e47c15f89295 GpoStatus = $_.GpoStatus # : AllSettingsEnabled Description = $_.Description # : CreationTime = $_.CreationTime # : 04.03.2020 17:19:42 ModificationTime = $_.ModificationTime# : 06.05.2020 10:30:36 UserVersion = $_.UserVersion # : AD Version: 0, SysVol Version: 0 ComputerVersion = $_.ComputerVersion # : AD Version: 1, SysVol Version: 1 WmiFilter = $_.WmiFilter # : Error = $ErrorMessage } if ($Advanced) { $Object['ACLConsistentInsideDetails'] = $NotInheritedPermissions } if ($IncludeGPOObject) { $Object['IncludeGPOObject'] = $_ } [PSCustomObject] $Object } } #> } } End { } } function Get-GPOZaurrWMI { [cmdletBinding()] Param( [Guid[]] $Guid, [string[]] $Name, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation ) $wmiFilterAttr = "msWMI-Name", "msWMI-Parm1", "msWMI-Parm2", "msWMI-Author", "msWMI-ID", 'CanonicalName', 'Created', 'Modified' $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] if ($Guid -or $Name) { foreach ($N in $Name) { try { $ldapFilter = "(&(objectClass=msWMI-Som)(msWMI-Name=$N))" Get-ADObject -LDAPFilter $ldapFilter -Properties $wmiFilterAttr -Server $QueryServer | ForEach-Object -Process { $WMI = $_.'msWMI-Parm2' -split ';' [PSCustomObject] @{ DisplayName = $_.'msWMI-Name' Description = $_.'msWMI-Parm1' DomainName = $Domain NameSpace = $WMI[5] Query = $WMI[6] Author = $_.'msWMI-Author' ID = $_.'msWMI-ID' Created = $_.Created Modified = $_.Modified ObjectGUID = $_.'ObjectGUID' CanonicalName = $_.CanonicalName DistinguishedName = $_.'DistinguishedName' } } } catch { Write-Warning "Get-GPOZaurrWMI - Error processing WMI for $Domain`: $($_.Error.Exception)" } } foreach ($G in $GUID) { $ldapFilter = "(&(objectClass=msWMI-Som)(Name={$G}))" try { Get-ADObject -LDAPFilter $ldapFilter -Properties $wmiFilterAttr -Server $QueryServer | ForEach-Object -Process { $WMI = $_.'msWMI-Parm2' -split ';' [PSCustomObject] @{ DisplayName = $_.'msWMI-Name' Description = $_.'msWMI-Parm1' DomainName = $Domain NameSpace = $WMI[5] Query = $WMI[6] Author = $_.'msWMI-Author' ID = $_.'msWMI-ID' Created = $_.Created Modified = $_.Modified ObjectGUID = $_.'ObjectGUID' CanonicalName = $_.CanonicalName DistinguishedName = $_.'DistinguishedName' } } } catch { Write-Warning "Get-GPOZaurrWMI - Error processing WMI for $Domain`: $($_.Error.Exception)" } } } else { $ldapFilter = "(objectClass=msWMI-Som)" try { Get-ADObject -LDAPFilter $ldapFilter -Properties $wmiFilterAttr -Server $QueryServer | ForEach-Object -Process { $WMI = $_.'msWMI-Parm2' -split ';' [PSCustomObject] @{ DisplayName = $_.'msWMI-Name' Description = $_.'msWMI-Parm1' DomainName = $Domain NameSpace = $WMI[5] Query = $WMI[6] Author = $_.'msWMI-Author' ID = $_.'msWMI-ID' Created = $_.Created Modified = $_.Modified ObjectGUID = $_.'ObjectGUID' CanonicalName = $_.CanonicalName DistinguishedName = $_.'DistinguishedName' } } } catch { Write-Warning "Get-GPOZaurrWMI - Error processing WMI for $Domain`: $($_.Error.Exception)" } } } } <# CanonicalName : ad.evotec.xyz/System/WMIPolicy/SOM/{E988C890-BDBC-4946-87B5-BF70F39F4686} CN : {E988C890-BDBC-4946-87B5-BF70F39F4686} Created : 08.04.2020 19:04:06 createTimeStamp : 08.04.2020 19:04:06 Deleted : Description : DisplayName : DistinguishedName : CN={E988C890-BDBC-4946-87B5-BF70F39F4686},CN=SOM,CN=WMIPolicy,CN=System,DC=ad,DC=evotec,DC=xyz dSCorePropagationData : {01.01.1601 01:00:00} instanceType : 4 isDeleted : LastKnownParent : Modified : 08.04.2020 19:04:06 modifyTimeStamp : 08.04.2020 19:04:06 msWMI-Author : przemyslaw.klys@evotec.pl msWMI-ChangeDate : 20200408170406.280000-000 msWMI-CreationDate : 20200408170406.280000-000 msWMI-ID : {E988C890-BDBC-4946-87B5-BF70F39F4686} msWMI-Name : Virtual Machines msWMI-Parm1 : Oh my description msWMI-Parm2 : 1;3;10;66;WQL;root\CIMv2;SELECT * FROM Win32_ComputerSystem WHERE Model = "Virtual Machine"; Name : {E988C890-BDBC-4946-87B5-BF70F39F4686} nTSecurityDescriptor : System.DirectoryServices.ActiveDirectorySecurity ObjectCategory : CN=ms-WMI-Som,CN=Schema,CN=Configuration,DC=ad,DC=evotec,DC=xyz ObjectClass : msWMI-Som ObjectGUID : c1ee708d-7a67-46e2-b13f-d11a573d2597 ProtectedFromAccidentalDeletion : False sDRightsEffective : 15 showInAdvancedViewOnly : True uSNChanged : 12785589 uSNCreated : 12785589 whenChanged : 08.04.2020 19:04:06 whenCreated : 08.04.2020 19:04:06 #> function Invoke-GPOZaurrPermission { [cmdletBinding(SupportsShouldProcess)] param( [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [parameter(Position = 0)] [scriptblock] $PermissionRules, [Parameter(ParameterSetName = 'GPOName')][string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID')][alias('GUID', 'GPOID')][string] $GPOGuid, [parameter(ParameterSetName = 'Linked', Mandatory)][validateset('Root', 'DomainControllers', 'Site', 'Other')][string] $Linked, [parameter(ParameterSetName = 'ADObject', ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject, [parameter(ParameterSetName = 'Filter')][string] $Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')", [parameter(ParameterSetName = 'Filter')][string] $SearchBase, [parameter(ParameterSetName = 'Filter')][Microsoft.ActiveDirectory.Management.ADSearchScope] $SearchScope, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [validateSet('Unknown', 'NotWellKnown', 'NotWellKnownAdministrative', 'NotAdministrative', 'All')][string[]] $Type, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [Array] $ApprovedGroups, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('Principal')][Array] $Trustee, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [Microsoft.GroupPolicy.GPPermissionType] $TrusteePermissionType, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('PrincipalType')][validateset('DistinguishedName', 'Name', 'Sid')][string] $TrusteeType = 'DistinguishedName', [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [System.Collections.IDictionary] $GPOCache, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('ForestName')][string] $Forest, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [string[]] $ExcludeDomains, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('Domain', 'Domains')][string[]] $IncludeDomains, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [System.Collections.IDictionary] $ExtendedForestInformation ) Begin { $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation <# $Script:Actions = @{ GpoApply = @{ Remove = @{ NotAdministrative = $false NotWellKnownAdministrative = $false } Add = @{ Administrative = $false WellKnownAdministrative = $false } } GpoRead = @{ Remove = @{ NotAdministrative = $false NotWellKnownAdministrative = $false } Add = @{ Administrative = $false WellKnownAdministrative = $false } } GpoCustom = @{ Remove = @{ NotAdministrative = $false NotWellKnownAdministrative = $false } Add = @{ Administrative = $false WellKnownAdministrative = $false } } GpoEditDeleteModifySecurity = @{ Remove = @{ NotAdministrative = $false NotWellKnownAdministrative = $false } Add = @{ Administrative = $false WellKnownAdministrative = $false } } GpoEdit = @{ Remove = @{ NotAdministrative = $false NotWellKnownAdministrative = $false } Add = @{ Administrative = $false WellKnownAdministrative = $false } } } #> } Process { if ($PermissionRules) { $Rules = & $PermissionRules <# foreach ($Rule in $Rules) { #$Actions["$Rule."] if ($Rule.Action -eq 'Remove' -and $Rule.Type -contains 'NotWellKnownAdministrative') { #$Actions.NotWellKnownAdministrative = $true } if ($Rule.Action -eq 'Remove' -and $Rule.Type -contains 'NotAdministrative') { #$Actions.Remove.NotAdministrative = $true } } #> } if ($GPOName -or $GPOGuid) { } else { $Splat = @{ } if ($ADObject) { $Splat['ADObject'] = $ADObject } elseif ($Linked) { $Splat['Linked'] = $Linked } else { if ($Filter) { $Splat['Filter'] = $Filter } if ($SearchBase) { $Splat['SearchBase'] = $SearchBase } if ($SearchScope) { $Splat['SearchScope'] = $SearchScope } } Get-GPOZaurrLink @Splat | ForEach-Object -Process { $GPO = $_ foreach ($Rule in $Rules) { if ($Rule.Action -eq 'Owner') { if ($Rule.Type -eq 'Administrative') { $AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"] if (-not $AdministrativeGroup) { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } } elseif ($Rule.Type -eq 'Default') { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner) to $($Rule.Principal)" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $Rule.Principal -Verbose:$false -WhatIf:$WhatIfPreference } continue } if ($Rule.Action -eq 'Remove') { $GPOPermissions = Get-GPOZaurrPermission -GPOGuid $_.GUID -IncludePermissionType $Rule.IncludePermissionType -ExcludePermissionType $Rule.ExcludePermissionType -Type $Rule.Type -IncludeGPOObject foreach ($Permission in $GPOPermissions) { Remove-PrivPermission -Principal $Permission.Sid -PrincipalType Sid -GPOPermission $Permission -IncludePermissionType $Permission.Permission #-IncludeDomains $GPO.DomainName } continue } if ($Rule.Action -eq 'Add') { #$GPOPermissions = Get-GPOZaurrPermission -GPOGuid $_.GUID -IncludePermissionType $Rule.IncludePermissionType -ExcludePermissionType $Rule.ExcludePermissionType -Type 'All' -IncludeGPOObject # foreach ($Permission in $GPOPermissions) { Add-GPOZaurrPermission -GPOGuid $_.GUID -IncludeDomains $GPO.DomainName -Type $Rule.Type -PermissionType $Rule.IncludePermissionType -ADAdministrativeGroups $ADAdministrativeGroups # } } } } } } End { } } function New-GPOZaurrWMI { [cmdletBinding(SupportsShouldProcess)] param( [parameter(Mandatory)][string] $Name, [string] $Description = ' ', [parameter(Mandatory)][string] $Query, [switch] $SkipQueryCheck, [switch] $Force, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation ) if (-not $Forest -and -not $ExcludeDomains -and -not $IncludeDomains -and -not $ExtendedForestInformation) { $IncludeDomains = $Env:USERDNSDOMAIN } if (-not $SkipQueryCheck) { try { $null = Get-CimInstance -Query $Query -ErrorAction Stop -Verbose:$false } catch { Write-Warning "New-GPOZaurrWMI - Query error $($_.Exception.Message). Terminating." return } } $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] $DomainInformation = Get-ADDomain -Server $QueryServer $defaultNamingContext = $DomainInformation.DistinguishedName #$defaultNamingContext = (Get-ADRootDSE).defaultnamingcontext [string] $Author = (([ADSI]"LDAP://<SID=$([System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value)>").UserPrincipalName).ToString() [string] $GUID = "{" + ([System.Guid]::NewGuid()) + "}" [string] $DistinguishedName = -join ("CN=", $GUID, ",CN=SOM,CN=WMIPolicy,CN=System,", $defaultNamingContext) $CurrentTime = (Get-Date).ToUniversalTime() [string] $CurrentDate = -join ( ($CurrentTime.Year).ToString("0000"), ($CurrentTime.Month).ToString("00"), ($CurrentTime.Day).ToString("00"), ($CurrentTime.Hour).ToString("00"), ($CurrentTime.Minute).ToString("00"), ($CurrentTime.Second).ToString("00"), ".", ($CurrentTime.Millisecond * 1000).ToString("000000"), "-000" ) [Array] $ExistingWmiFilter = Get-GPOZaurrWMI -ExtendedForestInformation $ForestInformation -IncludeDomains $Domain -Name $Name if ($ExistingWmiFilter.Count -eq 0) { [string] $WMIParm2 = -join ("1;3;10;", $Query.Length.ToString(), ";WQL;root\CIMv2;", $Query , ";") $OtherAttributes = @{ "msWMI-Name" = $Name "msWMI-Parm1" = $Description "msWMI-Parm2" = $WMIParm2 "msWMI-Author" = $Author "msWMI-ID" = $GUID "instanceType" = 4 "showInAdvancedViewOnly" = "TRUE" "distinguishedname" = $DistinguishedName "msWMI-ChangeDate" = $CurrentDate "msWMI-CreationDate" = $CurrentDate } $WMIPath = -join ("CN=SOM,CN=WMIPolicy,CN=System,", $defaultNamingContext) try { Write-Verbose "New-GPOZaurrWMI - Creating WMI filter $Name in $Domain" New-ADObject -Name $GUID -Type "msWMI-Som" -Path $WMIPath -OtherAttributes $OtherAttributes -Server $QueryServer } catch { Write-Warning "New-GPOZaurrWMI - Creating GPO filter error $($_.Exception.Message). Terminating." return } } else { foreach ($_ in $ExistingWmiFilter) { Write-Warning "New-GPOZaurrWMI - Skipping creation of GPO because name: $($_.DisplayName) guid: $($_.ID) for $($_.DomainName) already exists." } } } } function Remove-GPOPermission { [cmdletBinding()] param( [validateSet('Unknown', 'NotWellKnown', 'NotWellKnownAdministrative', 'Administrative', 'NotAdministrative', 'All')][string[]] $Type, [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType ) if ($Type) { @{ Action = 'Remove' Type = $Type IncludePermissionType = $IncludePermissionType ExcludePermissionType = $ExcludePermissionType } } <# foreach ($T in $Type) { foreach ($Permission in $IncludePermissionType) { if ($T -eq 'NotWellKnownAdministrative') { $Script:Actions[$Permission][$T] = $true } elseif ($T -eq 'NotAdministrative') { $Script:Actions[$Permission][$T] = $true } } } #> } <# function Find-GPOPermission { param( $GPOPermissions, [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [bool] $NotAdministrative, [bool] $NotWellKnownAdministrative ) foreach ($Permission in $GPOPermissions) { if ($Permission.Permission -in $IncludePermissionType) { if ($NotAdministrative -and $NotWellKnownAdministrative) { $Permission } } } } #> function Remove-GPOZaurr { [cmdletBinding(SupportsShouldProcess)] param( [parameter(Mandatory)][validateset('Empty', 'Unlinked')][string[]] $Type, [int] $LimitProcessing, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [string[]] $GPOPath, [string] $BackupPath, [switch] $BackupDated ) Begin { if ($BackupPath) { $BackupRequired = $true if ($BackupDated) { $BackupFinalPath = "$BackupPath\$((Get-Date).ToString('yyyy-MM-dd_HH_mm_ss'))" } else { $BackupFinalPath = $BackupPath } Write-Verbose "Remove-GPOZaurr - Backing up to $BackupFinalPath" $null = New-Item -ItemType Directory -Path $BackupFinalPath -Force } else { $BackupRequired = $false } $Count = 0 } Process { Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -GPOPath $GPOPath | ForEach-Object { if ($Type -contains 'Empty') { if ($_.ComputerSettingsAvailable -eq $false -and $_.UserSettingsAvailable -eq $false) { if ($BackupRequired) { try { Write-Verbose "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)" $BackupInfo = Backup-GPO -Guid $_.Guid -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer $BackupInfo $BackupOK = $true } catch { Write-Warning "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" $BackupOK = $false } } if (($BackupRequired -and $BackupOK) -or (-not $BackupRequired)) { try { Write-Verbose "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName)" Remove-GPO -Domain $_.DomainName -Guid $_.Guid -ErrorAction Stop #-Server $QueryServer } catch { Write-Warning "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } } $Count++ if ($LimitProcessing -eq $Count) { break } } } if ($Type -contains 'Unlinked') { if ($_.Linked -eq $false) { if ($BackupRequired) { try { Write-Verbose "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)" $BackupInfo = Backup-GPO -Guid $_.Guid -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer $BackupInfo $BackupOK = $true } catch { Write-Warning "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" $BackupOK = $false } } if (($BackupRequired -and $BackupOK) -or (-not $BackupRequired)) { try { Write-Verbose "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName)" Remove-GPO -Domain $_.DomainName -Guid $_.Guid -ErrorAction Stop #-Server $QueryServer } catch { Write-Warning "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } } $Count++ if ($LimitProcessing -eq $Count) { break } } } } } End { } } function Remove-GPOZaurrPermission { [cmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Global')] param( [Parameter(ParameterSetName = 'GPOName', Mandatory)] [string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID', Mandatory)] [alias('GUID', 'GPOID')][string] $GPOGuid, [string[]] $Principal, [validateset('DistinguishedName', 'Name', 'Sid')][string] $PrincipalType = 'Sid', [validateset('Unknown', 'NotAdministrative', 'Default')][string[]] $Type = 'Default', [alias('PermissionType')][Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType, [switch] $SkipWellKnown, [switch] $SkipAdministrative, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [int] $LimitProcessing ) Begin { $Count = 0 $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation if ($Type -eq 'Unknown') { if ($SkipAdministrative -or $SkipWellKnown) { Write-Warning "Remove-GPOZaurrPermission - Using SkipAdministrative or SkipWellKnown while looking for Unknown doesn't make sense as only Unknown will be displayed." } } } Process { if ($Type -contains 'Named' -and $Principal.Count -eq 0) { Write-Warning "Remove-GPOZaurrPermission - When using type Named you need to provide names to remove. Terminating." return } # $GPOPermission.GPOSecurity.RemoveTrustee($GPOPermission.Sid) #void RemoveTrustee(string trustee) #void RemoveTrustee(System.Security.Principal.IdentityReference identity) #$GPOPermission.GPOSecurity.Remove #void RemoveAt(int index) #void IList[GPPermission].RemoveAt(int index) #void IList.RemoveAt(int index) foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] if ($GPOName) { $getGPOSplat = @{ Name = $GPOName Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } elseif ($GPOGuid) { $getGPOSplat = @{ Guid = $GPOGuid Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } else { $getGPOSplat = @{ All = $true Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } Get-GPO @getGPOSplat | ForEach-Object -Process { $getPrivPermissionSplat = @{ Principal = $Principal PrincipalType = $PrincipalType Accounts = $Accounts Type = $Type GPO = $_ SkipWellKnown = $SkipWellKnown.IsPresent SkipAdministrative = $SkipAdministrative.IsPresent IncludeOwner = $false IncludeGPOObject = $true IncludePermissionType = $IncludePermissionType ExcludePermissionType = $ExcludePermissionType ADAdministrativeGroups = $ADAdministrativeGroups } [Array] $GPOPermissions = Get-PrivPermission @getPrivPermissionSplat if ($GPOPermissions.Count -gt 0) { foreach ($Permission in $GPOPermissions) { Remove-PrivPermission -Principal $Permission.Sid -PrincipalType Sid -GPOPermission $Permission -IncludePermissionType $Permission.Permission #-IncludeDomains $GPO.DomainName } $Count++ if ($Count -eq $LimitProcessing) { # skipping skips per removed permission not per gpo. break } } } } <# Get-GPOZaurrPermission @Splat | ForEach-Object -Process { $GPOPermission = $_ if ($Type -contains 'Unknown') { if ($GPOPermission.SidType -eq 'Unknown') { #Write-Verbose "Remove-GPOZaurrPermission - Removing $($GPOPermission.Sid) from $($GPOPermission.DisplayName) at $($GPOPermission.DomainName)" if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, "Removing $($GPOPermission.Sid) from $($GPOPermission.DisplayName) at $($GPOPermission.DomainName)")) { try { Write-Verbose "Remove-GPOZaurrPermission - Removing permission $($GPOPermission.Permission) for $($GPOPermission.Sid)" $GPOPermission.GPOSecurity.RemoveTrustee($GPOPermission.Sid) $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) #$GPOPermission.GPOSecurity.RemoveAt($GPOPermission.GPOSecurityPermissionItem) #$GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } catch { Write-Warning "Remove-GPOZaurrPermission - Removing permission $($GPOPermission.Permission) for $($GPOPermission.Sid) with error: $($_.Exception.Message)" } # Set-GPPPermission doesn't work on Unknown Accounts } $Count++ if ($Count -eq $LimitProcessing) { # skipping skips per removed permission not per gpo. break } } } if ($Type -contains 'Named') { } if ($Type -contains 'NotAdministrative') { } if ($Type -contains 'Default') { Remove-PrivPermission -Principal $Principal -PrincipalType $PrincipalType -GPOPermission $GPOPermission -IncludePermissionType $IncludePermissionType } #Set-GPPermission -PermissionLevel None -TargetName $GPOPermission.Sid -Verbose -DomainName $GPOPermission.DomainName -Guid $GPOPermission.GUID #-WhatIf #Set-GPPermission -PermissionLevel GpoRead -TargetName 'Authenticated Users' -TargetType Group -Verbose -DomainName $Domain -Guid $_.GUID -WhatIf } #> } End {} } function Remove-GPOZaurrWMI { [CmdletBinding(SupportsShouldProcess)] Param ( [Guid[]] $Guid, [string[]] $Name, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation ) if (-not $Forest -and -not $ExcludeDomains -and -not $IncludeDomains -and -not $ExtendedForestInformation) { $IncludeDomains = $Env:USERDNSDOMAIN } $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] [Array] $Objects = @( if ($Guid) { Get-GPOZaurrWMI -Guid $Guid -ExtendedForestInformation $ForestInformation -IncludeDomains $Domain } if ($Name) { Get-GPOZaurrWMI -Name $Name -ExtendedForestInformation $ForestInformation -IncludeDomains $Domain } ) $Objects | ForEach-Object -Process { if ($_.DistinguishedName) { Write-Verbose "Remove-GPOZaurrWMI - Removing WMI Filter $($_.DistinguishedName)" Remove-ADObject $_.DistinguishedName -Confirm:$false -Server $QueryServer } } } } function Repair-GPOZaurrPermissionConsistency { [cmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Default')] param( [Parameter(ParameterSetName = 'GPOName')][string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID')][alias('GUID', 'GPOID')][string] $GPOGuid, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [int] $LimitProcessing = [int32]::MaxValue ) $ConsistencySplat = @{ Forest = $Forest IncludeDomains = $IncludeDomains ExcludeDomains = $ExcludeDomains ExtendedForestInformation = $ExtendedForestInformation Verbose = $VerbosePreference } if ($GPOName) { $ConsistencySplat['GPOName'] = $GPOName } elseif ($GPOGuid) { $ConsistencySplat['GPOGuid'] = $GPOGUiD } else { $ConsistencySplat['Type'] = 'Inconsistent' } Get-GPOZaurrPermissionConsistency @ConsistencySplat -IncludeGPOObject | Where-Object { if ($_.ACLConsistent -eq $false) { $_ } } | Select-Object -First $LimitProcessing | ForEach-Object { #Write-Verbose "Repair-GPOZaurrPermissionConsistency - Repairing GPO consistency $($_.DisplayName) from domain: $($_.DomainName)" if ($PSCmdlet.ShouldProcess($_.DisplayName, "Reparing GPO permissions consistency in domain $($_.DomainName)")) { try { $_.IncludeGPOObject.MakeAclConsistent() } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Repair-GPOZaurrPermissionConsistency - Failed to set consistency: $($ErrorMessage)." } } } } function Restore-GPOZaurr { [cmdletBinding()] param( [parameter(Mandatory)][string] $BackupFolder, [alias('Name')][string] $DisplayName, [string] $NewDisplayName, [string] $Domain, [switch] $SkipBackupSummary ) if ($BackupFolder) { if (Test-Path -LiteralPath $BackupFolder) { if ($DisplayName) { if (-not $SkipBackupSummary) { $BackupSummary = Get-GPOZaurrBackupInformation -BackupFolder $BackupFolder if ($Domain) { [Array] $FoundGPO = $BackupSummary | Where-Object { $_.DisplayName -eq $DisplayName -and $_.DomainName -eq $Domain } } else { [Array] $FoundGPO = $BackupSummary | Where-Object { $_.DisplayName -eq $DisplayName } } foreach ($GPO in $FoundGPO) { if ($NewDisplayName) { Import-GPO -Path $BackupFolder -BackupId $GPO.ID -Domain $GPO.Domain -TargetName $NewDisplayName -CreateIfNeeded } else { Write-Verbose "Restore-GPOZaurr - Restoring GPO $($GPO.DisplayName) from $($GPO.DomainName) / BackupId: $($GPO.ID)" try { Restore-GPO -Path $BackupFolder -BackupId $GPO.ID -Domain $GPO.DomainName } catch { Write-Warning "Restore-GPOZaurr - Restoring GPO $($GPO.DisplayName) from $($GPO.DomainName) failed: $($_.Exception.Message)" } } } } else { if ($Domain) { Write-Verbose "Restore-GPOZaurr - Restoring GPO $($Name) from $($Domain)" try { Restore-GPO -Path $BackupFolder -Name $Name -Domain $Domain } catch { Write-Warning "Restore-GPOZaurr - Restoring GPO $($Name) from $($Domain) failed: $($_.Exception.Message)" } } else { Write-Verbose "Restore-GPOZaurr - Restoring GPO $($Name)" try { Restore-GPO -Path $BackupFolder -Name $Name } catch { Write-Warning "Restore-GPOZaurr - Restoring GPO $($Name) failed: $($_.Exception.Message)" } } } } else { $BackupSummary = Get-GPOZaurrBackupInformation -BackupFolder $BackupFolder foreach ($GPO in $BackupSummary) { Write-Verbose "Restore-GPOZaurr - Restoring GPO $($GPO.DisplayName) from $($GPO.DomainName) / BackupId: $($GPO.ID)" try { Restore-GPO -Path $BackupFolder -Domain $GPO.DomainName -BackupId $GPO.ID } catch { Write-Warning "Restore-GPOZaurr - Restoring GPO $($GPO.DisplayName) from $($GPO.DomainName) failed: $($_.Exception.Message)" } } } } else { Write-Warning "Restore-GPOZaurr - BackupFolder incorrect ($BackupFolder)" } } } function Save-GPOZaurrFiles { [cmdletBinding()] param( [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [string[]] $GPOPath, [switch] $DeleteExisting ) if ($GPOPath) { if (-not $ExtendedForestInformation) { $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains } else { $ForestInformation = $ExtendedForestInformation } if ($DeleteExisting) { $Test = Test-Path -LiteralPath $GPOPath if ($Test) { Write-Verbose "Save-GPOZaurrFiles - Removing existing content in $GPOPath" Remove-Item -LiteralPath $GPOPath -Recurse } } $null = New-Item -ItemType Directory -Path $GPOPath -Force foreach ($Domain in $ForestInformation.Domains) { Write-Verbose "Save-GPOZaurrFiles - Processing GPO for $Domain" Get-GPO -All -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain | ForEach-Object { $XMLContent = Get-GPOReport -ID $_.ID.Guid -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain $Path = [io.path]::Combine($GPOPath, "$($_.ID.Guid).xml") $XMLContent | Set-Content -LiteralPath $Path -Force -Encoding Unicode } } } } function Set-GPOOwner { [cmdletBinding()] param( [validateset('Administrative', 'Default')][string] $Type = 'Default', [string] $Principal ) if ($Type -eq 'Default') { if ($Principal) { @{ Action = 'Owner' Type = 'Default' Principal = $Principal } } } elseif ($Type -eq 'Administrative') { @{ Action = 'Owner' Type = 'Administrative' Principal = '' } } } function Set-GPOZaurrOwner { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER Type Unknown - finds unknown Owners and sets them to Administrative (Domain Admins) or chosen principal NotMatching - find administrative groups only and if sysvol and gpo doesn't match - replace with chosen principal or Domain Admins if not specified NotAdministrative - combination of Unknown/NotMatching and NotAdministrative - replace with chosen principal or Domain Admins if not specified All - if Owner is known it checks if it's Administrative, if it sn't it fixes that. If owner is unknown it fixes it .PARAMETER GPOName Parameter description .PARAMETER GPOGuid Parameter description .PARAMETER Forest Parameter description .PARAMETER ExcludeDomains Parameter description .PARAMETER IncludeDomains Parameter description .PARAMETER ExtendedForestInformation Parameter description .PARAMETER Principal Parameter description .PARAMETER SkipSysvol Parameter description .PARAMETER LimitProcessing Parameter description .EXAMPLE An example .NOTES General notes #> [cmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Type')] param( [Parameter(ParameterSetName = 'Type', Mandatory)] [validateset('Unknown', 'NotAdministrative', 'NotMatching', 'All')][string] $Type, [Parameter(ParameterSetName = 'Named')][string] $GPOName, [Parameter(ParameterSetName = 'Named')][alias('GUID', 'GPOID')][string] $GPOGuid, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [alias('ForestName')][string] $Forest, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [string[]] $ExcludeDomains, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [alias('Domain', 'Domains')][string[]] $IncludeDomains, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [System.Collections.IDictionary] $ExtendedForestInformation, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [string] $Principal, [switch] $SkipSysvol, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [int] $LimitProcessing = [int32]::MaxValue ) Begin { #Write-Verbose "Set-GPOZaurrOwner - Getting ADAdministrativeGroups" $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation #Write-Verbose "Set-GPOZaurrOwner - Processing GPO for Type $Type" } Process { $getGPOZaurrOwnerSplat = @{ IncludeSysvol = -not $SkipSysvol.IsPresent Forest = $Forest IncludeDomains = $IncludeDomains ExcludeDomains = $ExcludeDomains ExtendedForestInformation = $ExtendedForestInformation ADAdministrativeGroups = $ADAdministrativeGroups Verbose = $VerbosePreference } if ($GPOName) { $getGPOZaurrOwnerSplat['GPOName'] = $GPOName } elseif ($GPOGuid) { $getGPOZaurrOwnerSplat['GPOGuid'] = $GPOGUiD } Get-GPOZaurrOwner @getGPOZaurrOwnerSplat | Where-Object { if ($_.Owner) { $AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($_.Owner)"] } else { $AdministrativeGroup = $null } if (-not $SkipSysvol) { if ($_.SysvolOwner) { $AdministrativeGroupSysvol = $ADAdministrativeGroups['ByNetBIOS']["$($_.SysvolOwner)"] } else { $AdministrativeGroupSysvol = $null } } if ($Type -eq 'NotAdministrative') { if (-not $AdministrativeGroup -or (-not $AdministrativeGroupSysvol -and -not $SkipSysvol)) { $_ } else { if ($AdministrativeGroup -ne $AdministrativeGroupSysvol) { Write-Verbose "Set-GPOZaurrOwner - Detected mismatch GPO: $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner). Fixing required." $_ } } <# if (-not $AdministrativeGroup -and (-not $AdministrativeGroupSysvol -and -not $SkipSysvol)) { $Action = 'Both' $_ } elseif (-not $AdministrativeGroup) { $Action = 'OnlyGPO' $_ } elseif (-not $AdministrativeGroupSysvol -and -not $SkipSysvol) { $Action = 'OnlyFileSystem' $_ } else { if ($_.Owner -ne $_.SysvolOwner) { $Action = 'OnlyFileSystem' $_ } } #> } elseif ($Type -eq 'Unknown') { if (-not $_.Owner -or (-not $_.SysvolOwner -and -not $SkipSysvol)) { $_ } } elseif ($Type -eq 'NotMatching') { if ($SkipSysvol) { Write-Verbose "Set-GPOZaurrOwner - Detected mismatch GPO: $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner). SysVol scanning is disabled. Skipping." } else { if ($AdministrativeGroup -ne $AdministrativeGroupSysvol) { #Write-Verbose "Set-GPOZaurrOwner - Detected mismatch GPO: $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner). Fixing required." $_ } } } else { # we run with no type, that means we need to either set it to principal or to Administrative if ($_.Owner) { # we check if Principal is not set $AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($_.Owner)"] if (-not $SkipSysvol -and $_.SysvolOwner) { $AdministrativeGroupSysvol = $ADAdministrativeGroups['ByNetBIOS']["$($_.SysvolOwner)"] if (-not $AdministrativeGroup -or -not $AdministrativeGroupSysvol) { $_ } } else { if (-not $AdministrativeGroup) { $_ } } } else { $_ } } } | Select-Object -First $LimitProcessing | ForEach-Object -Process { $GPO = $_ #if (-not $Principal) { # $Principal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] #} if (-not $Principal) { $DefaultPrincipal = $ADAdministrativeGroups["$($_.DomainName)"]['DomainAdmins'] } else { $DefaultPrincipal = $Principal } if ($Action -eq 'OnlyGPO') { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner) (SID: $($GPO.OwnerSID)) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.DistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } elseif ($Action -eq 'OnlyFileSystem') { if (-not $SkipSysvol) { Write-Verbose "Set-GPOZaurrOwner - Changing Sysvol Owner GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.SysvolOwner) (SID: $($GPO.SysvolSid)) to $DefaultPrincipal" Set-FileOwner -JustPath -Path $GPO.SysvolPath -Owner $DefaultPrincipal -Verbose:$true -WhatIf:$WhatIfPreference } } else { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner) (SID: $($GPO.OwnerSID)) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.DistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference if (-not $SkipSysvol) { Write-Verbose "Set-GPOZaurrOwner - Changing Sysvol Owner GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.SysvolOwner) (SID: $($GPO.SysvolSid)) to $DefaultPrincipal" Set-FileOwner -JustPath -Path $GPO.SysvolPath -Owner $DefaultPrincipal -Verbose:$true -WhatIf:$WhatIfPreference } } } <# if ($Type -contains 'All') { # Regardless who is the owner it is overwritten if ($Principal) { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $Principal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $Principal -Verbose:$false -WhatIf:$WhatIfPreference } else { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } $Count++ if ($Count -eq $LimitProcessing) { break } } elseif ($Type -contains 'NotAdministrative' -and $Type -notcontains 'All') { if ($GPO.Owner) { $AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"] if (-not $AdministrativeGroup) { if ($Principal) { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $Principal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } else { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } $Count++ if ($Count -eq $LimitProcessing) { return } } } } else ($Type -contains 'Unknown' -and $Type -notcontains 'All') { if ($null -eq $GPO.Owner) { if ($Principal) { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner NULL/$($GPO.OwnerSID) to $Principal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $Principal -Verbose:$false -WhatIf:$WhatIfPreference } else { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner NULL/$($GPO.OwnerSID) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } $Count++ if ($Count -eq $LimitProcessing) { break } } } else { $GPO = $_ if ($Principal) { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $Principal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $Principal -Verbose:$false -WhatIf:$WhatIfPreference } else { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } } #> #} #> #} <# else { $getGPOZaurrOwnerSplat = @{ IncludeSysvol = $IncludeSysVol Forest = $Forest IncludeDomains = $IncludeDomains ExcludeDomains = $ExcludeDomains ExtendedForestInformation = $ExtendedForestInformation ADAdministrativeGroups = $ADAdministrativeGroups GPOName = $GPOName GPOGuid = $GPOGUiD } Get-GPOZaurrOwner @getGPOZaurrOwnerSplat $IncludeSysVol | ForEach-Object -Process { $GPO = $_ if ($Principal) { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $Principal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $Principal -Verbose:$false -WhatIf:$WhatIfPreference } else { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } $Count++ if ($Count -eq $LimitProcessing) { break } } } #> } End { } } Export-ModuleMember -Function @('Add-GPOPermission', 'Add-GPOZaurrPermission', 'Backup-GPOZaurr', 'Get-GPOZaurr', 'Get-GPOZaurrAD', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrLink', 'Get-GPOZaurrOwner', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrPermissionConsistency', 'Get-GPOZaurrWMI', 'Invoke-GPOZaurrPermission', 'New-GPOZaurrWMI', 'Remove-GPOPermission', 'Remove-GPOZaurr', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Repair-GPOZaurrPermissionConsistency', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOOwner', 'Set-GPOZaurrOwner') -Alias @() |