mirror of
https://github.com/EvotecIT/GPOZaurr.git
synced 2026-07-26 20:00:09 +00:00
Compare commits
188 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 55ab89a5b0 | |||
| 9da8c7c94b | |||
| 53aa69029f | |||
| 4189ad12f2 | |||
| b1c3037803 | |||
| 62308cbb6d | |||
| 914dcfb0c4 | |||
| 2cf4d2c6c9 | |||
| d53d50f99b | |||
| 2ef3c306ff | |||
| 481338f83b | |||
| eaf3b231ae | |||
| b2c73479c7 | |||
| 38c6327e30 | |||
| 0b3e072a3e | |||
| 89664bfd02 | |||
| 1021ebe5f4 | |||
| 521125bbc1 | |||
| ae6b596e5b | |||
| bfe50f02fe | |||
| 187b44a19d | |||
| 36793b33c4 | |||
| 94e6c785c1 | |||
| efbd2b12de | |||
| d0a678353f | |||
| 6b0f3b332d | |||
| 37483c91b5 | |||
| 9172948be3 | |||
| 14567959f7 | |||
| 6a9ad14083 | |||
| e00de40cd2 | |||
| 6f806698e9 | |||
| 2e1571b0d7 | |||
| ffedd2d9d2 | |||
| 911bc50f22 | |||
| 0383d249e9 | |||
| 8070179d27 | |||
| db67e6191e | |||
| db9b6d60c6 | |||
| 2c965d81d5 | |||
| bff372affe | |||
| 138a0f411e | |||
| 1c37a9d1df | |||
| 30535c1baf | |||
| 56c722edd0 | |||
| 1f43ae21fe | |||
| ef90ef05f7 | |||
| 43b304d252 | |||
| 24e691edb9 | |||
| 1c787735d4 | |||
| 13a2aa6482 | |||
| 1ac1f83abd | |||
| 65b2867588 | |||
| 1043a2d512 | |||
| 7002813027 | |||
| 03b8e4f2cb | |||
| 680762733e | |||
| 7a37d5b9f6 | |||
| a1e9a4a3fa | |||
| 8cbb3272b2 | |||
| 8da0c1793d | |||
| 5a7b20ca2b | |||
| ebffba3b95 | |||
| a79071c395 | |||
| a5a889b468 | |||
| 62d73041ea | |||
| d88307047c | |||
| 7d85d41747 | |||
| a1fab2ceb2 | |||
| 99f07f61e3 | |||
| 58136f0c43 | |||
| b55729d8e0 | |||
| 6206a33a2e | |||
| 165381b1e3 | |||
| ea1de10fd9 | |||
| 03453b6bdb | |||
| 4d7f49902d | |||
| 508d778d06 | |||
| 5c3157f15f | |||
| b33f42b320 | |||
| f8d3b363e7 | |||
| a68d917d19 | |||
| 946bb3029f | |||
| 975bf5b889 | |||
| 6fa0818375 | |||
| 2abec9579a | |||
| 75a8083368 | |||
| 06c711694e | |||
| 8a38ac4556 | |||
| 9d2ae288c0 | |||
| 0bc50328ee | |||
| a74b662c9b | |||
| 37d8db92f7 | |||
| d094344f9f | |||
| a24b1ff958 | |||
| de076a1cb4 | |||
| 663eecc01b | |||
| d1b7d71ad9 | |||
| d888f135e0 | |||
| 81ecf580c4 | |||
| 34c9d59150 | |||
| 80580b7dce | |||
| 304f70a4d9 | |||
| ab6c61ac52 | |||
| dbe79a7833 | |||
| 0cc05c4aeb | |||
| c10a4c088e | |||
| 015afd69a4 | |||
| 2fa9b202bc | |||
| 25bbf8d52e | |||
| 8a009bf288 | |||
| ed76fc9513 | |||
| 646c22bdab | |||
| d4f8cdc8e8 | |||
| 166d4fb767 | |||
| 0ca98a4165 | |||
| a5bcbbf285 | |||
| 513179fd03 | |||
| 72cd1da9ae | |||
| 3fe52c99b5 | |||
| fc6fe14579 | |||
| bd5a73439d | |||
| 469332e543 | |||
| 6cbe3a375a | |||
| c987ca9863 | |||
| f0d24e1902 | |||
| 61b9c916e7 | |||
| deebcb825d | |||
| 7adfd1ef65 | |||
| 828c221ac9 | |||
| 8e80fd423d | |||
| f52fd60fef | |||
| 9594afb246 | |||
| 7c52284b48 | |||
| 2fd64952af | |||
| 15538e8559 | |||
| a36a470538 | |||
| 0a5d65761c | |||
| 7ed3cb6dad | |||
| 4d9edde212 | |||
| 7ba40e3981 | |||
| ec81655019 | |||
| 752a34204b | |||
| 0afe6c6d23 | |||
| 2a300747a1 | |||
| 94b8a71192 | |||
| 49b9eccfd1 | |||
| 92b5f00d7f | |||
| 1f625e4e90 | |||
| 7ac406ca24 | |||
| 4d584902e8 | |||
| 7e6efb81f1 | |||
| 16b0a0f4b6 | |||
| 85eaa4e5d6 | |||
| 8c555a4fa9 | |||
| 8bc85a4c91 | |||
| 84ad1df972 | |||
| 71a12316e3 | |||
| 4a3a49440f | |||
| 0b2e2ea96c | |||
| 4ae3bbce12 | |||
| 471bc04fb2 | |||
| 4d050c536d | |||
| 508402b4bf | |||
| 6f1ac33df8 | |||
| 5130ef77e5 | |||
| 19c2b6bf90 | |||
| 5b1aaae915 | |||
| d239c979e9 | |||
| 35c04c88c0 | |||
| 048347c830 | |||
| 563ba55342 | |||
| 5a62968925 | |||
| a47fa85a8c | |||
| b156c91c7c | |||
| d44e27e68c | |||
| e5dc00007f | |||
| c31c8257a3 | |||
| b135fc3c7f | |||
| 0699cdf2ff | |||
| fb366e5e78 | |||
| 6456325584 | |||
| 808d05adb4 | |||
| f72a8d8018 | |||
| de6d06e60c | |||
| d14a8b7d5a | |||
| d9d4a641eb | |||
| a4c2e69117 |
@@ -1,4 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$T = Get-GPOZaurrPermission -Type Unknown -Verbose
|
||||
$T | Out-HtmlView -ScrollX -Filtering -DisablePaging -ScrollY -Online
|
||||
$T #| Out-HtmlView #-ScrollX -Filtering -DisablePaging -ScrollY -Online
|
||||
@@ -1,11 +1,11 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Step 1 - Create report
|
||||
$Report = Get-GPOZaurrPermission -Type All
|
||||
$Report | ConvertTo-Excel -FilePath $Env:UserProfile\Desktop\GPOOutput.xlsx -ExcelWorkSheetName 'GPO Permissions Before' -AutoFilter -AutoFit
|
||||
#$Report = Get-GPOZaurrPermission -Type All
|
||||
#$Report | ConvertTo-Excel -FilePath $Env:UserProfile\Desktop\GPOOutput.xlsx -ExcelWorkSheetName 'GPO Permissions Before' -AutoFilter -AutoFit
|
||||
|
||||
# Step 2 - Verify couple of GPOS returned with whatif
|
||||
#Remove-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 4 -WhatIf
|
||||
Remove-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 4 -WhatIf
|
||||
|
||||
# Step 3 - Confirm the change without whatif
|
||||
#Remove-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 4
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$SummaryHashtable = Get-GPOZaurrLink -AsHashTable -Summary
|
||||
$SummaryHashtable | Format-Table -AutoSize
|
||||
$SummaryHashtable[5]
|
||||
@@ -1,3 +1,3 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Get-GPOZaurrLink | Format-Table -AutoSize *
|
||||
Get-GPOZaurrLink -Verbose | Format-Table -AutoSize *
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
Get-GPOZaurrLink -SearchBase 'OU=Domain Controllers,DC=ad,DC=evotec,DC=xyz' | Format-Table -AutoSize
|
||||
|
||||
Get-GPOZaurrLink -SearchBase 'OU=Computers,OU=Production,DC=ad,DC=evotec,DC=xyz' | Format-Table -AutoSize
|
||||
Get-GPOZaurrLink -SearchBase 'OU=Accounts,OU=Production,DC=ad,DC=evotec,DC=xyz' | Format-Table -AutoSize
|
||||
|
||||
Get-GPOZaurrLink -SearchBase 'DC=ad,DC=evotec,DC=xyz' -SearchScope Base | Format-Table -AutoSize
|
||||
@@ -1,6 +1,7 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Get-ADOrganizationalUnit -Filter * -Properties distinguishedName, LinkedGroupPolicyObjects | Get-GPOZaurrLink | Format-Table
|
||||
Get-ADOrganizationalUnit -Filter * -Properties canonicalname, distinguishedName, LinkedGroupPolicyObjects | Get-GPOZaurrLink | Format-Table
|
||||
# gpLink is required property. While LinkedGroupPolicyObjects does work it doesn't contain information about enabled/enforced GPO
|
||||
Get-ADOrganizationalUnit -Filter * -Properties distinguishedName, LinkedGroupPolicyObjects, gpLink | Get-GPOZaurrLink | Format-Table
|
||||
Get-ADOrganizationalUnit -Filter * -Properties canonicalname, distinguishedName, LinkedGroupPolicyObjects, gpLink | Get-GPOZaurrLink | Format-Table
|
||||
Get-ADObject -Filter * -Properties distinguishedName, gplink -Server 'ad.evotec.pl' | Get-GPOZaurrLink | Format-Table -AutoSize
|
||||
Get-GPOZaurrLink | Format-Table -AutoSize
|
||||
@@ -0,0 +1,3 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Get-GPOZaurrLink -Site 'Katowice-1','Katowice-2' | Format-Table -AutoSize *
|
||||
@@ -0,0 +1,3 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Get-GPOZaurrLink -Linked Site | Format-Table -AutoSize *
|
||||
@@ -0,0 +1,8 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Summary = Get-GPOZaurrLink -Summary
|
||||
$Summary | Format-Table -AutoSize *
|
||||
|
||||
$OneGPO = $Summary | Where-Object { $_.DisplayName -eq 'ALL | Enable RDP' }
|
||||
$OneGPO.Links
|
||||
$OneGPO.LinksObjects | Format-Table *
|
||||
@@ -0,0 +1,41 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Clear-Host
|
||||
|
||||
$GPOName = 'TEST | Deny Admins'
|
||||
|
||||
$T = Get-GPOZaurrPermission -GPOName $GPOName #-IncludePermissionType GpoEditDeleteModifySecurity -PermitType Allow -Principal 'Domain Admins' -PrincipalType 'Name'
|
||||
$T | Format-Table *
|
||||
|
||||
|
||||
return
|
||||
|
||||
<#
|
||||
# this will go and check for both Domain Admins / Enterprise Admins - if found won't do anything
|
||||
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Type Administrative -Verbose
|
||||
# this will go thru, because PrincipalType is not set to look by Name. Be precise with what you ask for
|
||||
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Principal 'Domain Admins' -Verbose
|
||||
# this will be detected as already existing
|
||||
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Principal 'Domain Admins' -PrincipalType Name -Verbose
|
||||
# this will be added only if it doesn't exists - assuming that przemyslaw.klys is displayed in Get-GPOZaurrPermissions
|
||||
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoApply -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose
|
||||
# this will be added only if it doesn't exists - assuming that przemyslaw.klys is displayed in Get-GPOZaurrPermissions
|
||||
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose
|
||||
# this will ADD system if it doesn't eists
|
||||
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Type WellKnownAdministrative -Verbose
|
||||
|
||||
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoApply -Principal 'przemyslaw.klys' -Verbose
|
||||
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEditDeleteModifySecurity -Principal 'przemyslaw.klys' -Verbose
|
||||
# this will not work because we already have GPOEditDeleteModifySecurity which is higher than GpoEDIT
|
||||
Add-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoEdit -Principal 'przemyslaw.klys' -Verbose
|
||||
#>
|
||||
Add-GPOZaurrPermission -GPOName $GPOName -Type AuthenticatedUsers -PermissionType GpoRead -Verbose #-WhatIf
|
||||
|
||||
#$T = Get-GPOZaurrPermission -GPOName $GPOName #-ExcludePermissionType GpoApply,GpoRead -IncludeGPOObject
|
||||
#$T | Format-Table -AutoSize *
|
||||
|
||||
#Remove-GPOZaurrPermission -GPOName $GPOName -PermissionType GpoApply -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose
|
||||
|
||||
#$T = Get-GPOZaurrPermission -GPOName $GPOName #-ExcludePermissionType GpoApply,GpoRead -IncludeGPOObject
|
||||
#$T = Get-GPOZaurrPermission -GPOName $GPOName #-ExcludePermissionType GpoApply,GpoRead -IncludeGPOObject
|
||||
#$T | Format-Table -AutoSize *
|
||||
@@ -9,4 +9,4 @@ Invoke-GPOZaurrPermission -Linked Root -Verbose {
|
||||
Remove-GPOPermission -Type NotAdministrative, NotWellKnownAdministrative -IncludePermissionType GpoEdit, GpoEditDeleteModifySecurity
|
||||
Add-GPOPermission -Type Administrative -IncludePermissionType GpoEditDeleteModifySecurity
|
||||
#Add-GPOPermission -Type WellKnownAdministrative -IncludePermissionType GpoEditDeleteModifySecurity
|
||||
} #-WhatIf #| Format-Table *
|
||||
} -WhatIf
|
||||
@@ -1,11 +1,11 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Invoke-GPOZaurrPermission -Verbose -SearchBase 'OU=Computers,OU=Production,DC=ad,DC=evotec,DC=xyz' {
|
||||
Invoke-GPOZaurrPermission -Verbose -SearchBase 'OU=Production,DC=ad,DC=evotec,DC=pl' {
|
||||
Set-GPOOwner -Type Administrative
|
||||
#Set-GPOOwner -Principal 'EVOTEC\Enterprise Admins'
|
||||
#Set-GPOOwner -Principal 'Domain Admins'
|
||||
#Remove-GPOPermission -Type Administrative -IncludePermissionType GPOCustom
|
||||
Remove-GPOPermission -Type NotAdministrative, NotWellKnownAdministrative -IncludePermissionType GpoEdit, GpoEditDeleteModifySecurity
|
||||
#Add-GPOPermission -Type Administrative -IncludePermissionType GpoEditDeleteModifySecurity
|
||||
#Add-GPOPermission -Type WellKnownAdministrative -IncludePermissionType GpoEditDeleteModifySecurity
|
||||
} -WhatIf #| Format-Table *
|
||||
Add-GPOPermission -Type Administrative -IncludePermissionType GpoEditDeleteModifySecurity
|
||||
Add-GPOPermission -Type WellKnownAdministrative -IncludePermissionType GpoEditDeleteModifySecurity
|
||||
} -WhatIf
|
||||
@@ -1,10 +1,10 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Find broken GPOs
|
||||
Get-GPOZaurrBroken -Verbose -IncludeDomains 'ad.evotec.pl' | Format-Table
|
||||
Get-GPOZaurrBroken -Verbose | Format-Table # -IncludeDomains 'ad.evotec.pl' | Format-Table
|
||||
|
||||
# this allows you to process X amount of orphaned folders/files (good for testing)
|
||||
Remove-GPOZaurrBroken -Verbose -WhatIf #-IncludeDomains 'ad.evotec.pl' #-LimitProcessing 2
|
||||
Remove-GPOZaurrBroken -Verbose -WhatIf -Type AD -LimitProcessing 10 #-IncludeDomains 'ad.evotec.pl' #-LimitProcessing 2
|
||||
|
||||
# this runs for whole SYSVOL and checks things against GPOS
|
||||
Remove-GPOZaurrBroken -Verbose -IncludeDomains 'ad.evotec.xyz' -BackupPath $Env:UserProfile\Desktop\MyBackup1 -WhatIf
|
||||
Remove-GPOZaurrBroken -Verbose -IncludeDomains 'ad.evotec.xyz' -BackupPath $Env:UserProfile\Desktop\MyBackup1 -WhatIf -Type AD, SYSVOL
|
||||
@@ -8,7 +8,7 @@ Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
#Get-GPOZaurrLinkSummary -Report 'LinksSummary' -UnlimitedProperties | Format-Table *
|
||||
|
||||
$Report = Get-GPOZaurrLinkSummary #-UnlimitedProperties
|
||||
$Report | Format-Table *
|
||||
$Report.MultipleLinks | Format-Table *
|
||||
#$Report | Format-Table
|
||||
#$Report.MultipleLinks | Format-Table *
|
||||
$Report.OneLink | Format-Table *
|
||||
$Report.LinksSummary | Format-Table *
|
||||
#$Report.LinksSummary | Format-Table *
|
||||
@@ -1,4 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Output = Invoke-GPOZaurrContent -Verbose -OutputType HTML, Object -Open
|
||||
$Output = Invoke-GPOZaurrContent -Verbose -OutputType HTML, Object -Open -GPOPath "C:\Support\GitHub\GpoZaurr\Ignore\NewExamples" ##-Type LocalGroups
|
||||
$Output | Format-Table
|
||||
@@ -1,4 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Policies = Get-GPOZaurrFilesPolicyDefinition -Signature
|
||||
$Policies | Format-Table
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Report on empty folders
|
||||
Get-GPOZaurrFolders -FolderType Empty | Format-Table *
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Cleanup based on https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/manually-clearing-the-conflictanddeleted-folder-in-dfsr/ba-p/395711
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Invoke-GPOZaurrSupport -ComputerName 'ad1.ad.evotec.xyz' -UserName 'EVOTEC\przemyslaw.klys' -Type NativeHTML -ForceGPResult -Verbose
|
||||
|
||||
#Invoke-GPOZaurrSupport -ComputerName 'ad1.ad.evotec.xyz' -UserName 'EVOTEC\przemyslaw.klys' -Type HTML -Verbose -Path $PSScriptRoot\Reports\GPOSupport.html
|
||||
Invoke-GPOZaurrSupport -Type HTML -Verbose -Path $PSScriptRoot\Reports\GPOSupport.html -ComputerName ad1.ad.evotec.xyz
|
||||
return
|
||||
#$Support1 = Invoke-GPOZaurrSupport -ComputerName 'AD1' -UserName 'przemyslaw.klys' -Type Object
|
||||
#$Support = Invoke-GPOZaurrSupport -ComputerName 'AD1' -UserName 'EVOTEC\Administrator' -Type Object
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Extracts CSE from registry
|
||||
$AllRegistryExtensions = Find-CSExtension
|
||||
|
||||
@@ -6,5 +6,10 @@
|
||||
|
||||
# Get same output DN, CanonicalName, BlockInheritance (True/False) + Users/Computers + UsersCount/ComputerCount for those with Blocked Inhertiance
|
||||
# This is so you can have a list what machines are affected
|
||||
$Objects = Get-GPOZaurrInheritance -IncludeBlockedObjects -OnlyBlockedInheritance
|
||||
$ExcludedOU = @(
|
||||
# Works on OU/
|
||||
'ad.evotec.xyz/ITR02/Test'
|
||||
)
|
||||
|
||||
$Objects = Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance -Exclusions $ExcludedOU -IncludeGroupPoliciesForBlockedObjects
|
||||
$Objects | Format-Table
|
||||
@@ -1,4 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$FilesAll = Get-GPOZaurrNetLogon -SkipOwner -IncludeDomains 'ad.evotec.pl' #-OwnerOnly
|
||||
$FilesAll = Get-GPOZaurrNetLogon -IncludeDomains 'ad.evotec.xyz' -Verbose -OwnerOnly
|
||||
$FilesAll | Format-Table -a *
|
||||
@@ -1,7 +1,16 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Output = Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOOrphans -PassThru
|
||||
$Output
|
||||
#$Output = Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -PassThru -Type GPOConsistency, GPOList, GPODuplicates, GPOBroken, GPOOwners, NetLogonOwners, GPOPermissionsRead, GPOPermissionsAdministrative,GPOPermissionsUnknown
|
||||
|
||||
Write-Color -Text 'Output of nested report' -Color DarkYellow -LinesBefore 1 -LinesAfter 1
|
||||
$Output.GPOOrphans
|
||||
# Shows how to use exclusions (supported only in GPOBlockedInheritance)
|
||||
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOBlockedInheritance -Online -Exclusions @(
|
||||
'OU=Test,OU=ITR02,DC=ad,DC=evotec,DC=xyz'
|
||||
)
|
||||
|
||||
<#
|
||||
# Shows how to use exclusions for GPOList (different way)
|
||||
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOList -Online -Exclusions {
|
||||
Skip-GroupPolicy -Name 'de14_usr_std'
|
||||
Skip-GroupPolicy -Name 'ALL | Enable RDP' -DomaiName 'ad.evotec.xyz'
|
||||
}
|
||||
#>
|
||||
@@ -1,3 +1,3 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type NetLogonPermissions, GPOOrphans, GPOList, GPOConsistency, GPOOwners, GPODuplicates
|
||||
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOConsistency, GPOList, GPODuplicates, GPOBroken, GPOOwners, NetLogonOwners, GPOPermissionsRead, GPOPermissionsAdministrative, GPOPermissionsUnknown, GPOPermissions
|
||||
@@ -5,7 +5,7 @@ $Types = @(
|
||||
@{ Name = 'GPOConsistency'; Path = "$PSScriptRoot\Reports\GPOConsistency.html" }
|
||||
@{ Name = 'GPODuplicates'; Path = "$PSScriptRoot\Reports\GPODuplicates.html" }
|
||||
@{ Name = 'GPOList'; Path = "$PSScriptRoot\Reports\GPOList.html" }
|
||||
@{ Name = 'GPOOrphans'; Path = "$PSScriptRoot\Reports\GPOOrphans.html" }
|
||||
@{ Name = 'GPOBroken'; Path = "$PSScriptRoot\Reports\GPOBroken.html" }
|
||||
@{ Name = 'GPOPassword'; Path = "$PSScriptRoot\Reports\GPOPassword.html" }
|
||||
@{ Name = 'NetLogonPermissions'; Path = "$PSScriptRoot\Reports\NetLogonPermissions.html" }
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$GPOS = Get-GPOZaurr -GPOPath 'C:\Support\GitHub\GpoZaurr\Ignore\Empty' -ExcludeGroupPolicies {
|
||||
Skip-GroupPolicy -Name 'de14_usr_std'
|
||||
Skip-GroupPolicy -Name 'de14_usr_std' -DomaiName 'ad.evotec.xyz'
|
||||
}
|
||||
$GPOS | Format-Table -AutoSize *
|
||||
@@ -3,6 +3,6 @@
|
||||
# Optimize All
|
||||
Optimize-GPOZaurr -All -Verbose -IncludeDomains 'ad.evotec.pl' -LimitProcessing 1 {
|
||||
Skip-GroupPolicy -Name 'TEST | Empty GPO - AD.EVOTEC.PL CrossDomain GPO' -DomaiName 'ad.evotec.pl'
|
||||
}
|
||||
} -WhatIf
|
||||
# Optimize just one
|
||||
#Optimize-GPOZaurr -GPOName 'TEST | Empty GPO - AD.EVOTEC.PL CrossDomain GPO' -WhatIf -Verbose
|
||||
Optimize-GPOZaurr -GPOName 'TEST | Empty GPO - AD.EVOTEC.PL CrossDomain GPO' -WhatIf -Verbose
|
||||
@@ -0,0 +1,3 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Get-GPOZaurrPermissionAnalysis | Format-Table *
|
||||
@@ -0,0 +1,3 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Repair-GPOZaurrPermission -Verbose -WhatIf -Type Administrative -LimitProcessing 1
|
||||
@@ -0,0 +1,5 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
#Get-GPOZaurrBrokenLink -Verbose | Format-Table -AutoSize *
|
||||
|
||||
Get-GPOZaurrBrokenLink -Verbose -IncludeDomains ad.evotec.pl | Format-Table -AutoSize *
|
||||
@@ -0,0 +1,5 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
Repair-GPOZaurrBrokenLink -Verbose -LimitProcessing 1 #-WhatIf
|
||||
|
||||
#Repair-GPOZaurrBrokenLink -Verbose -IncludeDomains ad.evotec.pl -LimitProcessing 30 #-WhatIf
|
||||
+6
-6
@@ -4,11 +4,11 @@
|
||||
CmdletsToExport = @()
|
||||
CompanyName = 'Evotec'
|
||||
CompatiblePSEditions = @('Desktop')
|
||||
Copyright = '(c) 2011 - 2020 Przemyslaw Klys @ Evotec. All rights reserved.'
|
||||
Copyright = '(c) 2011 - 2021 Przemyslaw Klys @ Evotec. All rights reserved.'
|
||||
Description = 'Group Policy Eater is a PowerShell module that aims to gather information about Group Policies but also allows fixing issues that you may find in them.'
|
||||
FunctionsToExport = @('Add-GPOPermission', 'Add-GPOZaurrPermission', 'Backup-GPOZaurr', 'Clear-GPOZaurrSysvolDFSR', 'ConvertFrom-CSExtension', 'Find-CSExtension', 'Get-GPOZaurr', 'Get-GPOZaurrAD', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrBroken', 'Get-GPOZaurrDictionary', 'Get-GPOZaurrDuplicateObject', 'Get-GPOZaurrFiles', 'Get-GPOZaurrFilesPolicyDefinition', 'Get-GPOZaurrFolders', 'Get-GPOZaurrInheritance', 'Get-GPOZaurrLegacyFiles', 'Get-GPOZaurrLink', 'Get-GPOZaurrLinkSummary', 'Get-GPOZaurrNetLogon', 'Get-GPOZaurrOwner', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrPermissionConsistency', 'Get-GPOZaurrPermissionIssue', 'Get-GPOZaurrPermissionRoot', 'Get-GPOZaurrPermissionSummary', 'Get-GPOZaurrSysvolDFSR', 'Get-GPOZaurrWMI', 'Invoke-GPOZaurr', 'Invoke-GPOZaurrContent', 'Invoke-GPOZaurrPermission', 'Invoke-GPOZaurrSupport', 'New-GPOZaurrWMI', 'Optimize-GPOZaurr', 'Remove-GPOPermission', 'Remove-GPOZaurr', 'Remove-GPOZaurrBroken', 'Remove-GPOZaurrDuplicateObject', 'Remove-GPOZaurrFolders', 'Remove-GPOZaurrLegacyFiles', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Repair-GPOZaurrNetLogonOwner', 'Repair-GPOZaurrPermissionConsistency', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOOwner', 'Set-GPOZaurrOwner', 'Set-GPOZaurrStatus', 'Skip-GroupPolicy')
|
||||
FunctionsToExport = @('Add-GPOPermission', 'Add-GPOZaurrPermission', 'Backup-GPOZaurr', 'Clear-GPOZaurrSysvolDFSR', 'ConvertFrom-CSExtension', 'Find-CSExtension', 'Get-GPOZaurr', 'Get-GPOZaurrAD', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrBroken', 'Get-GPOZaurrBrokenLink', 'Get-GPOZaurrDictionary', 'Get-GPOZaurrDuplicateObject', 'Get-GPOZaurrFiles', 'Get-GPOZaurrFilesPolicyDefinition', 'Get-GPOZaurrFolders', 'Get-GPOZaurrInheritance', 'Get-GPOZaurrLegacyFiles', 'Get-GPOZaurrLink', 'Get-GPOZaurrLinkSummary', 'Get-GPOZaurrNetLogon', 'Get-GPOZaurrOwner', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrPermissionAnalysis', 'Get-GPOZaurrPermissionConsistency', 'Get-GPOZaurrPermissionIssue', 'Get-GPOZaurrPermissionRoot', 'Get-GPOZaurrPermissionSummary', 'Get-GPOZaurrSysvolDFSR', 'Get-GPOZaurrWMI', 'Invoke-GPOZaurr', 'Invoke-GPOZaurrContent', 'Invoke-GPOZaurrPermission', 'Invoke-GPOZaurrSupport', 'New-GPOZaurrWMI', 'Optimize-GPOZaurr', 'Remove-GPOPermission', 'Remove-GPOZaurr', 'Remove-GPOZaurrBroken', 'Remove-GPOZaurrDuplicateObject', 'Remove-GPOZaurrFolders', 'Remove-GPOZaurrLegacyFiles', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Repair-GPOZaurrBrokenLink', 'Repair-GPOZaurrNetLogonOwner', 'Repair-GPOZaurrPermission', 'Repair-GPOZaurrPermissionConsistency', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOOwner', 'Set-GPOZaurrOwner', 'Set-GPOZaurrStatus', 'Skip-GroupPolicy')
|
||||
GUID = 'f7d4c9e4-0298-4f51-ad77-e8e3febebbde'
|
||||
ModuleVersion = '0.0.96'
|
||||
ModuleVersion = '0.0.124'
|
||||
PowerShellVersion = '5.1'
|
||||
PrivateData = @{
|
||||
PSData = @{
|
||||
@@ -18,15 +18,15 @@
|
||||
}
|
||||
}
|
||||
RequiredModules = @(@{
|
||||
ModuleVersion = '0.0.189'
|
||||
ModuleVersion = '0.0.198'
|
||||
ModuleName = 'PSSharedGoods'
|
||||
Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
|
||||
}, @{
|
||||
ModuleVersion = '0.0.103'
|
||||
ModuleVersion = '0.0.124'
|
||||
ModuleName = 'ADEssentials'
|
||||
Guid = '9fc9fd61-7f11-4f4b-a527-084086f1905f'
|
||||
}, @{
|
||||
ModuleVersion = '0.0.122'
|
||||
ModuleVersion = '0.0.148'
|
||||
ModuleName = 'PSWriteHTML'
|
||||
Guid = 'a7bdf640-f5cb-4acf-9de0-365b322d245c'
|
||||
}, 'CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Security')
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
param(
|
||||
[System.Xml.XmlElement]$Content,
|
||||
[string] $ResultsType,
|
||||
[Microsoft.GroupPolicy.GPRsop] $ResultantSetPolicy,
|
||||
# [Microsoft.GroupPolicy.GPRsop] $ResultantSetPolicy,
|
||||
[string] $Splitter = [System.Environment]::NewLine
|
||||
)
|
||||
$GPOPrimary = [ordered] @{
|
||||
Summary = $null
|
||||
SummaryDetails = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
SummaryDownload = $null
|
||||
ResultantSetPolicy = $ResultantSetPolicy
|
||||
#ResultantSetPolicy = $ResultantSetPolicy
|
||||
|
||||
GroupPolicies = $null
|
||||
GroupPoliciesLinks = $null
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function ConvertTo-XMLDriveMapSettings {
|
||||
function ConvertTo-XMLDriveMapSettings {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
function ConvertTo-XMLFolderRedirection {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[switch] $SingleObject
|
||||
)
|
||||
if ($SingleObject) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Count = 0
|
||||
Settings = $null
|
||||
}
|
||||
[Array] $CreateGPO['Settings'] = foreach ($Folder in $GPO.DataSet) {
|
||||
foreach ($Location in $Folder.Location) {
|
||||
[PSCustomObject] @{
|
||||
DestinationPath = $Location.DestinationPath
|
||||
SecuritySID = $Location.SecurityGroup.SID.'#text'
|
||||
SecurityName = $Location.SecurityGroup.Name.'#text'
|
||||
GrantExclusiveRights = if ($Folder.GrantExclusiveRights -eq 'true') { $true } else { $false }
|
||||
MoveContents = if ($Folder.MoveContents -eq 'true') { $true } else { $false }
|
||||
FollowParent = if ($Folder.FollowParent -eq 'true') { $true } else { $false }
|
||||
ApplyToDownLevel = if ($Folder.ApplyToDownLevel -eq 'true') { $true } else { $false }
|
||||
DoNotCare = if ($Folder.DoNotCare -eq 'true') { $true } else { $false }
|
||||
RedirectToLocal = if ($Folder.RedirectToLocal -eq 'true') { $true } else { $false }
|
||||
PolicyRemovalBehavior = $Folder.PolicyRemovalBehavior # : LeaveContents
|
||||
ConfigurationControl = if ($Folder.ConfigurationControl -eq 'GP') { 'Group Policy' } else { $Folder.ConfigurationControl } # : GP
|
||||
PrimaryComputerEvaluation = $Folder.PrimaryComputerEvaluation # : PrimaryComputerPolicyDisabled
|
||||
}
|
||||
}
|
||||
}
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
foreach ($Folder in $GPO.DataSet) {
|
||||
foreach ($Location in $Folder.Location) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
Id = $Folder.Id
|
||||
DestinationPath = $Location.DestinationPath
|
||||
SecuritySID = $Location.SecurityGroup.SID.'#text'
|
||||
SecurityName = $Location.SecurityGroup.Name.'#text'
|
||||
GrantExclusiveRights = if ($Folder.GrantExclusiveRights -eq 'true') { $true } else { $false }
|
||||
MoveContents = if ($Folder.MoveContents -eq 'true') { $true } else { $false }
|
||||
FollowParent = if ($Folder.FollowParent -eq 'true') { $true } else { $false }
|
||||
ApplyToDownLevel = if ($Folder.ApplyToDownLevel -eq 'true') { $true } else { $false }
|
||||
DoNotCare = if ($Folder.DoNotCare -eq 'true') { $true } else { $false }
|
||||
RedirectToLocal = if ($Folder.RedirectToLocal -eq 'true') { $true } else { $false }
|
||||
PolicyRemovalBehavior = $Folder.PolicyRemovalBehavior # : LeaveContents
|
||||
ConfigurationControl = if ($Folder.ConfigurationControl -eq 'GP') { 'Group Policy' } else { $Folder.ConfigurationControl } # : GP
|
||||
PrimaryComputerEvaluation = $Folder.PrimaryComputerEvaluation # : PrimaryComputerPolicyDisabled
|
||||
Linked = $GPO.Linked
|
||||
LinksCount = $GPO.LinksCount
|
||||
Links = $GPO.Links
|
||||
}
|
||||
[PSCustomObject] $CreateGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
function ConvertTo-XMLGenericPolicy {
|
||||
function ConvertTo-XMLGenericPolicy {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function ConvertTo-XMLGenericPublicKey {
|
||||
function ConvertTo-XMLGenericPublicKey {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function ConvertTo-XMLGenericSecuritySettings {
|
||||
function ConvertTo-XMLGenericSecuritySettings {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function ConvertTo-XMLLocalGroups {
|
||||
function ConvertTo-XMLLocalGroups {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function ConvertTo-XMLPrinter {
|
||||
function ConvertTo-XMLPrinter {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function ConvertTo-XMLPrinterInternal {
|
||||
function ConvertTo-XMLPrinterInternal {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function ConvertTo-XMLRegistryAutologonOnReport {
|
||||
function ConvertTo-XMLRegistryAutologonOnReport {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function ConvertTo-XMLTaskScheduler {
|
||||
function ConvertTo-XMLTaskScheduler {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
function ConvertTo-XMLWindowsFirewall {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[switch] $SingleObject
|
||||
)
|
||||
if ($SingleObject) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Count = 0
|
||||
Settings = $null
|
||||
}
|
||||
[Array] $CreateGPO['Settings'] = foreach ($Policy in $GPO.DataSet) {
|
||||
[PSCustomObject] @{
|
||||
Name = $Policy.LocalName
|
||||
Version = $Policy.PolicyVersion.Value
|
||||
}
|
||||
}
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
foreach ($Policy in $GPO.DataSet) {
|
||||
[PSCustomObject]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
Name = $Policy.LocalName
|
||||
Version = $Policy.PolicyVersion.Value
|
||||
Linked = $GPO.Linked
|
||||
LinksCount = $GPO.LinksCount
|
||||
Links = $GPO.Links
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
function ConvertTo-XMLWindowsFirewallConnectionSecurityAuthentiation {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[switch] $SingleObject
|
||||
)
|
||||
if ($SingleObject) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Count = 0
|
||||
Settings = $null
|
||||
}
|
||||
[Array] $CreateGPO['Settings'] = foreach ($Connection in $GPO.DataSet) {
|
||||
[PSCustomObject] @{
|
||||
Name = $Connection.LocalName
|
||||
Version = $Connection.Version
|
||||
ConnectionGUID = $Connection.GUID
|
||||
Method = $Connection.AuthenticationSuites.Method #: MachineCert
|
||||
CAName = $Connection.AuthenticationSuites.CAName #: DC = xyz, DC = evotec, DC = ad, CN = ad-ADCS-CA
|
||||
CertAccountMapping = if ($Connection.AuthenticationSuites.CertAccountMapping -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.CertAccountMapping -eq 'false') { $false } else { $Connection.AuthenticationSuites.CertAccountMapping }
|
||||
ExcludeCAName = if ($Connection.AuthenticationSuites.ExcludeCAName -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.ExcludeCAName -eq 'false') { $false } else { $Connection.AuthenticationSuites.ExcludeCAName }
|
||||
HealthCert = if ($Connection.AuthenticationSuites.HealthCert -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.HealthCert -eq 'false') { $false } else { $Connection.AuthenticationSuites.HealthCert }
|
||||
}
|
||||
}
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
foreach ($Connection in $GPO.DataSet) {
|
||||
[PSCustomObject]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
Name = $Connection.LocalName
|
||||
Version = $Connection.Version
|
||||
ConnectionGUID = $Connection.GUID
|
||||
Method = $Connection.AuthenticationSuites.Method #: MachineCert
|
||||
CAName = $Connection.AuthenticationSuites.CAName #: DC = xyz, DC = evotec, DC = ad, CN = ad-ADCS-CA
|
||||
CertAccountMapping = if ($Connection.AuthenticationSuites.CertAccountMapping -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.CertAccountMapping -eq 'false') { $false } else { $Connection.AuthenticationSuites.CertAccountMapping }
|
||||
ExcludeCAName = if ($Connection.AuthenticationSuites.ExcludeCAName -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.ExcludeCAName -eq 'false') { $false } else { $Connection.AuthenticationSuites.ExcludeCAName }
|
||||
HealthCert = if ($Connection.AuthenticationSuites.HealthCert -eq 'true') { $true } elseif ($Connection.AuthenticationSuites.HealthCert -eq 'false') { $false } else { $Connection.AuthenticationSuites.HealthCert }
|
||||
Linked = $GPO.Linked
|
||||
LinksCount = $GPO.LinksCount
|
||||
Links = $GPO.Links
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
function ConvertTo-XMLWindowsFirewallProfile {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[switch] $SingleObject
|
||||
)
|
||||
if ($SingleObject) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Count = 0
|
||||
Settings = $null
|
||||
}
|
||||
[Array] $CreateGPO['Settings'] = foreach ($Profile in $GPO.DataSet) {
|
||||
[PSCustomObject] @{
|
||||
Profile = $Profile.LocalName
|
||||
EnableFirewall = if ($Profile.EnableFirewall.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
AllowLocalIPsecPolicyMerge = if ($Profile.AllowLocalIPsecPolicyMerge.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
AllowLocalPolicyMerge = if ($Profile.AllowLocalPolicyMerge.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
DefaultInboundAction = if ($Profile.DefaultInboundAction.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
DefaultOutboundAction = if ($Profile.DefaultOutboundAction.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
DisableNotifications = if ($Profile.DisableNotifications.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
DisableUnicastResponsesToMulticastBroadcast = if ($Profile.DisableUnicastResponsesToMulticastBroadcast.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
DoNotAllowExceptions = if ($Profile.DoNotAllowExceptions.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
LogFilePath = if ($Profile.LogFilePath.Value) { $Profile.LogFilePath.Value } else { 'Not configured' }
|
||||
LogDroppedPackets = if ($Profile.LogDroppedPackets.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
LogFileSize = if ($Profile.LogFileSize.Value) { $Profile.LogFileSize.Value } else { 'Not configured' }
|
||||
LogSuccessfulConnections = if ($Profile.LogSuccessfulConnections.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
}
|
||||
}
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
foreach ($Profile in $GPO.DataSet) {
|
||||
[PSCustomObject]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
Profile = $Profile.LocalName
|
||||
EnableFirewall = if ($Profile.EnableFirewall.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
AllowLocalIPsecPolicyMerge = if ($Profile.AllowLocalIPsecPolicyMerge.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
AllowLocalPolicyMerge = if ($Profile.AllowLocalPolicyMerge.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
DefaultInboundAction = if ($Profile.DefaultInboundAction.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
DefaultOutboundAction = if ($Profile.DefaultOutboundAction.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
DisableNotifications = if ($Profile.DisableNotifications.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
DisableUnicastResponsesToMulticastBroadcast = if ($Profile.DisableUnicastResponsesToMulticastBroadcast.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
DoNotAllowExceptions = if ($Profile.DoNotAllowExceptions.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
LogFilePath = if ($Profile.LogFilePath.Value) { $Profile.LogFilePath.Value } else { 'Not configured' }
|
||||
LogDroppedPackets = if ($Profile.LogDroppedPackets.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
LogFileSize = if ($Profile.LogFileSize.Value) { $Profile.LogFileSize.Value } else { 'Not configured' }
|
||||
LogSuccessfulConnections = if ($Profile.LogSuccessfulConnections.Value -eq 'true') { 'Yes' } elseif ($Profile.EnableFirewall.Value -eq 'false') { 'No' } else { 'Not configured' }
|
||||
Linked = $GPO.Linked
|
||||
LinksCount = $GPO.LinksCount
|
||||
Links = $GPO.Links
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
function ConvertTo-XMLWindowsFirewallRules {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[switch] $SingleObject
|
||||
)
|
||||
if ($SingleObject) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Count = 0
|
||||
Settings = $null
|
||||
}
|
||||
[Array] $CreateGPO['Settings'] = foreach ($Rule in $GPO.DataSet) {
|
||||
[PSCustomObject] @{
|
||||
Version = $Rule.Version
|
||||
Type = if ($Rule.Dir -eq 'In') { 'Inbound' } elseif ($Rule.Dir -eq 'Out') { 'Outbound' } else { $Rule.Dir }
|
||||
Name = $Rule.Name
|
||||
Action = $Rule.Action
|
||||
Enabled = if ($Rule.Active -eq 'true') { $true } else { $false }
|
||||
Profile = $Rule.Profile
|
||||
Svc = $Rule.Svc
|
||||
LocalAddressIPv4 = $Rule.LA4
|
||||
LocalAddressIPv6 = $Rule.LA6
|
||||
RemoteAddressIPV4 = $Rule.RA4
|
||||
RemoteAddressIPV6 = $Rule.RA6
|
||||
LocalPort = $Rule.LPort
|
||||
RemotePort = $Rule.RPort
|
||||
Description = $Rule.Desc
|
||||
EmbedCtxt = $Rule.EmbedCtxt
|
||||
Edge = $Rule.Edge
|
||||
IFType = $Rule.IFType
|
||||
Security = $Rule.Security
|
||||
App = $Rule.App
|
||||
Protocol = $Rule.Protocol
|
||||
RMAuth = $Rule.RMAuth
|
||||
RUAuth = $Rule.RUAuth
|
||||
ICMP4 = $Rule.ICMP4
|
||||
LocalName = $Rule.LocalName
|
||||
|
||||
}
|
||||
}
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
foreach ($Rule in $GPO.DataSet) {
|
||||
[PSCustomObject]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
Version = $Rule.Version
|
||||
Type = if ($Rule.Dir -eq 'In') { 'Inbound' } elseif ($Rule.Dir -eq 'Out') { 'Outbound' } else { $Rule.Dir }
|
||||
Name = $Rule.Name
|
||||
Action = $Rule.Action
|
||||
Enabled = if ($Rule.Active -eq 'true') { $true } else { $false }
|
||||
Profile = $Rule.Profile
|
||||
Svc = $Rule.Svc
|
||||
LocalAddressIPv4 = $Rule.LA4
|
||||
LocalAddressIPv6 = $Rule.LA6
|
||||
RemoteAddressIPV4 = $Rule.RA4
|
||||
RemoteAddressIPV6 = $Rule.RA6
|
||||
LocalPort = $Rule.LPort
|
||||
RemotePort = $Rule.RPort
|
||||
Description = $Rule.Desc
|
||||
EmbedCtxt = $Rule.EmbedCtxt
|
||||
Edge = $Rule.Edge
|
||||
IFType = $Rule.IFType
|
||||
Security = $Rule.Security
|
||||
App = $Rule.App
|
||||
Protocol = $Rule.Protocol
|
||||
RMAuth = $Rule.RMAuth
|
||||
RUAuth = $Rule.RUAuth
|
||||
ICMP4 = $Rule.ICMP4
|
||||
LocalName = $Rule.LocalName
|
||||
Linked = $GPO.Linked
|
||||
LinksCount = $GPO.LinksCount
|
||||
Links = $GPO.Links
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<#
|
||||
Version : 2.30
|
||||
Action : Allow
|
||||
Name : @%SystemRoot%\system32\firewallapi.dll,-37303
|
||||
Dir : In
|
||||
App : %SystemRoot%\system32\svchost.exe
|
||||
Svc : dnscache
|
||||
Profile : Public
|
||||
RA4 : LocalSubnet
|
||||
RA6 : LocalSubnet
|
||||
LPort : 5353
|
||||
Protocol : 17
|
||||
Desc : @%SystemRoot%\system32\firewallapi.dll,-37304
|
||||
Active : true
|
||||
EmbedCtxt : @%SystemRoot%\system32\firewallapi.dll,-37302
|
||||
|
||||
|
||||
Version : 2.30
|
||||
Action : Allow
|
||||
Name : TEST APP
|
||||
Dir : In
|
||||
App : C:\Test\exe.exe
|
||||
Active : true
|
||||
|
||||
Version : 2.30
|
||||
Action : Block
|
||||
Name : Blo
|
||||
Dir : Out
|
||||
App : dfdff
|
||||
Active : true
|
||||
|
||||
Version : 2.30
|
||||
Action : Block
|
||||
Name : @FirewallAPI.dll,-36012
|
||||
Dir : Out
|
||||
App : %SystemRoot%\system32\svchost.exe
|
||||
Svc : Qwave
|
||||
Profile : {Private, Public}
|
||||
RPort : 2177
|
||||
Protocol : 17
|
||||
Desc : @FirewallAPI.dll,-36013
|
||||
Active : true
|
||||
EmbedCtxt : @FirewallAPI.dll,-36001
|
||||
#>
|
||||
@@ -0,0 +1,76 @@
|
||||
function ConvertTo-XMLWindowsFirewallSecurityRules {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
[switch] $SingleObject
|
||||
)
|
||||
if ($SingleObject) {
|
||||
$CreateGPO = [ordered]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
#GpoCategory = $GPOEntry.GpoCategory
|
||||
#GpoSettings = $GPOEntry.GpoSettings
|
||||
Count = 0
|
||||
Settings = $null
|
||||
}
|
||||
[Array] $CreateGPO['Settings'] = foreach ($Rule in $GPO.DataSet) {
|
||||
[PSCustomObject] @{
|
||||
Version = $Rule.Version
|
||||
Name = $Rule.Name
|
||||
Action = $Rule.Action
|
||||
Enabled = if ($Rule.Active -eq 'true') { $true } else { $false }
|
||||
Auth1Set = $Rule.Auth1Set
|
||||
Auth2Set = $Rule.Auth2Set
|
||||
Crypto2Set = $Rule.Crypto2Set
|
||||
Description = $Rule.Desc
|
||||
}
|
||||
}
|
||||
$CreateGPO['Count'] = $CreateGPO['Settings'].Count
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
$CreateGPO['LinksCount'] = $GPO.LinksCount
|
||||
$CreateGPO['Links'] = $GPO.Links
|
||||
[PSCustomObject] $CreateGPO
|
||||
} else {
|
||||
foreach ($Rule in $GPO.DataSet) {
|
||||
[PSCustomObject]@{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.DomainName
|
||||
GUID = $GPO.GUID
|
||||
GpoType = $GPO.GpoType
|
||||
Version = $Rule.Version
|
||||
Name = $Rule.Name
|
||||
Action = $Rule.Action
|
||||
Enabled = if ($Rule.Active -eq 'true') { $true } else { $false }
|
||||
Auth1Set = $Rule.Auth1Set
|
||||
Auth2Set = $Rule.Auth2Set
|
||||
Crypto2Set = $Rule.Crypto2Set
|
||||
Description = $Rule.Desc
|
||||
Linked = $GPO.Linked
|
||||
LinksCount = $GPO.LinksCount
|
||||
Links = $GPO.Links
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
Version : 2.30
|
||||
Action : Boundary
|
||||
Name : TeST Aut
|
||||
Auth1Set : {E5A5D32A-4BCE-4e4d-B07F-4AB1BA7E5FE3}
|
||||
Auth2Set : {E5A5D32A-4BCE-4e4d-B07F-4AB1BA7E5FE4}
|
||||
Crypto2Set : {E5A5D32A-4BCE-4e4d-B07F-4AB1BA7E5FE2}
|
||||
Desc :
|
||||
Active : true
|
||||
|
||||
Version : 2.30
|
||||
Action : Boundary
|
||||
Name : CA TEST
|
||||
Auth1Set : {0E3A2DDC-F31B-42B5-BEAC-890752F9C0BB}
|
||||
Auth2Set : EmptySet
|
||||
Crypto2Set : {E5A5D32A-4BCE-4e4d-B07F-4AB1BA7E5FE2}
|
||||
Desc :
|
||||
Active : true
|
||||
#>
|
||||
@@ -1,4 +1,4 @@
|
||||
function Get-GPOCategories {
|
||||
function Get-GPOCategories {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPO,
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
function Get-GPOPrivInheritance {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[parameter(ParameterSetName = 'ADObject', ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
|
||||
[System.Collections.IDictionary] $CacheReturnedGPOs,
|
||||
[System.Collections.IDictionary] $ForestInformation,
|
||||
[string] $Domain,
|
||||
[switch] $SkipDomainRoot,
|
||||
[switch] $SkipDomainControllers
|
||||
)
|
||||
foreach ($Object in $ADObject) {
|
||||
if ($SkipDomainRoot) {
|
||||
if ($Object.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']) {
|
||||
# other skips Domain Root
|
||||
continue
|
||||
}
|
||||
}
|
||||
if ($SkipDomainControllers) {
|
||||
if ($Object.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']) {
|
||||
# other skips Domain Controllers
|
||||
continue
|
||||
}
|
||||
}
|
||||
$Inheritance = Get-GPInheritance -Target $Object.DistinguishedName
|
||||
foreach ($Link in $Inheritance.GpoLinks) {
|
||||
[PSCustomObject] @{
|
||||
DisplayName = $Link.DisplayName
|
||||
DomainName = $Domain
|
||||
GUID = $Link.GPOID
|
||||
Enabled = $Link.Enabled
|
||||
Enforced = $Link.Enforced
|
||||
Order = $Link.Order
|
||||
Target = $Object.DistinguishedName
|
||||
TargetCanonical = $Object.CanonicalName
|
||||
TargetObjectClass = $Object.objectClass
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
function Get-GPOPrivInheritanceLoop {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
|
||||
[System.Collections.IDictionary] $CacheReturnedGPOs,
|
||||
[System.Collections.IDictionary] $ForestInformation,
|
||||
[validateset('Root', 'DomainControllers', 'OrganizationalUnit')][string[]] $Linked,
|
||||
[string] $SearchBase,
|
||||
[Microsoft.ActiveDirectory.Management.ADSearchScope] $SearchScope,
|
||||
[string] $Filter
|
||||
)
|
||||
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']
|
||||
$Splat['Filter'] = "(objectClass -eq 'organizationalUnit')"
|
||||
$Splat['SearchBase'] = $SearchBase
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
Get-GPOPrivInheritance -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation
|
||||
}
|
||||
if ($Linked -contains 'Root') {
|
||||
$SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
|
||||
$Splat['Filter'] = "objectClass -eq 'domainDNS'"
|
||||
$Splat['SearchBase'] = $SearchBase
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
Get-GPOPrivInheritance -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation
|
||||
}
|
||||
if ($Linked -contains 'Site') {
|
||||
# Sites are defined only in primary domain
|
||||
# Sites are not supported by Get-GPInheritance
|
||||
}
|
||||
if ($Linked -contains 'OrganizationalUnit') {
|
||||
$SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
|
||||
$Splat['Filter'] = "(objectClass -eq 'organizationalUnit')"
|
||||
$Splat['SearchBase'] = $SearchBase
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
Get-GPOPrivInheritance -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -SkipDomainRoot -SkipDomainControllers
|
||||
}
|
||||
}
|
||||
} elseif ($Filter) {
|
||||
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']
|
||||
$SearchBaseDC = ConvertFrom-DistinguishedName -DistinguishedName $SearchBase -ToDC
|
||||
if ($SearchBaseDC -ne $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
|
||||
}
|
||||
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
Get-GPOPrivInheritance -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Get-GPOPrivInheritance -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObject -Domain '' -ForestInformation $ForestInformation
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
function Get-GPOPrivLink {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[parameter(ParameterSetName = 'ADObject', ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
|
||||
[System.Collections.IDictionary] $CacheReturnedGPOs,
|
||||
[System.Collections.IDictionary] $ForestInformation,
|
||||
[string] $Domain,
|
||||
[switch] $SkipDomainRoot,
|
||||
[switch] $SkipDomainControllers,
|
||||
[switch] $AsHashTable,
|
||||
[switch] $SkipDuplicates
|
||||
)
|
||||
foreach ($Object in $ADObject) {
|
||||
if ($SkipDomainRoot) {
|
||||
if ($Object.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']) {
|
||||
# other skips Domain Root
|
||||
continue
|
||||
}
|
||||
}
|
||||
if ($SkipDomainControllers) {
|
||||
if ($Object.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']) {
|
||||
# other skips Domain Controllers
|
||||
continue
|
||||
}
|
||||
}
|
||||
$OutputGPOs = Get-PrivGPOZaurrLink -Object $Object -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
||||
foreach ($OutputGPO in $OutputGPOs) {
|
||||
if (-not $SkipDuplicates) {
|
||||
$OutputGPO
|
||||
} else {
|
||||
$UniqueGuid = -join ($OutputGPO.DomainName, $OutputGPO.Guid)
|
||||
if (-not $CacheReturnedGPOs[$UniqueGuid]) {
|
||||
$CacheReturnedGPOs[$UniqueGuid] = $OutputGPO
|
||||
$OutputGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
function Get-GPOZaurrLinkInheritance {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Short description
|
||||
|
||||
.DESCRIPTION
|
||||
Long description
|
||||
|
||||
.PARAMETER ADObject
|
||||
Parameter description
|
||||
|
||||
.PARAMETER Filter
|
||||
Parameter description
|
||||
|
||||
.PARAMETER SearchBase
|
||||
Parameter description
|
||||
|
||||
.PARAMETER SearchScope
|
||||
Parameter description
|
||||
|
||||
.PARAMETER Linked
|
||||
Parameter description
|
||||
|
||||
.PARAMETER Limited
|
||||
Parameter description
|
||||
|
||||
.PARAMETER SkipDuplicates
|
||||
Parameter description
|
||||
|
||||
.PARAMETER GPOCache
|
||||
Parameter description
|
||||
|
||||
.PARAMETER Forest
|
||||
Parameter description
|
||||
|
||||
.PARAMETER ExcludeDomains
|
||||
Parameter description
|
||||
|
||||
.PARAMETER IncludeDomains
|
||||
Parameter description
|
||||
|
||||
.PARAMETER ExtendedForestInformation
|
||||
Parameter description
|
||||
|
||||
.PARAMETER AsHashTable
|
||||
Parameter description
|
||||
|
||||
.PARAMETER Summary
|
||||
Parameter description
|
||||
|
||||
.EXAMPLE
|
||||
$Output = Get-GPOZaurrLinkInheritance -Summary
|
||||
$Output | Format-Table
|
||||
|
||||
$Output[5]
|
||||
|
||||
$Output[5].Links | Format-Table
|
||||
$Output[5].LinksObjects | Format-Table
|
||||
|
||||
.NOTES
|
||||
This is based on Get-GPInheritance which isn't ideal and doesn't support sites. Get-GPOZaurrLink is better. Leaving in case I need it later on for private use only.
|
||||
#>
|
||||
[cmdletbinding(DefaultParameterSetName = 'All')]
|
||||
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', 'OrganizationalUnit')][string[]] $Linked,
|
||||
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[switch] $Limited,
|
||||
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[switch] $SkipDuplicates,
|
||||
|
||||
[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,
|
||||
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[switch] $AsHashTable,
|
||||
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[switch] $Summary
|
||||
)
|
||||
Begin {
|
||||
$CacheReturnedGPOs = [ordered] @{}
|
||||
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
if (-not $GPOCache -and -not $Limited) {
|
||||
$GPOCache = @{ }
|
||||
# While initially we used $ForestInformation.Domains but the thing is GPOs can be linked to other domains so we need to get them all so we can use cache of it later on even if we're processing just one domain
|
||||
# That's why we use $ForestInformation.Forest.Domains instead
|
||||
foreach ($Domain in $ForestInformation.Forest.Domains) {
|
||||
$QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
|
||||
Get-GPO -All -DomainName $Domain -Server $QueryServer | ForEach-Object {
|
||||
$GPOCache["$Domain$($_.ID.Guid)"] = $_
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Process {
|
||||
if (-not $Filter -and -not $Linked) {
|
||||
# We choose ALL, except SITE which is not supported gor Get-GPInheritance
|
||||
# that's why it's better to use Get-GPOZaurrLink
|
||||
#$Linked = 'Root', 'DomainControllers', 'Site', 'OrganizationalUnit'
|
||||
}
|
||||
$getGPOPrivInheritanceLoopSplat = @{
|
||||
Linked = $Linked
|
||||
ForestInformation = $ForestInformation
|
||||
CacheReturnedGPOs = $CacheReturnedGPOs
|
||||
SearchScope = $SearchScope
|
||||
SearchBase = $SearchBase
|
||||
ADObject = $ADObject
|
||||
Filter = $Filter
|
||||
}
|
||||
Remove-EmptyValue -Hashtable $getGPOPrivInheritanceLoopSplat -Recursive
|
||||
|
||||
# we need to use nested functions to support pipeline output and as hashtable and reporting that returns single value
|
||||
if ($AsHashTable -or $Summary) {
|
||||
$HashTable = [ordered] @{}
|
||||
$SummaryHashtable = [ordered] @{}
|
||||
$Links = Get-GPOPrivInheritanceLoop @getGPOPrivInheritanceLoopSplat
|
||||
foreach ($Link in $Links) {
|
||||
$Key = -join ($Link.DomainName, $Link.GUID)
|
||||
if (-not $HashTable[$Key]) {
|
||||
$HashTable[$Key] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
}
|
||||
$HashTable[$Key].Add($Link)
|
||||
}
|
||||
foreach ($Key in $HashTable.Keys) {
|
||||
[Array] $Link = $HashTable[$Key]
|
||||
$EnabledLinks = $Link.Enabled.Where( { $_ -eq $true }, 'split')
|
||||
if ($EnabledLinks[0].Count -gt 0) {
|
||||
$IsLinked = $true
|
||||
} else {
|
||||
$IsLinked = $false
|
||||
}
|
||||
$SummaryLink = [PSCustomObject] @{
|
||||
DisplayName = $Link[0].DisplayName
|
||||
DomainName = $Link[0].DomainName
|
||||
GUID = $Link[0].GUID
|
||||
Linked = $IsLinked
|
||||
LinksCount = $Link.Count
|
||||
LinksEnabledCount = $EnabledLinks[0].Count
|
||||
LinksDisabledCount = $EnabledLinks[1].Count
|
||||
Links = $Link.Target
|
||||
LinksObjects = $Link
|
||||
}
|
||||
$SummaryHashtable[$Key] = $SummaryLink
|
||||
}
|
||||
if ($AsHashTable -and $Summary) {
|
||||
$SummaryHashtable
|
||||
} elseif ($AsHashTable) {
|
||||
$HashTable
|
||||
} elseif ($Summary) {
|
||||
$SummaryHashtable.Values
|
||||
}
|
||||
} else {
|
||||
Get-GPOPrivInheritanceLoop @getGPOPrivInheritanceLoopSplat
|
||||
}
|
||||
}
|
||||
End {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
function Get-GPOZaurrLinkLoop {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
|
||||
[System.Collections.IDictionary] $CacheReturnedGPOs,
|
||||
[System.Collections.IDictionary] $ForestInformation,
|
||||
[validateset('All', 'Root', 'DomainControllers', 'Site', 'OrganizationalUnit')][string[]] $Linked,
|
||||
[string] $SearchBase,
|
||||
[Microsoft.ActiveDirectory.Management.ADSearchScope] $SearchScope,
|
||||
[string] $Filter,
|
||||
[switch] $SkipDuplicates,
|
||||
[string[]] $Site
|
||||
)
|
||||
if (-not $ADObject) {
|
||||
if ($Site) {
|
||||
foreach ($S in $Site) {
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for site $Site"
|
||||
# Sites are defined only in primary domain
|
||||
if ($ForestInformation['DomainsExtended'][$Domain]['DNSRoot'] -eq $ForestInformation['DomainsExtended'][$Domain]['Forest']) {
|
||||
$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]
|
||||
}
|
||||
$Splat['Filter'] = "(objectClass -eq 'site') -and (name -eq '$S')"
|
||||
$Splat['SearchBase'] = -join ("CN=Configuration,", $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName'])
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
if ($ADObjectGPO) {
|
||||
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif ($SearchBase -or $SearchScope -or $Filter) {
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
if (-not $Filter) {
|
||||
$Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')"
|
||||
}
|
||||
$Splat = @{
|
||||
Filter = $Filter
|
||||
Properties = 'distinguishedName', 'gplink', 'CanonicalName'
|
||||
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
|
||||
}
|
||||
if ($PSBoundParameters.ContainsKey('SearchBase')) {
|
||||
$DomainDistinguishedName = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
|
||||
$SearchBaseDC = ConvertFrom-DistinguishedName -DistinguishedName $SearchBase -ToDC
|
||||
if ($SearchBaseDC -ne $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
|
||||
}
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
if ($ADObjectGPO) {
|
||||
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
|
||||
}
|
||||
}
|
||||
} elseif (-not $Filter) {
|
||||
# if not linked, we force it to All
|
||||
if (-not $Linked) {
|
||||
$Linked = 'All'
|
||||
}
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for domain $Domain"
|
||||
$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 'Root' -or $Linked -contains 'All') {
|
||||
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for domain $Domain at ROOT level"
|
||||
$Splat['Filter'] = "objectClass -eq 'domainDNS'"
|
||||
$Splat['SearchBase'] = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
if ($ADObjectGPO) {
|
||||
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
|
||||
}
|
||||
}
|
||||
if ($Linked -contains 'Site' -or $Linked -contains 'All') {
|
||||
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for domain $Domain at SITE level"
|
||||
# Sites are defined only in primary domain
|
||||
if ($ForestInformation['DomainsExtended'][$Domain]['DNSRoot'] -eq $ForestInformation['DomainsExtended'][$Domain]['Forest']) {
|
||||
$Splat['Filter'] = "(objectClass -eq 'site')"
|
||||
$Splat['SearchBase'] = -join ("CN=Configuration,", $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName'])
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
if ($ADObjectGPO) {
|
||||
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Linked -contains 'DomainControllers' -or $Linked -contains 'All') {
|
||||
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for domain $Domain at DC level"
|
||||
$Splat['Filter'] = "(objectClass -eq 'organizationalUnit')"
|
||||
$Splat['SearchBase'] = $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
if ($ADObjectGPO) {
|
||||
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
|
||||
}
|
||||
}
|
||||
if ($Linked -contains 'OrganizationalUnit' -or $Linked -contains 'All') {
|
||||
Write-Verbose "Get-GPOZaurrLink - Getting GPO links for domain $Domain at OU level"
|
||||
$Splat['Filter'] = "(objectClass -eq 'organizationalUnit')"
|
||||
$Splat['SearchBase'] = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
if ($ADObjectGPO) {
|
||||
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -SkipDomainRoot -SkipDomainControllers -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<#
|
||||
elseif ($Filter) {
|
||||
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']
|
||||
$SearchBaseDC = ConvertFrom-DistinguishedName -DistinguishedName $SearchBase -ToDC
|
||||
if ($SearchBaseDC -ne $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
|
||||
}
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
if ($ADObjectGPO) {
|
||||
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObjectGPO -Domain $Domain -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
|
||||
}
|
||||
}
|
||||
}
|
||||
#>
|
||||
} else {
|
||||
Get-GPOPrivLink -CacheReturnedGPOs $CacheReturnedGPOs -ADObject $ADObject -Domain '' -ForestInformation $ForestInformation -AsHashTable:$AsHashTable -SkipDuplicates:$SkipDuplicates
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,10 @@
|
||||
if (-not $ADAdministrativeGroups) {
|
||||
$ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
}
|
||||
$AdministrativeExists = @{
|
||||
$AdministrativeExists = [ordered] @{
|
||||
DisplayName = $GPOPermissions[0].DisplayName
|
||||
DomainName = $GPOPermissions[0].DomainName
|
||||
GUID = $GPOPermissions[0].GUID
|
||||
Skip = $false
|
||||
DomainAdmins = $false
|
||||
EnterpriseAdmins = $false
|
||||
@@ -55,5 +58,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
$AdministrativeExists
|
||||
[PSCustomObject] $AdministrativeExists
|
||||
}
|
||||
@@ -6,69 +6,71 @@
|
||||
[System.Collections.IDictionary] $GPOCache
|
||||
)
|
||||
if ($Object.GpLink -and $Object.GpLink.Trim() -ne '') {
|
||||
#$Object.GpLink -split { $_ -eq '[' -or $_ -eq ']' } -replace ';0' -replace 'LDAP://'
|
||||
$Object.GpLink -split '\[LDAP://' -split ';' | ForEach-Object -Process {
|
||||
#Write-Verbose $_
|
||||
if ($_.Length -gt 10) {
|
||||
$DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDomainCN
|
||||
$Output = [ordered] @{
|
||||
DistinguishedName = $Object.DistinguishedName
|
||||
CanonicalName = if ($Object.CanonicalName) { $Object.CanonicalName.TrimEnd('/') } else { $Object.CanonicalName }
|
||||
Guid = [Regex]::Match( $_, '(?={)(.*)(?<=})').Value -replace '{' -replace '}'
|
||||
}
|
||||
$Search = -join ($DomainCN, $Output['Guid'])
|
||||
if ($GPOCache -and -not $Limited) {
|
||||
if ($GPOCache[$Search]) {
|
||||
$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
|
||||
} else {
|
||||
Write-Warning "Get-PrivGPOZaurrLink - Couldn't find link $Search in a GPO Cache. Lack of permissions for given GPO? Are you running as admin? Skipping."
|
||||
}
|
||||
} else {
|
||||
$Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDC
|
||||
$Output['GPODistinguishedName'] = $_
|
||||
[PSCustomObject] $Output
|
||||
}
|
||||
}
|
||||
}
|
||||
$ObjectsToProcess = $Object.GpLink -split '\]\['
|
||||
} elseif ($Object.LinkedGroupPolicyObjects -and $Object.LinkedGroupPolicyObjects.Trim() -ne '') {
|
||||
$Object.LinkedGroupPolicyObjects -split '\[LDAP://' -split ';' | ForEach-Object -Process {
|
||||
if ($_.Length -gt 10) {
|
||||
$DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDomainCN
|
||||
$Output = [ordered] @{
|
||||
DistinguishedName = $Object.DistinguishedName
|
||||
CanonicalName = if ($Object.CanonicalName) { $Object.CanonicalName.TrimEnd('/') } else { $Object.CanonicalName }
|
||||
Guid = [Regex]::Match( $_, '(?={)(.*)(?<=})').Value -replace '{' -replace '}'
|
||||
}
|
||||
$Search = -join ($DomainCN, $Output['Guid'])
|
||||
if ($GPOCache -and -not $Limited) {
|
||||
if ($GPOCache[$Search]) {
|
||||
$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
|
||||
} else {
|
||||
Write-Warning "Get-PrivGPOZaurrLink - Couldn't find link $Search in a GPO Cache. Lack of permissions for given GPO? Are you running as admin? Skipping."
|
||||
}
|
||||
$ObjectsToProcess = $Object.LinkedGroupPolicyObjects -split '\]\['
|
||||
} else {
|
||||
$ObjectsToProcess = $null
|
||||
}
|
||||
$ObjectsToProcess | ForEach-Object -Process {
|
||||
$Link = $_ -replace 'LDAP://' -replace '\]' -replace '\['
|
||||
if ($Link.Length -gt 10) {
|
||||
$SplitGPLink = $Link -split ';'
|
||||
$DN = $SplitGPLink[0]
|
||||
$Option = $SplitGPLink[1]
|
||||
if ($Option -eq '0') {
|
||||
$Enforced = $false
|
||||
$Enabled = $true
|
||||
} elseif ($Option -eq '1') {
|
||||
$Enabled = $false
|
||||
$Enforced = $false
|
||||
} elseif ($Option -eq '2') {
|
||||
$Enabled = $true
|
||||
$Enforced = $true
|
||||
} elseif ($Option -eq '3') {
|
||||
$Enabled = $false
|
||||
$Enforced = $true
|
||||
} else {
|
||||
if ($Object.GpLink) {
|
||||
Write-Warning "Get-PrivGPOZaurrLink - This should't happen. Please investigate - Option: $Option"
|
||||
} else {
|
||||
$Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDC
|
||||
$Output['GPODistinguishedName'] = $_
|
||||
[PSCustomObject] $Output
|
||||
Write-Warning "Get-PrivGPOZaurrLink - Property GPLink is required to be able to tell if Enabled/Enforced is added. Skipping those settings."
|
||||
}
|
||||
$Enabled = $null
|
||||
$Enforced = $null
|
||||
}
|
||||
$DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $DN -ToDomainCN
|
||||
$Output = [ordered] @{
|
||||
DistinguishedName = $Object.DistinguishedName
|
||||
#Domain = ConvertFrom-DistinguishedName -DistinguishedName $Object.DistinguishedName -ToDomainCN
|
||||
CanonicalName = if ($Object.CanonicalName) { $Object.CanonicalName.TrimEnd('/') } else { $Object.CanonicalName }
|
||||
Guid = [Regex]::Match($DN, '(?={)(.*)(?<=})').Value -replace '{' -replace '}'
|
||||
Enforced = $Enforced
|
||||
Enabled = $Enabled
|
||||
ObjectClass = $Object.ObjectClass
|
||||
}
|
||||
$Search = -join ($DomainCN, $Output['Guid'])
|
||||
if ($GPOCache -and -not $Limited) {
|
||||
if ($GPOCache[$Search]) {
|
||||
$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 $DN -ToDC
|
||||
$Output['GPODistinguishedName'] = $DN
|
||||
# This is object name, usually used for sites
|
||||
$Output['Name'] = $Object.Name
|
||||
[PSCustomObject] $Output
|
||||
} else {
|
||||
Write-Warning "Get-PrivGPOZaurrLink - Couldn't find link $Search in a GPO Cache. Lack of permissions for given GPO? Are you running as admin? Skipping."
|
||||
}
|
||||
} else {
|
||||
$Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $DN -ToDC
|
||||
$Output['GPODistinguishedName'] = $DN
|
||||
[PSCustomObject] $Output
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+129
-61
@@ -9,25 +9,67 @@
|
||||
[string] $Splitter = [System.Environment]::NewLine,
|
||||
[switch] $ReturnObject,
|
||||
[System.Collections.IDictionary] $ExcludeGroupPolicies,
|
||||
[string[]] $Type
|
||||
[string[]] $Type,
|
||||
[System.Collections.IDictionary] $LinksSummaryCache
|
||||
)
|
||||
if ($XMLContent.GPO.LinksTo) {
|
||||
$LinkSplit = ([Array] $XMLContent.GPO.LinksTo).Where( { $_.Enabled -eq $true }, 'Split')
|
||||
[Array] $LinksEnabled = $LinkSplit[0]
|
||||
[Array] $LinksDisabled = $LinkSplit[1]
|
||||
$LinksEnabledCount = $LinksEnabled.Count
|
||||
$LinksDisabledCount = $LinksDisabled.Count
|
||||
$LinksTotalCount = ([Array] $XMLContent.GPO.LinksTo).Count
|
||||
if ($LinksEnabledCount -eq 0) {
|
||||
$Linked = $false
|
||||
|
||||
$DisplayName = $XMLContent.GPO.Name
|
||||
$DomainName = $XMLContent.GPO.Identifier.Domain.'#text'
|
||||
|
||||
if ($LinksSummaryCache) {
|
||||
$SearchGUID = -join ($XMLContent.GPO.Identifier.Domain.'#text', $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}')
|
||||
if ($LinksSummaryCache[$SearchGUID]) {
|
||||
$Linked = $LinksSummaryCache[$SearchGUID].Linked
|
||||
$LinksEnabledCount = $LinksSummaryCache[$SearchGUID].LinksEnabledCount
|
||||
$LinksDisabledCount = $LinksSummaryCache[$SearchGUID].LinksDisabledCount
|
||||
$LinksTotalCount = $LinksSummaryCache[$SearchGUID].LinksCount
|
||||
$Links = $LinksSummaryCache[$SearchGUID].Links
|
||||
$LinksObjects = $LinksSummaryCache[$SearchGUID].LinksObjects
|
||||
} else {
|
||||
$Linked = $true
|
||||
$Linked = $false
|
||||
$LinksEnabledCount = 0
|
||||
$LinksDisabledCount = 0
|
||||
$LinksTotalCount = 0
|
||||
$Links = $null
|
||||
$LinksObjects = $null
|
||||
}
|
||||
} else {
|
||||
$Linked = $false
|
||||
$LinksEnabledCount = 0
|
||||
$LinksDisabledCount = 0
|
||||
$LinksTotalCount = 0
|
||||
if ($XMLContent.GPO.LinksTo) {
|
||||
$LinkSplit = ([Array] $XMLContent.GPO.LinksTo).Where( { $_.Enabled -eq $true }, 'Split')
|
||||
[Array] $LinksEnabled = $LinkSplit[0]
|
||||
[Array] $LinksDisabled = $LinkSplit[1]
|
||||
$LinksEnabledCount = $LinksEnabled.Count
|
||||
$LinksDisabledCount = $LinksDisabled.Count
|
||||
$LinksTotalCount = ([Array] $XMLContent.GPO.LinksTo).Count
|
||||
if ($LinksEnabledCount -eq 0) {
|
||||
$Linked = $false
|
||||
} else {
|
||||
$Linked = $true
|
||||
}
|
||||
$Links = @(
|
||||
$XMLContent.GPO.LinksTo | ForEach-Object -Process {
|
||||
if ($_) {
|
||||
$_.SOMPath
|
||||
}
|
||||
}
|
||||
) -join $Splitter
|
||||
$LinksObjects = $XMLContent.GPO.LinksTo | ForEach-Object -Process {
|
||||
if ($_) {
|
||||
[PSCustomObject] @{
|
||||
CanonicalName = $_.SOMPath
|
||||
Enabled = $_.Enabled
|
||||
NoOverride = $_.NoOverride
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$Linked = $false
|
||||
$LinksEnabledCount = 0
|
||||
$LinksDisabledCount = 0
|
||||
$LinksTotalCount = 0
|
||||
$Links = $null
|
||||
$LinksObjects = $null
|
||||
}
|
||||
}
|
||||
# Find proper values for enabled/disabled user/computer settings
|
||||
if ($XMLContent.GPO.Computer.Enabled -eq 'False') {
|
||||
@@ -35,7 +77,7 @@
|
||||
} elseif ($XMLContent.GPO.Computer.Enabled -eq 'True') {
|
||||
$ComputerEnabled = $true
|
||||
} else {
|
||||
Write-Warning "Get-XMLGPO - Computer enabled not set to true or false. Weird."
|
||||
Write-Warning "Get-XMLGPO - Computer enabled not set to true or false [$DisplayName/$DomainName]. Weird."
|
||||
$ComputerEnabled = $null
|
||||
}
|
||||
if ($XMLContent.GPO.User.Enabled -eq 'False') {
|
||||
@@ -43,7 +85,7 @@
|
||||
} elseif ($XMLContent.GPO.User.Enabled -eq 'True') {
|
||||
$UserEnabled = $true
|
||||
} else {
|
||||
Write-Warning "Get-XMLGPO - User enabled not set to true or false. Weird."
|
||||
Write-Warning "Get-XMLGPO - User enabled not set to true or false [$DisplayName/$DomainName] . Weird."
|
||||
$UserEnabled = $null
|
||||
}
|
||||
# Translate Enabled to same as GPO GUI
|
||||
@@ -62,8 +104,8 @@
|
||||
}
|
||||
|
||||
# This is kind of old way of doing things, but it's superseded by other way below
|
||||
$ComputerSettingsAvailable = if ($null -eq $XMLContent.GPO.Computer.ExtensionData) { $false } else { $true }
|
||||
$UserSettingsAvailable = if ($null -eq $XMLContent.GPO.User.ExtensionData) { $false } else { $true }
|
||||
[bool] $ComputerSettingsAvailable = if ($null -eq $XMLContent.GPO.Computer.ExtensionData) { $false } else { $true }
|
||||
[bool] $UserSettingsAvailable = if ($null -eq $XMLContent.GPO.User.ExtensionData) { $false } else { $true }
|
||||
|
||||
if ($ComputerSettingsAvailable -eq $false -and $UserSettingsAvailable -eq $false) {
|
||||
$NoSettings = $true
|
||||
@@ -74,35 +116,58 @@
|
||||
# $OutputUser = $XMLContent.GPO.User.ExtensionData.Extension | Where-Object { $_.PSObject.Properties.TypeNameOfValue -in 'System.Xml.XmlElement', 'System.Object[]' }
|
||||
# $OutputComputer = $XMLContent.GPO.Computer.ExtensionData.Extension | Where-Object { $_.PSObject.Properties.TypeNameOfValue -in 'System.Xml.XmlElement', 'System.Object[]' }
|
||||
|
||||
$OutputUser = foreach ($ExtensionType in $XMLContent.GPO.User.ExtensionData.Extension) {
|
||||
if ($ExtensionType) {
|
||||
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
|
||||
try {
|
||||
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
|
||||
} catch {
|
||||
Write-Warning "Get-XMLGPO - things went sideways $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
|
||||
# This is additional check we do for error check to prevent false-positives for EMPTY on non-english language
|
||||
$PreCheckOutputUser = $false
|
||||
$PreCheckOutputComputer = $false
|
||||
foreach ($Extension in $XMLContent.GPO.User.ExtensionData) {
|
||||
if ($Extension.Error) {
|
||||
$PreCheckOutputUser = $true
|
||||
}
|
||||
$KeysToLoop
|
||||
}
|
||||
$OutputComputer = foreach ($ExtensionType in $XMLContent.GPO.Computer.ExtensionData.Extension) {
|
||||
if ($ExtensionType) {
|
||||
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
|
||||
try {
|
||||
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
|
||||
} catch {
|
||||
Write-Warning "Get-XMLGPO - things went sideways $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
foreach ($Extension in $XMLContent.GPO.Computer.ExtensionData) {
|
||||
if ($Extension.Error) {
|
||||
$PreCheckOutputComputer = $true
|
||||
}
|
||||
$KeysToLoop
|
||||
}
|
||||
if ($PreCheckOutputComputer -eq $true -or $PreCheckOutputUser -eq $true) {
|
||||
# in some cases GPResult seems to return an error - this was first noticed by user when using Dutch based system
|
||||
# I am not sure if it's possible to fix this error for users, but once that happens checking if GPO is empty fails using the method below
|
||||
# therefore we will use the old method of assuming something is empty or not empty in such case
|
||||
Write-Warning "Get-XMLGPO - Reading GPO content [$DisplayName/$DomainName] returned an error. This may be because of non-english language. Assesing EMPTY using old method which can report false positives. Be careful please."
|
||||
$OutputUser = @()
|
||||
$OutputComputer = @()
|
||||
} else {
|
||||
[Array] $OutputUser = foreach ($ExtensionType in $XMLContent.GPO.User.ExtensionData.Extension) {
|
||||
if ($ExtensionType) {
|
||||
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
|
||||
try {
|
||||
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
|
||||
} catch {
|
||||
Write-Warning "Get-XMLGPO - things went sideways [$DisplayName/$DomainName]. Error $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
}
|
||||
$KeysToLoop
|
||||
}
|
||||
[Array] $OutputComputer = foreach ($ExtensionType in $XMLContent.GPO.Computer.ExtensionData.Extension) {
|
||||
if ($ExtensionType) {
|
||||
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
|
||||
try {
|
||||
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
|
||||
} catch {
|
||||
Write-Warning "Get-XMLGPO - things went sideways [$DisplayName/$DomainName]. Error $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
}
|
||||
$KeysToLoop
|
||||
}
|
||||
|
||||
[bool] $ComputerSettingsAvailable = if ($OutputComputer.Count -gt 0) { $true } else { $false }
|
||||
[bool] $UserSettingsAvailable = if ($OutputUser.Count -gt 0) { $true } else { $false }
|
||||
}
|
||||
|
||||
$ComputerSettingsAvailable = if ($OutputComputer) { $true } else { $false }
|
||||
$UserSettingsAvailable = if ($OutputUser) { $true } else { $false }
|
||||
|
||||
if (-not $ComputerSettingsAvailable -and -not $UserSettingsAvailable) {
|
||||
if ($ComputerSettingsAvailable -eq $false -and $UserSettingsAvailable -eq $false) {
|
||||
$Empty = $true
|
||||
} else {
|
||||
$Empty = $false
|
||||
@@ -217,11 +282,13 @@
|
||||
'DisplayName' = $XMLContent.GPO.Name
|
||||
'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text'
|
||||
'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}'
|
||||
'Days' = (New-TimeSpan -Start ([DateTime] $XMLContent.GPO.ModifiedTime) -End (Get-Date)).Days
|
||||
'Empty' = $Empty
|
||||
'Linked' = $Linked
|
||||
'Enabled' = $EnabledBool
|
||||
'Optimized' = $Optimized
|
||||
'Problem' = $Problem
|
||||
'ApplyPermission' = $null
|
||||
'Exclude' = $Exclude
|
||||
'ComputerPolicies' = $XMLContent.GPO.Computer.ExtensionData.Name -join ", "
|
||||
'UserPolicies' = $XMLContent.GPO.User.ExtensionData.Name -join ", "
|
||||
@@ -237,8 +304,8 @@
|
||||
'UserSettingsAvailable' = $UserSettingsAvailable
|
||||
#'ComputerSettingsAvailableReal' = $ComputerSettingsAvailableReal
|
||||
#'UserSettingsAvailableReal' = $UserSettingsAvailableReal
|
||||
'ComputerSettingsTypes' = $OutputComputer.Name
|
||||
'UserSettingsTypes' = $OutputUser.Name
|
||||
'ComputerSettingsTypes' = $OutputComputer.Name -join ", "
|
||||
'UserSettingsTypes' = $OutputUser.Name -join ", "
|
||||
'ComputerEnabled' = $ComputerEnabled
|
||||
'UserEnabled' = $UserEnabled
|
||||
'ComputerSettingsStatus' = if ($XMLContent.GPO.Computer.VersionDirectory -eq 0 -and $XMLContent.GPO.Computer.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" }
|
||||
@@ -248,6 +315,7 @@
|
||||
'UserSettingsVersionIdentical' = if ($XMLContent.GPO.User.VersionDirectory -eq $XMLContent.GPO.User.VersionSysvol) { $true } else { $false }
|
||||
'UserSettings' = $XMLContent.GPO.User.ExtensionData.Extension
|
||||
'NoSettings' = $NoSettings
|
||||
'Description' = $GPO.Description
|
||||
'CreationTime' = [DateTime] $XMLContent.GPO.CreatedTime
|
||||
'ModificationTime' = [DateTime] $XMLContent.GPO.ModifiedTime
|
||||
'ReadTime' = [DateTime] $XMLContent.GPO.ReadTime
|
||||
@@ -279,24 +347,19 @@
|
||||
}
|
||||
)
|
||||
'Auditing' = if ($XMLContent.GPO.SecurityDescriptor.AuditingPresent.'#text' -eq 'true') { $true } else { $false }
|
||||
'Links' = @(
|
||||
$XMLContent.GPO.LinksTo | ForEach-Object -Process {
|
||||
if ($_) {
|
||||
$_.SOMPath
|
||||
}
|
||||
}
|
||||
) -join $Splitter
|
||||
'LinksObjects' = $XMLContent.GPO.LinksTo | ForEach-Object -Process {
|
||||
if ($_) {
|
||||
[PSCustomObject] @{
|
||||
CanonicalName = $_.SOMPath
|
||||
Enabled = $_.Enabled
|
||||
NoOverride = $_.NoOverride
|
||||
}
|
||||
}
|
||||
}
|
||||
'Links' = $Links
|
||||
'LinksObjects' = $LinksObjects
|
||||
'GPOObject' = $GPO
|
||||
}
|
||||
if ($GPOOutput.ACL) {
|
||||
$GPOOutput.ApplyPermission = $false
|
||||
foreach ($Permission in $GPOOutput.ACL) {
|
||||
if ($Permission.Permissions -eq 'Apply Group Policy') {
|
||||
$GPOOutput.ApplyPermission = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if ($PermissionsOnly -or $OwnerOnly) {
|
||||
$GPOOutput
|
||||
@@ -319,6 +382,11 @@
|
||||
$GPOOutput
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'NoApplyPermission') {
|
||||
if ($GPOOutput.ApplyPermission -eq $false) {
|
||||
$GPOOutput
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOAnalysis']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
}
|
||||
} -SearchBuilder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,25 +4,207 @@
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrInheritance -IncludeBlockedObjects -OnlyBlockedInheritance -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
if ($Script:Reporting['GPOBlockedInheritance']['Exclusions']) {
|
||||
Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance -IncludeGroupPoliciesForBlockedObjects -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $Excludeomains -Exclusions $Script:Reporting['GPOBlockedInheritance']['Exclusions']
|
||||
} else {
|
||||
Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance -IncludeGroupPoliciesForBlockedObjects -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $Excludeomains
|
||||
}
|
||||
}
|
||||
Processing = {
|
||||
foreach ($GPO in $Script:Reporting['GPOBlockedInheritance']['Data']) {
|
||||
if (-not $Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmlessPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmlessPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigationPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigationPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if ($GPO.Exclude -eq $true) {
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['Exclude']++
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedExclude'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedExclude'] + $GPO.UsersCount
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedExclude'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedExclude'] + $GPO.ComputersCount
|
||||
} else {
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffected'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffected'] + $GPO.UsersCount
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffected'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffected'] + $GPO.ComputersCount
|
||||
}
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedIncludingExclude'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedIncludingExclude'] + $GPO.UsersCount
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedIncludingExclude'] = $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedIncludingExclude'] + $GPO.ComputersCount
|
||||
|
||||
if ($GPO.Exclude -eq $false -and ($GPO.UsersCount -gt 0 -or $GPO.ComputersCount -gt 0)) {
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigation']++
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigationPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
if ($GPO.Exclude -eq $false -and ($GPO.UsersCount -eq 0 -and $GPO.ComputersCount -eq 0)) {
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmless']++
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmlessPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
# add gpo from blocked inheritance to create additional table
|
||||
#foreach ($GpoBlocked in $Script:Reporting['GPOBlockedInheritance']['Data'].GroupPolicies) {
|
||||
#$Script:Reporting['GPOBlockedInheritance']['Variables']['GroupPolicies'].Add($GpoBlocked)
|
||||
#}
|
||||
}
|
||||
if ($Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigation'] -gt 0 -or $Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmless'] -gt 0) {
|
||||
$Script:Reporting['GPOBlockedInheritance']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOBlockedInheritance']['ActionRequired'] = $false
|
||||
}
|
||||
}
|
||||
Resources = @(
|
||||
'http://www.firewall.cx/microsoft-knowledgebase/windows-2012/1056-windows-2012-group-policy-enforcement.html'
|
||||
)
|
||||
Variables = @{
|
||||
|
||||
Total = 0
|
||||
Exclude = 0
|
||||
RequiresInvesigation = 0
|
||||
RequiresInvesigationPerDomain = [ordered] @{}
|
||||
DeletionHarmless = 0
|
||||
DeletionHarmlessPerDomain = [ordered] @{}
|
||||
UsersAffected = 0
|
||||
UsersAffectedExclude = 0
|
||||
UsersAffectedIncludingExclude = 0
|
||||
ComputersAffected = 0
|
||||
ComputersAffectedIncludingExclude = 0
|
||||
ComputersAffectedExclude = 0
|
||||
GroupPolicies = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
}
|
||||
Overview = {
|
||||
|
||||
}
|
||||
Summary = {
|
||||
New-HTMLText -FontSize 10pt -TextBlock {
|
||||
"By default, group policy settings that are linked to parent objects are inherited to the child objects in the active directory hierarchy. "
|
||||
"By default, Default Domain Policy is linked to the domain and is inherited to all the child objects of the domain hierarchy. "
|
||||
"So does any other policies linked to the top level OU's. "
|
||||
}
|
||||
New-HTMLText -Text "Block Inheritance" -FontSize 10pt -FontWeight bold
|
||||
New-HTMLText -FontSize 10pt -Text @(
|
||||
"As GPOs can be inherited by default, they can also be blocked, if required using the Block Inheritance. "
|
||||
"If the Block Inheritance setting is enabled, the inheritance of group policy setting is blocked. "
|
||||
"This setting is mostly used when the OU contains users or computers that require different settings than what is applied to the domain level. "
|
||||
"Unfortunetly blocking inheritance can have serious security consequences. "
|
||||
)
|
||||
New-HTMLText -Text @(
|
||||
'As it stands currently there are ',
|
||||
$Script:Reporting['GPOBlockedInheritance']['Data'].Count,
|
||||
' organiational units with '
|
||||
'GPO Inheritance Block'
|
||||
' out of which '
|
||||
$Script:Reporting['GPOBlockedInheritance']['Variables']['Exclude'].Count,
|
||||
' are marked as Excluded '
|
||||
'(approved by IT). '
|
||||
) -FontSize 10pt -FontWeight normal, bold, normal, bold, normal, bold, normal, bold -LineBreak
|
||||
if ($Script:Reporting['GPOBlockedInheritance']['Data'].Count -ne 0) {
|
||||
New-HTMLText -Text 'Users & Computers affected by inheritance blocks:' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffected'], ' users affected due to inheritance blocks' -FontWeight bold, normal
|
||||
New-HTMLListItem -Text $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedExclude'], ' users affected, but approved/Exclude, due to inheritance blocks' -FontWeight bold, normal
|
||||
New-HTMLListItem -Text $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffected'], ' computers affected due to inheritance blocks' -FontWeight bold, normal
|
||||
New-HTMLListItem -Text $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedExclude'], ' computers affected, but approved/Exclude, due to inheritance blocks' -FontWeight bold, normal
|
||||
} -FontSize 10pt
|
||||
|
||||
New-HTMLText -Text 'Following domains require:' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
foreach ($Domain in $Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigationPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain proposes ", $Script:Reporting['GPOBlockedInheritance']['Variables']['RequiresInvesigationPerDomain'][$Domain], " investigation (computers or users inside)." -FontWeight normal, bold, normal
|
||||
New-HTMLListItem -Text "$Domain proposes ", $Script:Reporting['GPOBlockedInheritance']['Variables']['DeletionHarmlessPerDomain'][$Domain], " removal (mostly harmless due to no computers or users inside)." -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
}
|
||||
New-HTMLText -FontSize 10pt -Text "Please review output in table and follow the steps below table to get Active Directory Group Policies in healthy state."
|
||||
}
|
||||
Solution = {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOBlockedInheritance']['Data'] -Filtering
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLPanel {
|
||||
& $Script:GPOConfiguration['GPOBlockedInheritance']['Summary']
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartLegend -Names 'Affected', 'Affected, but Exclude' -Color Salmon, PaleGreen
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartBar -Name 'Users' -Value $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffected'], $Script:Reporting['GPOBlockedInheritance']['Variables']['UsersAffectedExclude']
|
||||
New-ChartBar -Name 'Computers' -Value $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffected'], $Script:Reporting['GPOBlockedInheritance']['Variables']['ComputersAffectedExclude']
|
||||
} -Title 'Users & Computers affected due to blocked inheritance' -TitleAlignment center
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'Organizational Units with Group Policy Blocked Inheritance' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOBlockedInheritance']['Data'] -Filtering {
|
||||
New-TableEvent -TableID 'TableWithGroupPoliciesBlockedInheritance' -SourceColumnID 8 -TargetColumnID 9
|
||||
New-HTMLTableCondition -Name 'Exclude' -Value $true -BackgroundColor DeepSkyBlue -ComparisonType string -Row
|
||||
New-TableConditionGroup {
|
||||
New-TableCondition -Name 'BlockedInheritance' -Value $true
|
||||
New-TableCondition -Name 'Exclude' -Value $false
|
||||
} -BackgroundColor Salmon -FailBackgroundColor SpringGreen -HighlightHeaders 'BlockedInheritance', 'Exclude'
|
||||
New-TableConditionGroup {
|
||||
New-TableCondition -Name 'UsersCount' -Value 0
|
||||
New-TableCondition -Name 'ComputersCount' -Value 0
|
||||
} -BackgroundColor Salmon -FailBackgroundColor Amber -HighlightHeaders 'UsersCount', 'ComputersCount'
|
||||
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder -ExcludeProperty GroupPolicies
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policies affecting objects in Organizational Units with Blocked Inheritance' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOBlockedInheritance']['Data'].GroupPolicies -Filtering {
|
||||
New-TableCondition -Name 'Enabled' -Value $true -BackgroundColor SpringGreen -FailBackgroundColor Salmon
|
||||
New-TableCondition -Name 'Enforced' -Value $true -BackgroundColor Amber -FailBackgroundColor AirForceBlue
|
||||
New-TableCondition -Name 'LinkedDirectly' -Value $true -BackgroundColor Amber -FailBackgroundColor AirForceBlue
|
||||
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder -ExcludeProperty GroupPolicies -DataTableID 'TableWithGroupPoliciesBlockedInheritance'
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix - Organizational Units with Group Policy Blocked Inheritance' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLWizard {
|
||||
New-HTMLWizardStep -Name 'Prepare environment' {
|
||||
New-HTMLText -Text "To be able to execute actions in automated way please install required modules. Those modules will be installed straight from Microsoft PowerShell Gallery."
|
||||
New-HTMLCodeBlock -Code {
|
||||
Install-Module GPOZaurr -Force
|
||||
Import-Module GPOZaurr -Force
|
||||
} -Style powershell
|
||||
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text @(
|
||||
"Depending when this report was run you may want to prepare new report before proceeding removing Group Policy Inheritance Blocks. "
|
||||
"Please keep in mind that if exclusions for some Organizational OU's were defined you need to pass them to cmdlet below to not remove approved GPO Inheritance Blocks. "
|
||||
"To generate new report please use:"
|
||||
)
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBlockedGPOInheritanceBefore.html -Verbose -Type GPOBlockedInheritance
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment. "
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step. "
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludeObjects -OnlyBlockedInheritance
|
||||
$GPOOutput | Format-Table # do your actions as desired
|
||||
}
|
||||
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove OU GPO Inheritance Blocks' {
|
||||
New-HTMLText -Text @(
|
||||
"Removing inheritance blocks is quite trivial and can be done from GPO GUI. However knowing when to remove is the important part. "
|
||||
"Please consult other Domain Admins before removing any inheritance blocks, and either approve exclusion or remove blocking inheritance. "
|
||||
)
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Verification report' {
|
||||
New-HTMLText -TextBlock {
|
||||
"Once cleanup task was executed properly, we need to verify that report now shows no problems."
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBlockedGPOInheritanceAfter.html -Verbose -Type GPOBlockedInheritance
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOBlockedInheritance']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOBlockedInheritance']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
}
|
||||
} -SearchBuilder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
$GPOZaurrBrokenLink = [ordered] @{
|
||||
Name = 'Group Policy Broken Links'
|
||||
Enabled = $true
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrBrokenLink -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
$Script:Reporting['GPOBrokenLink']['Variables']['RequireDeletion'] = $Script:Reporting['GPOBrokenLink']['Data'].Count
|
||||
$Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'] = @{}
|
||||
$Script:Reporting['GPOBrokenLink']['Variables']['Unique'] = @{}
|
||||
foreach ($Link In $Script:Reporting['GPOBrokenLink']['Data']) {
|
||||
$DomainName = ConvertFrom-DistinguishedName -ToDomainCN -DistinguishedName $Link.DistinguishedName
|
||||
# Create Per Domain Variables
|
||||
if (-not $Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'][$DomainName]) {
|
||||
$Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'][$DomainName] = 0
|
||||
}
|
||||
$Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'][$DomainName]++
|
||||
# Lets do unique OU counting
|
||||
$Script:Reporting['GPOBrokenLink']['Variables']['Unique'][$Link.CanonicalName] = $Link
|
||||
}
|
||||
$Script:Reporting['GPOBrokenLink']['Variables']['UniqueObjects'] = $Script:Reporting['GPOBrokenLink']['Variables']['Unique'].Keys
|
||||
|
||||
if ($Script:Reporting['GPOBrokenLink']['Data'].Count -gt 0) {
|
||||
$Script:Reporting['GPOBrokenLink']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOBrokenLink']['ActionRequired'] = $false
|
||||
}
|
||||
}
|
||||
Variables = @{
|
||||
RequireDeletion = 0
|
||||
WillFixPerDomain = $null
|
||||
UniqueObjects = $null
|
||||
Unique = $null
|
||||
}
|
||||
Overview = {
|
||||
|
||||
}
|
||||
Summary = {
|
||||
New-HTMLText -FontSize 10pt -TextBlock {
|
||||
"When GPO is deleted correctly, it usually is removed from AD, SYSVOL, and any link to it is also discarded. "
|
||||
"Unfortunately, this is true only if the GPO is created and linked within the same domain. "
|
||||
"If GPO is linked in another domain, this leaves a broken link hanging on before it was linked. "
|
||||
"Additionally, the Remove-GPO cmdlet doesn't handle site link deletions, which causes dead links to be stuck on sites until those are manually deleted. "
|
||||
"This means that any GPOs deleted using PowerShell may leave a trail."
|
||||
}
|
||||
New-HTMLText -Text @(
|
||||
'As it stands currently there are ',
|
||||
$Script:Reporting['GPOBrokenLink']['Data'].Count,
|
||||
' broken links that need to be deleted over '
|
||||
$Script:Reporting['GPOBrokenLink']['Variables']['UniqueObjects'].Count,
|
||||
' unique objects. '
|
||||
) -FontSize 10pt -FontWeight normal, bold, normal, bold, normal -LineBreak
|
||||
if ($Script:Reporting['GPOBrokenLink']['Data'].Count -ne 0) {
|
||||
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
foreach ($Domain in $Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOBrokenLink']['Variables']['WillFixPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
}
|
||||
}
|
||||
Solution = {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLPanel {
|
||||
& $Script:GPOConfiguration['GPOBrokenLink']['Summary']
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartLegend -Names 'Bad' -Color Salmon
|
||||
New-ChartBar -Name 'Broken Links' -Value $Script:Reporting['GPOBrokenLink']['Data'].Count
|
||||
} -Title 'Broken Links' -TitleAlignment center
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policy Broken Links' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOBrokenLink']['Data'] -Filtering {
|
||||
|
||||
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to remove Broken Links' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLWizard {
|
||||
New-HTMLWizardStep -Name 'Prepare environment' {
|
||||
New-HTMLText -Text "To be able to execute actions in automated way please install required modules. Those modules will be installed straight from Microsoft PowerShell Gallery."
|
||||
New-HTMLCodeBlock -Code {
|
||||
Install-Module GPOZaurr -Force
|
||||
Import-Module GPOZaurr -Force
|
||||
} -Style powershell
|
||||
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding fixing GPO links. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenLinkBefore.html -Verbose -Type GPOBrokenLink
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment. "
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step. "
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurrBrokenLink -Verbose
|
||||
$GPOOutput | Format-Table * # do your actions as desired
|
||||
}
|
||||
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove Broken Links' {
|
||||
New-HTMLText -Text "Following command when executed, runs internally command that lists all broken links. After finding them all it delets them according to given criteria. "
|
||||
New-HTMLText -Text "Make sure when running it for the first time to run it with ", "WhatIf", " parameter as shown below to prevent accidental removal." -FontWeight normal, bold, normal -Color Black, Red, Black
|
||||
|
||||
New-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrBrokenLink -WhatIf -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be changed matches expected data. Once happy with results please follow with command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrBrokenLink -Verbose -LimitProcessing 2
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed removes only first X number of links. Keep in mind that 5 broken links on a single Organizational Unit are treated as one. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur. "
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly. "
|
||||
}
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Verification report' {
|
||||
New-HTMLText -TextBlock {
|
||||
"Once cleanup task was executed properly, we need to verify that report now shows no problems."
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenLinkAfter.html -Verbose -Type GPOBrokenLink
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOBrokenLink']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOBrokenLink']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,11 +52,12 @@
|
||||
}
|
||||
Summary = {
|
||||
New-HTMLText -FontSize 10pt -TextBlock {
|
||||
"When GPO is created it creates an entry in Active Directory (metadata) and SYSVOL (content). "
|
||||
"Two different places meens two different sets of permissions. Group Policy module is making sure the data in both places is correct. "
|
||||
"However, for different reasons it's not nessecary the case and often permissions go out of sync between AD and SYSVOL. "
|
||||
"This test verifies consistency of policies between AD and SYSVOL in two ways. "
|
||||
"It checks top level permissions for a GPO, and then checks if all files within said GPO are inheriting permissions or have different permissions in place. "
|
||||
"When GPO is created, it creates an entry in Active Directory (metadata) and SYSVOL (content). "
|
||||
"Two different places mean two different sets of permissions. "
|
||||
"The group Policy module is making sure the data in both places is correct. "
|
||||
"However, it's not necessarily the case for different reasons, and often permissions go out of sync between AD and SYSVOL. "
|
||||
"This test verifies the consistency of policies between AD and SYSVOL in two ways. "
|
||||
"It checks top-level permissions for a GPO and then checks if all files within said GPO is inheriting permissions or have different permissions in place."
|
||||
}
|
||||
New-HTMLText -Text 'Following list presents ', 'permissions consistency between Active Directory and SYSVOL for Group Policies' -FontSize 10pt -FontWeight normal, bold
|
||||
New-HTMLList -Type Unordered {
|
||||
@@ -90,7 +91,7 @@
|
||||
New-HTMLTableCondition -Name 'ACLConsistentInside' -Value $true -BackgroundColor PaleGreen -TextTransform capitalize -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ACLConsistent' -Value 'Not available' -BackgroundColor Crimson -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ACLConsistentInside' -Value 'Not available' -BackgroundColor Crimson -ComparisonType string
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix - Permissions Consistency' {
|
||||
@@ -111,10 +112,10 @@
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrPermissionsInconsistentBefore.html -Verbose -Type GPOConsistency
|
||||
}
|
||||
New-HTMLText -Text {
|
||||
New-HTMLText -Text @(
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
)
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurrPermissionConsistency
|
||||
@@ -143,8 +144,12 @@
|
||||
New-HTMLText -Text "If there's nothing else to be fixed, we can skip to next step step"
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Fix inconsistent downlevel permissions' {
|
||||
New-HTMLText -Text "Unfortunetly this step is manual until automation is developed. "
|
||||
New-HTMLText -Text "If there are inconsistent permissions found inside GPO one has to fix them manually by going into SYSVOL and making sure inheritance is enabled, and that permissions are consistent across all files."
|
||||
New-HTMLText -Text @(
|
||||
"Unfortunetly this step is manual until automation is developed. "
|
||||
"If there are inconsistent permissions found inside GPO one has to fix them manually by going into SYSVOL and making sure inheritance is enabled, and that permissions are consistent across all files."
|
||||
"Please keep in mind that it's possible inconsistent downlevel permissions fix will not be required once the top level fix is applied. "
|
||||
"Rerun report to find out if you've just fixed top-level permissions. "
|
||||
)
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Verification report' {
|
||||
New-HTMLText -TextBlock {
|
||||
@@ -155,7 +160,7 @@
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
New-HTMLSection -Name 'Group Policy CNF (Duplicate) Objects' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPODuplicates']['Data'] -Filtering {
|
||||
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix - Remove duplicate (CNF) objects' {
|
||||
@@ -68,7 +68,7 @@
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrDuplicateObjectsBefore.html -Verbose -Type GPODuplicates
|
||||
}
|
||||
New-HTMLText -Text {
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment. "
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step. "
|
||||
}
|
||||
@@ -106,7 +106,7 @@
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOFiles']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
}
|
||||
} -SearchBuilder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
$GPOZaurrLinks = [ordered] @{
|
||||
Name = 'Group Policy Links'
|
||||
Enabled = $true
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrLink -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -Summary
|
||||
}
|
||||
Processing = {
|
||||
|
||||
}
|
||||
Variables = @{
|
||||
|
||||
}
|
||||
Overview = {
|
||||
|
||||
}
|
||||
Solution = {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOLinks']['Data'] -Filtering
|
||||
if ($Script:Reporting['GPOLinks']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOLinks']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -SearchBuilder
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+185
-53
@@ -19,6 +19,8 @@
|
||||
$Script:Reporting['GPOList']['Variables']['GPOOptimizedPerDomain'] = @{}
|
||||
$Script:Reporting['GPOList']['Variables']['GPOProblemPerDomain'] = @{}
|
||||
$Script:Reporting['GPOList']['Variables']['GPONoProblemPerDomain'] = @{}
|
||||
$Script:Reporting['GPOList']['Variables']['GPOApplyPermissionYesPerDomain'] = @{}
|
||||
$Script:Reporting['GPOList']['Variables']['GPOApplypermissionNoPerDomain'] = @{}
|
||||
foreach ($GPO in $Script:Reporting['GPOList']['Data']) {
|
||||
# Create Per Domain Variables
|
||||
if (-not $Script:Reporting['GPOList']['Variables']['GPONotValidPerDomain'][$GPO.DomainName]) {
|
||||
@@ -39,7 +41,22 @@
|
||||
if (-not $Script:Reporting['GPOList']['Variables']['GPONoProblemPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOList']['Variables']['GPONoProblemPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if ($GPO.Enabled -eq $false -or $GPO.Empty -eq $true -or $GPO.Linked -eq $false) {
|
||||
if (-not $Script:Reporting['GPOList']['Variables']['GPOApplyPermissionYesPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOList']['Variables']['GPOApplyPermissionYesPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOList']['Variables']['GPOApplypermissionNoPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOList']['Variables']['GPOApplypermissionNoPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
|
||||
if ($GPO.Days -le $Script:Reporting['GPOList']['Variables']['GPOOlderThan']) {
|
||||
# Skip GPOS that are younger than 30 days
|
||||
$Script:Reporting['GPOList']['Variables']['GPOSkip']++
|
||||
}
|
||||
if (($GPO.Enabled -eq $false -or $GPO.Empty -eq $true -or $GPO.Linked -eq $false -or $GPO.ApplyPermission -eq $false) -and $GPO.Days -le $Script:Reporting['GPOList']['Variables']['GPOOlderThan']) {
|
||||
# Skip GPOS that are younger than 30 days
|
||||
$Script:Reporting['GPOList']['Variables']['GPONotValidButSkip']++
|
||||
}
|
||||
if (($GPO.Enabled -eq $false -or $GPO.Empty -eq $true -or $GPO.Linked -eq $false -or $GPO.ApplyPermission -eq $false) -and $GPO.Days) {
|
||||
$Script:Reporting['GPOList']['Variables']['GPONotValid']++
|
||||
$Script:Reporting['GPOList']['Variables']['GPONotValidPerDomain'][$GPO.DomainName]++
|
||||
} else {
|
||||
@@ -78,6 +95,11 @@
|
||||
} else {
|
||||
$Script:Reporting['GPOList']['Variables']['GPODisabled']++
|
||||
}
|
||||
if ($GPO.ApplyPermission -eq $true) {
|
||||
$Script:Reporting['GPOList']['Variables']['ApplyPermissionYes']++
|
||||
} else {
|
||||
$Script:Reporting['GPOList']['Variables']['ApplyPermissionNo']++
|
||||
}
|
||||
if ($GPO.LinksDisabledCount -eq $GPO.LinksCount -and $GPO.LinksCount -gt 0) {
|
||||
$Script:Reporting['GPOList']['Variables']['GPOLinkedButLinkDisabled']++
|
||||
}
|
||||
@@ -120,45 +142,52 @@
|
||||
}
|
||||
}
|
||||
$Script:Reporting['GPOList']['Variables']['GPOTotal'] = $Script:Reporting['GPOList']['Data'].Count
|
||||
if ($Script:Reporting['GPOList']['Variables']['GPONotValid'] -gt 0) {
|
||||
if ($Script:Reporting['GPOList']['Variables']['GPONotValid'] -gt 0 -and $Script:Reporting['GPOList']['Variables']['GPONotValidButSkip'] -ne $Script:Reporting['GPOList']['Variables']['GPONotValid']) {
|
||||
$Script:Reporting['GPOList']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOList']['ActionRequired'] = $false
|
||||
}
|
||||
}
|
||||
Variables = @{
|
||||
GPONotValidPerDomain = $null
|
||||
GPOValidPerDomain = $null
|
||||
GPONotOptimizedPerDomain = $null
|
||||
GPOOptimizedPerDomain = $null
|
||||
GPOProblemPerDomain = $null
|
||||
GPONoProblemPerDomain = $null
|
||||
GPOWithProblems = 0
|
||||
ComputerOptimizedYes = 0
|
||||
ComputerOptimizedNo = 0
|
||||
ComputerProblemYes = 0
|
||||
ComputerProblemNo = 0
|
||||
UserOptimizedYes = 0
|
||||
UserOptimizedNo = 0
|
||||
UserProblemYes = 0
|
||||
UserProblemNo = 0
|
||||
GPOOptimized = 0
|
||||
GPONotOptimized = 0
|
||||
GPOProblem = 0
|
||||
GPONoProblem = 0
|
||||
GPONotLinked = 0
|
||||
GPOLinked = 0
|
||||
GPOEmpty = 0
|
||||
GPONotEmpty = 0
|
||||
GPOEmptyAndUnlinked = 0
|
||||
GPOEmptyOrUnlinked = 0
|
||||
GPOLinkedButEmpty = 0
|
||||
GPOEnabled = 0
|
||||
GPODisabled = 0
|
||||
GPOValid = 0
|
||||
GPONotValid = 0
|
||||
GPOLinkedButLinkDisabled = 0
|
||||
GPOTotal = 0
|
||||
GPOOlderThan = 30
|
||||
GPONotValidPerDomain = $null
|
||||
GPOValidPerDomain = $null
|
||||
GPONotOptimizedPerDomain = $null
|
||||
GPOOptimizedPerDomain = $null
|
||||
GPOProblemPerDomain = $null
|
||||
GPONoProblemPerDomain = $null
|
||||
GPOApplyPermissionYesPerDomain = $null
|
||||
GPOApplyPermissionNoPerDomain = $null
|
||||
GPOWithProblems = 0
|
||||
ComputerOptimizedYes = 0
|
||||
ComputerOptimizedNo = 0
|
||||
ComputerProblemYes = 0
|
||||
ComputerProblemNo = 0
|
||||
UserOptimizedYes = 0
|
||||
UserOptimizedNo = 0
|
||||
UserProblemYes = 0
|
||||
UserProblemNo = 0
|
||||
GPOOptimized = 0
|
||||
GPONotOptimized = 0
|
||||
GPOProblem = 0
|
||||
GPONoProblem = 0
|
||||
GPONotLinked = 0
|
||||
GPOLinked = 0
|
||||
GPOEmpty = 0
|
||||
GPONotEmpty = 0
|
||||
GPOEmptyAndUnlinked = 0
|
||||
GPOEmptyOrUnlinked = 0
|
||||
GPOLinkedButEmpty = 0
|
||||
GPOEnabled = 0
|
||||
GPODisabled = 0
|
||||
GPOSkip = 0
|
||||
GPOValid = 0
|
||||
GPONotValid = 0
|
||||
GPONotValidButSkip = 0
|
||||
GPOLinkedButLinkDisabled = 0
|
||||
GPOTotal = 0
|
||||
ApplyPermissionYes = 0
|
||||
ApplyPermissionNo = 0
|
||||
}
|
||||
Overview = {
|
||||
|
||||
@@ -167,21 +196,27 @@
|
||||
New-HTMLText -TextBlock {
|
||||
"Over time Administrators add more and more group policies, as business requirements change. "
|
||||
"Due to neglection or thinking it may serve it's purpose later on a lot of Group Policies often have no value at all. "
|
||||
"Either the Group Policy is not linked to anything and just stays unlinked forever, or GPO is linked, but the link (links) are disabled. "
|
||||
"Either the Group Policy is not linked to anything and just stays unlinked forever, or GPO is linked, but the link (links) are disabled or GPO is totally disabled. "
|
||||
"Then there are Group Policies that are targetting certain group or person and that group is removed leaving Group Policy doing nothing. "
|
||||
"Additionally sometimes new GPO is created without any settings or the settings are removed over time, but GPO stays in place. "
|
||||
} -FontSize 10pt
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies total: ', $Script:Reporting['GPOList']['Variables']['GPOTotal'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies valid: ", $Script:Reporting['GPOList']['Variables']['GPOValid'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies to delete: ", $Script:Reporting['GPOList']['Variables']['GPONotValid'] -FontWeight normal, bold {
|
||||
New-HTMLListItem -Text "Group Policies ", "NOT", " valid: ", $Script:Reporting['GPOList']['Variables']['GPONotValid'] -FontWeight normal, bold, normal, bold {
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies that are unlinked (are not doing anything currently): ', $Script:Reporting['GPOList']['Variables']['GPONotLinked'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are empty (have no settings): ", $Script:Reporting['GPOList']['Variables']['GPOEmpty'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are linked, but empty: ", $Script:Reporting['GPOList']['Variables']['GPOLinkedButEmpty'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are linked, but link disabled: ", $Script:Reporting['GPOList']['Variables']['GPOLinkedButLinkDisabled'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are disabled (both user/computer sections): ", $Script:Reporting['GPOList']['Variables']['GPODisabled'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that have no Apply Permission: ", $Script:Reporting['GPOList']['Variables']['ApplyPermissionNo'] -FontWeight normal, bold
|
||||
}
|
||||
}
|
||||
} -Color Black, Red, Black, Red, Black
|
||||
New-HTMLListItem -Text @(
|
||||
"Group Policies ", "NOT", " valid, to skip: ", $Script:Reporting['GPOList']['Variables']['GPONotValidButSkip'], " (modified less than $($Script:Reporting['GPOList']['Variables']['GPOOlderThan']) days ago)"
|
||||
) -FontWeight 'normal', 'bold', 'normal', 'bold', 'normal' -Color 'Black', 'Red', 'Black', 'Red', 'Black'
|
||||
New-HTMLListItem -Text "Group Policies recently modified: ", $Script:Reporting['GPOList']['Variables']['GPOSkip'], " (modified less than $($Script:Reporting['GPOList']['Variables']['GPOOlderThan']) days ago)" -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
|
||||
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
|
||||
@@ -257,6 +292,13 @@
|
||||
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOList']['Variables']['GPONotOptimizedPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
# Just in case report is too big and the full file is not attached
|
||||
New-HTMLText -FontSize 10pt -Text "To generate up to date report please execute: " -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Install-Module GPOZaurr -Force', ' or ', ' install module manually.' -Color RoyalBlue, None, None
|
||||
New-HTMLListItem -Text 'Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOPListBefore.html -Verbose -Type GPOList' -Color RoyalBlue
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -FontSize 10pt -Text 'Steps above will generate above summary with more details allowing you to get up to date report and steps on how to fix it.'
|
||||
}
|
||||
Solution = {
|
||||
New-HTMLSection -Invisible {
|
||||
@@ -270,6 +312,7 @@
|
||||
New-ChartBar -Name 'Linked' -Value $Script:Reporting['GPOList']['Variables']['GPOLinked'], $Script:Reporting['GPOList']['Variables']['GPONotLinked']
|
||||
New-ChartBar -Name 'Not Empty' -Value $Script:Reporting['GPOList']['Variables']['GPONotEmpty'], $Script:Reporting['GPOList']['Variables']['GPOEmpty']
|
||||
New-ChartBar -Name 'Enabled' -Value $Script:Reporting['GPOList']['Variables']['GPOEnabled'], $Script:Reporting['GPOList']['Variables']['GPODisabled']
|
||||
New-ChartBar -Name 'Apply Permission' -Value $Script:Reporting['GPOList']['Variables']['ApplyPermissionYes'], $Script:Reporting['GPOList']['Variables']['ApplyPermissionNo']
|
||||
New-ChartBar -Name 'Valid' -Value $Script:Reporting['GPOList']['Variables']['GPOValid'], $Script:Reporting['GPOList']['Variables']['GPONotValid']
|
||||
New-ChartBar -Name 'Optimized (for speed)' -Value $Script:Reporting['GPOList']['Variables']['GPOOptimized'], $Script:Reporting['GPOList']['Variables']['GPONotOptimized']
|
||||
New-ChartBar -Name 'No problem' -Value $Script:Reporting['GPOList']['Variables']['GPONoProblem'], $Script:Reporting['GPOList']['Variables']['GPOProblem']
|
||||
@@ -289,6 +332,7 @@
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "Enabled", " - means GPO has at least one section enabled. If enabled is set to false that means both sections are disabled, and therefore GPO is not active. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "Optimized", " - means GPO section that is not in use is disabled. If section (user or computer) is enabled and there is no content, it's not optimized. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "Problem", " - means GPO has one or more section (user or computer) that is disabled, yet there is content in it. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "ApplyPermission", " - means GPO has no Apply Permission. This means there's no user/computer/group it's applicable to. "
|
||||
} -FontSize 10pt
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOList']['Data'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Exclude' -Value $true -BackgroundColor DeepSkyBlue -ComparisonType string -Row
|
||||
@@ -298,6 +342,7 @@
|
||||
New-HTMLTableCondition -Name 'Enabled' -Value $false -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Optimized' -Value $false -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Problem' -Value $true -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ApplyPermission' -Value $false -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerProblem' -Value $true -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'UserProblem' -Value $true -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerOptimized' -Value $false -BackgroundColor Salmon -ComparisonType string
|
||||
@@ -308,11 +353,12 @@
|
||||
New-HTMLTableCondition -Name 'Enabled' -Value $true -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Optimized' -Value $true -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Problem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ApplyPermission' -Value $true -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerProblem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'UserProblem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerOptimized' -Value $true -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'UserOptimized' -Value $true -BackgroundColor SpringGreen -TextTransform capitalize -ComparisonType string
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
@@ -369,11 +415,11 @@
|
||||
"You would do so using following approach "
|
||||
) -FontSize 10pt -FontWeight bold, normal
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Empty, Unlinked, Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor' {
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Empty, Unlinked, Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor' {
|
||||
Skip-GroupPolicy -Name 'TEST | Drive Mapping'
|
||||
Skip-GroupPolicy -Name 'Default Domain Policy'
|
||||
Skip-GroupPolicy -Name 'Default Domain Controllers Policy' -DomaiName 'JustOneDomain'
|
||||
}
|
||||
} -WhatIf
|
||||
}
|
||||
New-HTMLText -Text @(
|
||||
"Code above when executed will scan YourDomainYouHavePermissionsFor, find all empty, unlinked, disabled group policies, backup any GPO just before it's to be deleted to `$Env:UserProfile\Desktop\GPO. "
|
||||
@@ -382,11 +428,55 @@
|
||||
"Now go ahead and find what's there"
|
||||
)
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove GPOs that are EMPTY or UNLINKED' {
|
||||
New-HTMLWizardStep -Name 'Remove GPOs (Manual)' {
|
||||
New-HTMLText -Text @(
|
||||
"Please condider deleting GPOs manually if the amount of GPOs to delete is small enough. "
|
||||
"Deleting 1-5-30 GPOs manually on domain of 4000 GPOs will be much faster than doing it in controlled manner with automated steps mentioned on next steps. "
|
||||
"What can take 30 minutes manually, can take 8 hours using automated script, because of amount of checks required by the script over and over to delete a single GPO. "
|
||||
) -FontWeight normal, bold, normal, bold, normal, bold, normal, normal -Color Black, Red, Black, Red, Black
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove GPOs that are EMPTY' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command when executed removes every ",
|
||||
"EMPTY"
|
||||
" or "
|
||||
" Group Policy. Make sure when running it for the first time to run it with ",
|
||||
"WhatIf",
|
||||
" parameter as shown below to prevent accidental removal.",
|
||||
"Make sure to use BackupPath which will make sure that for each GPO that is about to be deleted a backup is made to folder on a desktop."
|
||||
"You can skip parameters related to backup if you did backup all GPOs prior to running remove command. "
|
||||
) -FontWeight normal, bold, normal, bold, normal, bold, normal, normal -Color Black, Red, Black, Red, Black
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be deleted matches expected data. "
|
||||
} -LineBreak
|
||||
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed deletes only first X empty GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur."
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly."
|
||||
"Please make sure to check if backup is made as well before going all in."
|
||||
}
|
||||
New-HTMLText -Text "If there's nothing else to be deleted, we can skip to next step step"
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove GPOs that are UNLINKED' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command when executed removes every ",
|
||||
"NOT LINKED"
|
||||
" Group Policy. Make sure when running it for the first time to run it with ",
|
||||
"WhatIf",
|
||||
@@ -395,33 +485,33 @@
|
||||
"You can skip parameters related to backup if you did backup all GPOs prior to running remove command. "
|
||||
) -FontWeight normal, bold, normal, bold, normal, bold, normal, normal -Color Black, Red, Black, Red, Black
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be deleted matches expected data. "
|
||||
} -LineBreak
|
||||
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed deletes only first X empty or unlinked GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur."
|
||||
"This command when executed deletes only first X unlinked GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur."
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly."
|
||||
"Please make sure to check if backup is made as well before going all in."
|
||||
}
|
||||
New-HTMLText -Text "If there's nothing else to be deleted on SYSVOL side, we can skip to next step step"
|
||||
New-HTMLText -Text "If there's nothing else to be deleted, we can skip to next step step"
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove GPOs that are DISABLED' {
|
||||
New-HTMLText -Text @(
|
||||
@@ -437,26 +527,26 @@
|
||||
""
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be deleted matches expected data. "
|
||||
} -LineBreak
|
||||
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
Remove-GPOZaurr -RequireDays 30 -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed deletes only first X disabled GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur. "
|
||||
@@ -465,6 +555,48 @@
|
||||
}
|
||||
New-HTMLText -Text "If there's nothing else to be deleted, we can skip to next step step."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove GPOs that do not APPLY' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command when executed removes every ",
|
||||
"NoApplyPermission"
|
||||
" Group Policy. Make sure when running it for the first time to run it with ",
|
||||
"WhatIf",
|
||||
" parameter as shown below to prevent accidental removal.",
|
||||
"Make sure to use BackupPath which will make sure that for each GPO that is about to be deleted a backup is made to folder on a desktop."
|
||||
"You can skip parameters related to backup if you did backup all GPOs prior to running remove command. "
|
||||
) -FontWeight normal, bold, normal, bold, normal, bold, normal, normal -Color Black, Red, Black, Red, Black
|
||||
New-HTMLText -TextBlock {
|
||||
""
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -RequireDays 30 -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -RequireDays 30 -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be deleted matches expected data. "
|
||||
} -LineBreak
|
||||
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -RequireDays 30 -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -RequireDays 30 -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed deletes only first X NoApplyPermission GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur. "
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly. "
|
||||
"Please make sure to check if backup is made as well before going all in."
|
||||
}
|
||||
New-HTMLText -Text "If there's nothing else to be deleted, we can skip to next step step."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Optimize GPOs (optional)' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command when executed disables user or computer section when there's no content for given type. ",
|
||||
@@ -510,7 +642,7 @@
|
||||
}
|
||||
New-HTMLText -Text "If there are no more problems to solve, GPOs to optimize in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,8 +123,8 @@
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartPie -Name 'Correct Owners' -Value $Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersAdministrators'] -Color LightGreen
|
||||
New-ChartPie -Name 'Incorrect Owners' -Value $Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersToFix'] -Color Crimson
|
||||
New-ChartPie -Name 'Correct Owners' -Value $Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersAdministrators'] -Color SpringGreen
|
||||
New-ChartPie -Name 'Incorrect Owners' -Value $Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersToFix'] -Color Salmon
|
||||
} -Title 'NetLogon Owners' -TitleAlignment center
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@
|
||||
New-HTMLTableCondition -Name 'OwnerType' -Value "WellKnownAdministrative" -BackgroundColor LightGreen -ComparisonType string -Operator eq
|
||||
New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor LightGreen -ComparisonType string -Operator eq
|
||||
New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
}
|
||||
} -SearchBuilder
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix NetLogon Owners ' {
|
||||
@@ -206,7 +206,7 @@
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
# }
|
||||
# New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
# }
|
||||
# } -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
# } -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
@@ -237,7 +237,7 @@
|
||||
New-HTMLTableCondition -Name 'Status' -Value "Review permission required" -BackgroundColor PaleGoldenrod -ComparisonType string -Operator eq
|
||||
New-HTMLTableCondition -Name 'Status' -Value "Removal permission required" -BackgroundColor Salmon -ComparisonType string -Operator eq -Row
|
||||
New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor LightGreen -ComparisonType string -Operator eq
|
||||
}
|
||||
} -SearchBuilder
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix NetLogon Permissions ' {
|
||||
@@ -272,6 +272,7 @@
|
||||
New-HTMLText -Text @(
|
||||
"In case of NETLOGON permissions it's impossible to tell what in a given moment for given domain should be automatically removed except for the very obvious ",
|
||||
"unknown ", 'permissions. Domain Admins have to make their assesment on and remove permissions from users or groups that '
|
||||
"they think do not belong. "
|
||||
) -FontWeight normal, bold, normal
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Verification report' {
|
||||
@@ -283,7 +284,7 @@
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
$GPOZaurrOrphans = [ordered] @{
|
||||
Name = 'Orphaned Group Policies'
|
||||
Name = 'Broken Group Policies'
|
||||
Enabled = $true
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
@@ -7,41 +7,52 @@
|
||||
Get-GPOZaurrBroken -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'] = @{}
|
||||
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'] = @{}
|
||||
foreach ($GPO in $Script:Reporting['GPOOrphans']['Data']) {
|
||||
if (-not $Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName] = 0
|
||||
$Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'] = @{}
|
||||
$Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssuePerDomain'] = @{}
|
||||
$Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssuePerDomain'] = @{}
|
||||
foreach ($GPO in $Script:Reporting['GPOBroken']['Data']) {
|
||||
if (-not $Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName] = 0
|
||||
if (-not $Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssuePerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssuePerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if ($GPO.Status -eq 'Not available in AD') {
|
||||
$Script:Reporting['GPOOrphans']['Variables']['NotAvailableInAD']++
|
||||
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeleted']++
|
||||
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]++
|
||||
$Script:Reporting['GPOBroken']['Variables']['NotAvailableInAD']++
|
||||
$Script:Reporting['GPOBroken']['Variables']['ToBeDeleted']++
|
||||
$Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]++
|
||||
} elseif ($GPO.Status -eq 'Not available on SYSVOL') {
|
||||
$Script:Reporting['GPOOrphans']['Variables']['NotAvailableOnSysvol']++
|
||||
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeleted']++
|
||||
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]++
|
||||
$Script:Reporting['GPOBroken']['Variables']['NotAvailableOnSysvol']++
|
||||
$Script:Reporting['GPOBroken']['Variables']['ToBeDeleted']++
|
||||
$Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]++
|
||||
} elseif ($GPO.Status -eq 'Permissions issue') {
|
||||
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue']++
|
||||
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName]++
|
||||
$Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssue']++
|
||||
$Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName]++
|
||||
} elseif ($GPO.Status -eq 'ObjectClass issue') {
|
||||
$Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssue']++
|
||||
$Script:Reporting['GPOBroken']['Variables']['ToBeDeleted']++
|
||||
$Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssuePerDomain'][$GPO.DomainName]++
|
||||
$Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOOrphans']['Variables']['ToBeDeleted'] -gt 0) {
|
||||
$Script:Reporting['GPOOrphans']['ActionRequired'] = $true
|
||||
if ($Script:Reporting['GPOBroken']['Variables']['ToBeDeleted'] -gt 0) {
|
||||
$Script:Reporting['GPOBroken']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOOrphans']['ActionRequired'] = $false
|
||||
$Script:Reporting['GPOBroken']['ActionRequired'] = $false
|
||||
}
|
||||
}
|
||||
Variables = @{
|
||||
NotAvailableInAD = 0
|
||||
NotAvailableOnSysvol = 0
|
||||
NotAvailablePermissionIssue = 0
|
||||
NotAvailablePermissionIssuePerDomain = $null
|
||||
ToBeDeleted = 0
|
||||
ToBeDeletedPerDomain = $null
|
||||
NotAvailableInAD = 0
|
||||
NotAvailableOnSysvol = 0
|
||||
NotAvailablePermissionIssue = 0
|
||||
NotAvailablePermissionIssuePerDomain = $null
|
||||
ToBeDeleted = 0
|
||||
ToBeDeletedPerDomain = $null
|
||||
NotAvailableObjectClassIssue = 0
|
||||
NotAvailableObjectClassIssuePerDomain = $null
|
||||
}
|
||||
Overview = {
|
||||
<#
|
||||
@@ -58,15 +69,15 @@
|
||||
}
|
||||
New-HTMLText -Text 'Following chart presents ', 'Broken / Orphaned Group Policies' -FontSize 10pt -FontWeight normal, bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies on SYSVOL, but no details in AD: ', $Script:Reporting['GPOOrphans']['Variables']['NotAvailableInAD'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies in AD, but no content on SYSVOL: ', $Script:Reporting['GPOOrphans']['Variables']['NotAvailableOnSysvol'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which couldn't be assed due to permissions issue: ", $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies on SYSVOL, but no details in AD: ', $Script:Reporting['GPOBroken']['Variables']['NotAvailableInAD'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies in AD, but no content on SYSVOL: ', $Script:Reporting['GPOBroken']['Variables']['NotAvailableOnSysvol'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which couldn't be assed due to permissions issue: ", $Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssue'] -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -FontSize 10pt -Text 'Those problems must be resolved before doing other clenaup activities.'
|
||||
New-HTMLChart {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Name 'Not in AD', 'Not on SYSVOL', 'Permissions Issue' -Color Crimson, LightCoral, IndianRed
|
||||
New-ChartBar -Name 'Orphans' -Value $Script:Reporting['GPOOrphans']['Variables']['NotAvailableInAD'], $Script:Reporting['GPOOrphans']['Variables']['NotAvailableOnSysvol'], $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue']
|
||||
New-ChartBar -Name 'Orphans' -Value $Script:Reporting['GPOBroken']['Variables']['NotAvailableInAD'], $Script:Reporting['GPOBroken']['Variables']['NotAvailableOnSysvol'], $Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssue']
|
||||
} -Title 'Broken / Orphaned Group Policies' -TitleAlignment center
|
||||
}
|
||||
#>
|
||||
@@ -85,14 +96,15 @@
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text 'Following problems were detected:' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies on SYSVOL, but no details in AD: ', $Script:Reporting['GPOOrphans']['Variables']['NotAvailableInAD'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies in AD, but no content on SYSVOL: ', $Script:Reporting['GPOOrphans']['Variables']['NotAvailableOnSysvol'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which couldn't be assed due to permissions issue: ", $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies on SYSVOL, but no details in AD: ', $Script:Reporting['GPOBroken']['Variables']['NotAvailableInAD'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies in AD, but no content on SYSVOL: ', $Script:Reporting['GPOBroken']['Variables']['NotAvailableOnSysvol'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Group Policies which exists, but have wrong ObjectClass: ', $Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssue'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which couldn't be assed due to permissions issue: ", $Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssue'] -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
foreach ($Domain in $Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
|
||||
foreach ($Domain in $Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOBroken']['Variables']['ToBeDeletedPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text "Please review output in table and follow the steps below table to get Active Directory Group Policies in healthy state." -FontSize 10pt
|
||||
@@ -100,25 +112,26 @@
|
||||
Solution = {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLPanel {
|
||||
& $Script:GPOConfiguration['GPOOrphans']['Summary']
|
||||
& $Script:GPOConfiguration['GPOBroken']['Summary']
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Name 'Not in AD', 'Not on SYSVOL', 'Permissions Issue' -Color Crimson, LightCoral, IndianRed
|
||||
New-ChartBar -Name 'Orphans' -Value $Script:Reporting['GPOOrphans']['Variables']['NotAvailableInAD'], $Script:Reporting['GPOOrphans']['Variables']['NotAvailableOnSysvol'], $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue']
|
||||
New-ChartLegend -Name 'Not in AD', 'Not on SYSVOL', 'ObjectClass Issue', 'Permissions Issue' -Color Crimson, LightCoral, MediumOrchid, IndianRed
|
||||
New-ChartBar -Name 'Broken' -Value $Script:Reporting['GPOBroken']['Variables']['NotAvailableInAD'], $Script:Reporting['GPOBroken']['Variables']['NotAvailableOnSysvol'], $Script:Reporting['GPOBroken']['Variables']['NotAvailableObjectClassIssue'], $Script:Reporting['GPOBroken']['Variables']['NotAvailablePermissionIssue']
|
||||
} -Title 'Broken / Orphaned Group Policies' -TitleAlignment center
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'Health State of Group Policies' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOOrphans']['Data'] -Filtering {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOBroken']['Data'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Status' -Value "Not available in AD" -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Status' -Value "Not available on SYSVOL" -BackgroundColor LightCoral -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Status' -Value "ObjectClass issue" -BackgroundColor MediumOrchid -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Status' -Value "Permissions issue" -BackgroundColor MediumVioletRed -ComparisonType string -Color White
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix - Not available on SYSVOL / Active Directory' {
|
||||
New-HTMLSection -Name 'Steps to fix - Not available on SYSVOL / Active Directory / ObjectClass issue' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLWizard {
|
||||
@@ -133,7 +146,7 @@
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding with removal. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoBefore.html -Verbose -Type GPOOrphans
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoBefore.html -Verbose -Type GPOBroken
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
@@ -243,23 +256,61 @@
|
||||
"If there's nothing else to be deleted on AD side, we can skip to next step step. "
|
||||
}
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Fix GPOs of wrong ObjectClass' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command when executed runs cleanup procedure that removes all GPOs which have ObjectClass of Container, rather than required groupPolicyContainer. "
|
||||
"Make sure when running it for the first time to run it with ",
|
||||
"WhatIf",
|
||||
" parameter as shown below to prevent accidental removal."
|
||||
'When run it will remove GPO metadata from AD, and any files/folders from SYSVOL.'
|
||||
) -FontWeight normal, normal, bold, normal -Color Black, Black, Red, Black
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrBroken -Type ObjectClass -WhatIf -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrBroken -Type ObjectClass -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor' -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be deleted matches expected data. "
|
||||
"Keep in mind that there is no backup for this as backup process doesn't see GPOs that are of wrong ObjectClass. "
|
||||
"Once you delete it, it's gone. "
|
||||
} -LineBreak
|
||||
New-HTMLText -Text 'Once happy with results please follow with command (this will start deletion process): ' -LineBreak -FontWeight bold
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrBroken -Type ObjectClass -LimitProcessing 2 -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrBroken -Type ObjectClass -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor' -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed deletes only first X broken GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur. "
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly. "
|
||||
"If there's nothing else to be deleted, we can skip to next step step. "
|
||||
}
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Verification report' {
|
||||
New-HTMLText -TextBlock {
|
||||
"Once cleanup task was executed properly, we need to verify that report now shows no problems."
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoAfter.html -Verbose -Type GPOOrphans
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoAfter.html -Verbose -Type GPOBroken
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOOrphans']['WarningsAndErrors']) {
|
||||
if ($Script:Reporting['GPOBroken']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOOrphans']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOBroken']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
}
|
||||
|
||||
@@ -77,18 +77,19 @@
|
||||
#>
|
||||
}
|
||||
Summary = {
|
||||
New-HTMLText -FontSize 10pt -TextBlock {
|
||||
"By default GPO creation is usually maintained by Domain Admins or Enterprise Admins. "
|
||||
"When GPO is created by member of Domain Admins or Enterprise Admins group the GPO Owner is set to Domain Admins. "
|
||||
"When GPO is created by member of Group Policy Creator Owners or other group has delegated rights to create a GPO the owner of said GPO is not Domain Admins group but is assigned to relevant user. "
|
||||
"GPO Owners should be Domain Admins or Enterprise Admins to prevent abuse. If that isn't so it means owner is able to fully control GPO and potentially change it's settings in uncontrolled way. "
|
||||
"While at the moment of creation of new GPO it's not a problem, in long term it's possible such person may no longer be admin, yet keep their rights over GPO. "
|
||||
}
|
||||
New-HTMLText -FontSize 10pt -TextBlock {
|
||||
"As you're aware Group Policies are stored in 2 places. In Active Directory (metadata) and SYSVOL (settings). This means that there are 2 places where GPO Owners exists. "
|
||||
"This also means that for multiple reasons AD and SYSVOL can be out of sync when it comes to their permissions which can lead to uncontrolled ability to modify them. "
|
||||
"Ownership in Active Directory and Ownership of SYSVOL for said GPO are required to be the same. "
|
||||
}
|
||||
New-HTMLText -FontSize 10pt -Text @(
|
||||
"By default, GPO creation is usually maintained by Domain Admins or Enterprise Admins. "
|
||||
"When GPO is created by Domain Admins or Enterprise Admins group members, the GPO Owner is set to Domain Admins. "
|
||||
"When GPO is created by a member of Group Policy Creator Owners or other group has delegated rights to create a GPO, "
|
||||
"the owner of said GPO is not Domain Admins group but is assigned to the relevant user. "
|
||||
"GPO Owners should be Domain Admins or Enterprise Admins to prevent abuse. "
|
||||
"If that isn't so, it means the owner can fully control GPO and potentially change its settings in an uncontrolled way. "
|
||||
"While at the moment of creation of new GPO, it's not a problem, in the long term, it's possible such a person may no longer be admin, yet keep their rights over GPO. "
|
||||
"As your aware, Group Policies are stored in 2 places. In Active Directory (metadata) and SYSVOL (settings). "
|
||||
"This means that there are 2 places where GPO Owners exists. "
|
||||
"This also means that for multiple reasons, AD and SYSVOL can be out of sync when it comes to their permissions, which can lead to uncontrolled ability to modify them. "
|
||||
"Ownership in Active Directory and Ownership of SYSVOL for said GPO is required to be the same."
|
||||
)
|
||||
New-HTMLText -Text "Here's a short summary of ", "Group Policy Owners", ": " -FontSize 10pt -FontWeight normal, bold, normal
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Administrative Owners: ', $Script:Reporting['GPOOwners']['Variables']['IsAdministrative'] -FontWeight normal, bold
|
||||
@@ -133,7 +134,7 @@
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOOwners']['Data'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'IsOwnerConsistent' -Value $false -BackgroundColor Salmon -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'IsOwnerAdministrative' -Value $false -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
} -PagingOptions 10, 20, 30, 40, 50 -SearchBuilder
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix Group Policy Owners' {
|
||||
@@ -217,7 +218,7 @@
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPassword']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
}
|
||||
} -SearchBuilder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
$GPOZaurrPermissions = [ordered] @{
|
||||
Name = 'Group Policy Permissions'
|
||||
Enabled = $true
|
||||
Action = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrPermission -Type All -IncludePermissionType GpoEditDeleteModifySecurity, GpoEdit, GpoCustom -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
|
||||
}
|
||||
Variables = @{
|
||||
|
||||
}
|
||||
Overview = {
|
||||
|
||||
}
|
||||
Solution = {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['Data'] -Filtering
|
||||
if ($Script:Reporting['GPOPermissions']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
Permissions = Get-GPOZaurrPermission -Type Administrative -IncludePermissionType GpoEditDeleteModifySecurity -ReturnSecurityWhenNoData -IncludeGPOObject -ReturnSingleObject -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
$Object['PermissionsPerRow'] = $Object['Permissions'] | ForEach-Object { $_ }
|
||||
$Object['PermissionsAnalysis'] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
$Object
|
||||
}
|
||||
Processing = {
|
||||
@@ -33,6 +34,8 @@
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFix']++
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFixPerDomain'][$GPO[0].DomainName]++
|
||||
}
|
||||
# lets create table and add it there
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['Data'].'PermissionsAnalysis'.Add($Analysis)
|
||||
}
|
||||
if ($Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFix'] -gt 0) {
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['ActionRequired'] = $true
|
||||
@@ -82,16 +85,21 @@
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Name 'Yes', 'No' -Color LightGreen, Salmon
|
||||
New-ChartLegend -Name 'Yes', 'No' -Color SpringGreen, Salmon
|
||||
New-ChartBar -Name 'Administrative Users Present' -Value $Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillNotTouch'], $Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFix']
|
||||
#New-ChartBar -Name 'Accessible Group Policies' -Value $Script:Reporting['GPOPermissionsAdministrative']['Variables']['Read'], $Script:Reporting['GPOPermissionsAdministrative']['Variables']['CouldNotRead']
|
||||
} -Title 'Group Policy Permissions' -TitleAlignment center
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policy Administrative Users Analysis' {
|
||||
New-HTMLSection -Name 'Group Policy Administrative Users Permissions Summary' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsAdministrative']['Data'].PermissionsPerRow -Filtering {
|
||||
New-HTMLTableCondition -Name 'Permission' -Value '' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 7, 15, 30, 45, 60
|
||||
} -PagingOptions 7, 15, 30, 45, 60 -SearchBuilder
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policy Administrative Users Analysis' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsAdministrative']['Data'].PermissionsAnalysis -Filtering {
|
||||
# New-HTMLTableCondition -Name 'Permission' -Value '' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 7, 15, 30, 45, 60 -SearchBuilder
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix Group Policy Administrative Users' {
|
||||
@@ -184,7 +192,7 @@
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,583 @@
|
||||
$GPOZaurrPermissionsAnalysis = [ordered] @{
|
||||
Name = 'Group Policy Permissions Analysis'
|
||||
Enabled = $true
|
||||
Action = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
$Object = [ordered] @{
|
||||
Permissions = Get-GPOZaurrPermission -ReturnSecurityWhenNoData -IncludeGPOObject -ReturnSingleObject -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
$Object['PermissionsPerRow'] = $Object['Permissions'] | ForEach-Object { $_ }
|
||||
$Object['PermissionsAnalysis'] = Get-GPOZaurrPermissionAnalysis -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -Permissions $Object.Permissions
|
||||
$Object['PermissionsIssues'] = Get-GPOZaurrPermissionIssue -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
$Object
|
||||
}
|
||||
Processing = {
|
||||
# Create Per Domain Variables
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrativePerDomain'] = @{}
|
||||
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAuthenticatedUsersPerDomain'] = @{}
|
||||
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystemPerDomain'] = @{}
|
||||
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknownPerDomain'] = @{}
|
||||
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotFixPerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixPerDomain'] = @{}
|
||||
|
||||
$Script:Reporting['GPOPermissions']['Variables']['ReadPerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissions']['Variables']['TotalPerDomain'] = @{}
|
||||
|
||||
foreach ($GPO in $Script:Reporting['GPOPermissions']['Data'].PermissionsIssues) {
|
||||
# Create Per Domain Variables
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['ReadPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['ReadPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['TotalPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['TotalPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if ($GPO.PermissionIssue) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['CouldNotRead']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'][$GPO.DomainName]++
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['Read']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['ReadPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
$Script:Reporting['GPOPermissions']['Variables']['Total']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['TotalPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
foreach ($GPO in $Script:Reporting['GPOPermissions']['Data'].PermissionsAnalysis) {
|
||||
# Create Per Domain Variables
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillFixPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillNotFixPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotFixPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrativePerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrativePerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystemPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystemPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknownPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknownPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
|
||||
# Checks
|
||||
if ($GPO.Administrative -eq $true) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrative']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrativePerDomain'][$GPO.DomainName]++
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrative']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
|
||||
if ($GPO.AuthenticatedUsers -eq $true) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAuthenticatedUsers']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAuthenticatedUsersPerDomain'][$GPO.DomainName]++
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsers']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
|
||||
if ($GPO.System -eq $true) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystem']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystemPerDomain'][$GPO.DomainName]++
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixSystem']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
|
||||
if ($GPO.Unknown -eq $false) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknown']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknownPerDomain'][$GPO.DomainName]++
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixUnknown']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
|
||||
if ($GPO.Status -eq $false) {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFix']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillFixPerDomain'][$GPO.DomainName]++
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotFix']++
|
||||
$Script:Reporting['GPOPermissions']['Variables']['WillNotFixPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOPermissions']['Variables']['WillFix'] -gt 0 -or $Script:Reporting['GPOPermissions']['Variables']['CouldNotRead'] -gt 0) {
|
||||
$Script:Reporting['GPOPermissions']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissions']['ActionRequired'] = $false
|
||||
}
|
||||
}
|
||||
Variables = @{
|
||||
# Issues / Couldnt read report
|
||||
Read = 0
|
||||
ReadPerDomain = $null
|
||||
CouldNotRead = 0
|
||||
CouldNotReadPerDomain = $null
|
||||
TotalPerDomain = $null
|
||||
Total = 0
|
||||
# Permissions analysis
|
||||
WillFix = 0
|
||||
WillNotFix = 0
|
||||
WillFixAdministrative = 0
|
||||
WillNotTouchAdministrative = 0
|
||||
WillFixUnknown = 0
|
||||
WillNotTouchUnknown = 0
|
||||
WillNotTouchSystem = 0
|
||||
WillFixSystem = 0
|
||||
WillNotTouchAuthenticatedUsers = 0
|
||||
WillFixAuthenticatedUsers = 0
|
||||
WillNotTouchAuthenticatedUsersPerDomain = $null
|
||||
WillFixAuthenticatedUsersPerDomain = $null
|
||||
WillNotTouchSystemPerDomain = $null
|
||||
WillFixSystemPerDomain = $null
|
||||
WillFixAdministrativePerDomain = $null
|
||||
WillNotTouchAdministrativePerDomain = $null
|
||||
WillNotFixPerDomain = $null
|
||||
WillFixPerDomain = $null
|
||||
WillFixUnknownPerDomain = $null
|
||||
WillNotTouchUnknownPerDomain = $null
|
||||
}
|
||||
Summary = {
|
||||
New-HTMLText -FontSize 10pt -Text "When GPO is created it gets a handful of standard permissions. Those are:"
|
||||
New-HTMLList {
|
||||
New-HTMLListItem -Text "NT AUTHORITY\Authenticated Users with GpoApply permissions"
|
||||
New-HTMLListItem -Text "Domain Admins and Enterprise Admins with Edit/Delete/Modify permissions"
|
||||
New-HTMLListItem -Text "SYSTEM account with Edit/Delete/Modify permissions"
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -FontSize 10pt -Text "But then IT people change those permissions to their own needs. While most changes make sense and are required to be able to target proper groups of people, some changes are not required or even bad. "
|
||||
|
||||
New-HTMLText -Text "First problem relates to NT AUTHORITY\Authenticated Users" -FontSize 10pt -FontWeight bold -TextDecoration underline -Alignment center
|
||||
|
||||
New-HTMLText -FontSize 10pt -TextBlock {
|
||||
"When GPO is created one of the permissions that are required for proper functioning of Group Policies is NT AUTHORITY\Authenticated Users. "
|
||||
"Some Administrators don't follow best practices and trying to remove GpoApply permission, remove also GpoRead permission from a GPO which can have consequences. "
|
||||
"On June 14th, 2016 Microsoft released [HotFix](https://support.microsoft.com/en-gb/help/3159398/ms16-072-description-of-the-security-update-for-group-policy-june-14-2) that requires Authenticated Users to be present on all Group Policies to function properly. "
|
||||
"MS16-072 changes the security context with which user group policies are retrieved. "
|
||||
"This by-design behavior change protects customers’ computers from a security vulnerability. "
|
||||
}
|
||||
New-HTMLList {
|
||||
New-HTMLListItem -Text "Before MS16-072 is installed, user group policies were retrieved by using the user’s security context. "
|
||||
New-HTMLListItem -Text "After MS16-072 is installed, user group policies are retrieved by using the computer's security context."
|
||||
} -FontSize 10pt
|
||||
|
||||
New-HTMLText -FontSize 10pt -Text @(
|
||||
"Unfortunetly it's not as simple as it sounds. While checking for permissions mostly works fine, it's possible a Group Policy has totally removed account permissions from being able to asses any of it. ",
|
||||
"The account we're using "
|
||||
"$($Env:USERDOMAIN)\$($Env:USERNAME.ToUpper())",
|
||||
" may simply not have enough permisions to properly asses permissions for a GPO. "
|
||||
"Therefore we're using dual assesment for this situation, where first assesment is checking for GPO visibility or lack of it, and second assesment is checking for direct permissions assignement. "
|
||||
"We just were able to detect the problem, but hopefully higher level account (Domain Admin) should be able to provide full assesment. "
|
||||
) -FontWeight normal, normal, bold, normal -Color None, None, BlueDiamond, none, none
|
||||
|
||||
New-HTMLText -FontSize 10pt -Text "First assesment results: " -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text "Group Policies couldn't read at all: ", $Script:Reporting['GPOPermissions']['Variables']['CouldNotRead'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies with permissions allowing read: ", $Script:Reporting['GPOPermissions']['Variables']['Read'] -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
foreach ($Domain in $Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text @(
|
||||
"$Domain requires ",
|
||||
$Script:Reporting['GPOPermissions']['Variables']['CouldNotReadPerDomain'][$Domain],
|
||||
" changes out of ",
|
||||
$Script:Reporting['GPOPermissions']['Variables']['TotalPerDomain'][$Domain],
|
||||
"."
|
||||
) -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
|
||||
New-HTMLText -FontSize 10pt -Text "Second Assesment results " -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies requiring Authenticated Users with GpoRead permission: ', $Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsers'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which don't require changes: ", $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAuthenticatedUsers'] -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
foreach ($Domain in $Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsersPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text "Second problem relates to Domain Admins and Enterprise Admins" -FontSize 10pt -FontWeight bold -TextDecoration underline -Alignment center
|
||||
New-HTMLText -FontSize 10pt -TextBlock {
|
||||
"When GPO is created by default it gets Domain Admins and Enterprise Admins with Edit/Delete/Modify Security permissions. "
|
||||
"For some reason, some Administrators remove those permissions or modify them when they shouldn't touch those at all. "
|
||||
"Since having Edit/Delete/Modify Security permissions doesn't affect GPOApply permissions there's no reason to remove Domain Admins or Enterprise Admins from permissions, or limit their rights. "
|
||||
"Domain Admins and Enterprise Admins have to have either GPOEditModify permissions or at the very least GPOCustom. "
|
||||
"When GPOCustom is set it usually means there's a mix of Allow and Deny permission in place (for example deny GPOApply). "
|
||||
"In such case we're assuming you know what you're doing. However it's always possible to review those permissions, as those are marked in the table for review. "
|
||||
} -LineBreak
|
||||
|
||||
New-HTMLText -FontSize 10pt -Text "Assesment results " -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies requiring Administrative permission fix: ', $Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrative'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which don't require changes: ", $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrative'] -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
foreach ($Domain in $Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrativePerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
|
||||
New-HTMLText -Text "Third problem relates to SYSTEM account" -FontSize 10pt -FontWeight bold -TextDecoration underline -Alignment center
|
||||
New-HTMLText -FontSize 10pt -TextBlock {
|
||||
"When GPO is created by default it gets SYSTEM account with Edit/Delete/Modify Security permissions. "
|
||||
"For some reason, some Administrators remove those permissions or modify them when they shouldn't touch those at all. "
|
||||
"Since having Edit/Delete/Modify Security permissions doesn't affect GPOApply permissions there's no reason to remove SYSTEM from permissions, or limit their rights. "
|
||||
} -LineBreak
|
||||
|
||||
New-HTMLText -FontSize 10pt -Text "Assesment results " -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies requiring SYSTEM permission fix: ', $Script:Reporting['GPOPermissions']['Variables']['WillFixSystem'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which don't require changes: ", $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystem'] -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
foreach ($Domain in $Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOPermissions']['Variables']['WillFixSystemPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
|
||||
New-HTMLText -Text "Fourth problem relates to UNKNOWN SID" -FontSize 10pt -FontWeight bold -TextDecoration underline -Alignment center
|
||||
New-HTMLText -FontSize 10pt -TextBlock {
|
||||
"Sometimes groups or users are deleted in Active Directory and unfortunetly their permissions are not cleaned automatically. "
|
||||
"Those are left in-place and stay there forever until removed. "
|
||||
} -LineBreak
|
||||
|
||||
New-HTMLText -FontSize 10pt -Text "Assesment results " -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies requiring Unknown permission removal: ', $Script:Reporting['GPOPermissions']['Variables']['WillFixUnknown'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which don't require changes: ", $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknown'] -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
foreach ($Domain in $Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOPermissions']['Variables']['WillFixUnknownPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt -LineBreak
|
||||
# Just in case report is too big and the full file is not attached
|
||||
New-HTMLText -FontSize 10pt -Text "To generate up to date report please execute: " -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Install-Module GPOZaurr -Force', ' or ', ' install module manually.' -Color RoyalBlue, None, None
|
||||
New-HTMLListItem -Text 'Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOPermissionsBefore.html -Verbose -Type GPOPermissions' -Color RoyalBlue
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -FontSize 10pt -Text 'Steps above will generate above summary with more details allowing you to get up to date report and steps on how to fix it.'
|
||||
}
|
||||
Solution = {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLPanel {
|
||||
& $Script:GPOConfiguration['GPOPermissions']['Summary']
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Name 'Yes', 'No' -Color SpringGreen, Salmon
|
||||
New-ChartBar -Name 'Visible Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['Read'], $Script:Reporting['GPOPermissions']['Variables']['CouldNotRead']
|
||||
New-ChartBar -Name 'Overall Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['WillNotFix'], $Script:Reporting['GPOPermissions']['Variables']['WillFix']
|
||||
New-ChartBar -Name 'Administrative Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrative'], $Script:Reporting['GPOPermissions']['Variables']['WillFixAdministrative']
|
||||
New-ChartBar -Name 'Authenticated Users Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchAdministrative'], $Script:Reporting['GPOPermissions']['Variables']['WillFixAuthenticatedUsers']
|
||||
New-ChartBar -Name 'System Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchSystem'], $Script:Reporting['GPOPermissions']['Variables']['WillFixSystem']
|
||||
New-ChartBar -Name 'Unknown Permissions' -Value $Script:Reporting['GPOPermissions']['Variables']['WillNotTouchUnknown'], $Script:Reporting['GPOPermissions']['Variables']['WillFixUnknown']
|
||||
} -Title 'Group Policy Permissions' -TitleAlignment center
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policy Visibility Analysis' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['Data'].PermissionsIssues -Filtering {
|
||||
New-HTMLTableCondition -Name 'PermissionIssue' -Value $true -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 7, 15, 30, 45, 60 -DefaultSortColumn PermissionIssue -DefaultSortOrder Descending -SearchBuilder
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policy Permissions Analysis' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLText -Text 'Explanation to table columns:' -FontSize 10pt
|
||||
New-HTMLList {
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "Status", " - means GPO has at least one problem with permissions. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "Administrative", " - means GPO has problem with either Domain Admins or Enterprise Admins not having proper permissions. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "AuthenticatedUsers", " - means GPO has Authenticated Users missing either as GPOApply or GPORead. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "System", " - means GPO has SYSTEM permission missing or lacking proper permissions. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "DomainAdmins", " - means GPO has Domain Admins missing or having wrong permissions. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "EnterpriseAdmins", " - means GPO has Enterprise Admins missing or having wrong permissions. "
|
||||
} -FontSize 10pt
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['Data'].PermissionsAnalysis -Filtering {
|
||||
New-HTMLTableCondition -Name 'Status' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Administrative' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'AuthenticatedUsers' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'System' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Unknown' -Value 'False' -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'DomainAdmins' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'EnterpriseAdmins' -Value 'True' -BackgroundColor SpringGreen -ComparisonType string
|
||||
|
||||
# Mark as warning
|
||||
New-HTMLTableCondition -Name 'DomainAdminsPermission' -Value 'GpoCustom' -BackgroundColor Moccasin -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'EnterpriseAdminsPermission' -Value 'GpoCustom' -BackgroundColor Moccasin -ComparisonType string
|
||||
# Reverse
|
||||
New-HTMLTableCondition -Name 'Status' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
New-HTMLTableCondition -Name 'Administrative' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
New-HTMLTableCondition -Name 'AuthenticatedUsers' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
New-HTMLTableCondition -Name 'System' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
New-HTMLTableCondition -Name 'Unknown' -Value 'False' -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
New-HTMLTableCondition -Name 'DomainAdmins' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
New-HTMLTableCondition -Name 'EnterpriseAdmins' -Value 'True' -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
|
||||
New-TableEvent -TableID 'GPOPermissionsAll' -SourceColumnName 'GUID' -TargetColumnID 1 # TargetColumnID 1 eq GUID on the other table
|
||||
} -PagingOptions 7, 15, 30, 45, 60 -SearchBuilder
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'All Permissions' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['Data'].PermissionsPerRow -Filtering {
|
||||
New-HTMLTableHeader -Names 'PrincipalNetBiosName', 'PrincipalDistinguishedName', 'PrincipalDomainName', 'PrincipalName', 'PrincipalSid', 'PrincipalSidType' -Title 'Account Information'
|
||||
New-HTMLTableCondition -Name 'Permission' -Value 'GpoEditDeleteModifySecurity' -BackgroundColor HotPink -ComparisonType string -Operator eq
|
||||
New-HTMLTableCondition -Name 'Permission' -Value 'GpoCustom' -BackgroundColor Moccasin -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Permission' -Value 'GpoApply' -BackgroundColor Orange -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Permission' -Value 'GpoRead' -BackgroundColor MediumSpringGreen -ComparisonType string -Operator eq
|
||||
New-HTMLTableCondition -Name 'PrincipalSidType' -Value 'Unknown' -BackgroundColor Salmon -ComparisonType string -Operator eq
|
||||
} -PagingOptions 7, 15, 30, 45, 60 -DataTableID 'GPOPermissionsAll' -SearchBuilder
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix Group Policy Administrative Users' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLWizard {
|
||||
New-HTMLWizardStep -Name 'Prepare environment' {
|
||||
New-HTMLText -Text "To be able to execute actions in automated way please install required modules. Those modules will be installed straight from Microsoft PowerShell Gallery."
|
||||
New-HTMLCodeBlock -Code {
|
||||
Install-Module GPOZaurr -Force
|
||||
Import-Module GPOZaurr -Force
|
||||
} -Style powershell
|
||||
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding with fixing Group Policy Authenticated Users. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOPermissionsBefore.html -Verbose -Type GPOPermissions
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment. "
|
||||
"GPOs with problems will be those not having any value for Permission/PermissionType columns. "
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
# This gets all permissions
|
||||
$AllPermissions = Get-GPOZaurrPermission
|
||||
$AllPermissions | Format-Table
|
||||
|
||||
# this analyses permissions
|
||||
$PermissionsAnalysis = Get-GPOZaurrPermissionAnalysis
|
||||
$PermissionsAnalysis | Format-Table
|
||||
}
|
||||
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Make a backup (optional)' {
|
||||
New-HTMLText -TextBlock {
|
||||
"The process of fixing GPO Permissions does NOT touch GPO content. It simply adds permissionss on AD and SYSVOL at the same time for given GPO. "
|
||||
"However, it's always good to have a backup before executing changes that may impact Active Directory. "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOSummary = Backup-GPOZaurr -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -Type All
|
||||
$GPOSummary | Format-Table # only if you want to display output of backup
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Above command when executed will make a backup to Desktop, create GPO folder and within it it will put all those GPOs. "
|
||||
}
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Add Authenticated Users permissions' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command will find any GPO which doesn't have Authenticated User as GpoRead or GpoApply and will add it as GpoRead. ",
|
||||
"This change doesn't change GpoApply permission, therefore it won't change to whom the GPO applies to. ",
|
||||
"It ensures that COMPUTERS can read GPO properly to be able to Apply it. ",
|
||||
"Make sure when running it for the first time to run it with ",
|
||||
"WhatIf",
|
||||
" parameter as shown below to prevent accidental adding of permissions."
|
||||
) -FontWeight normal, normal, normal, normal, bold, normal -Color Black, Black, Black, Black, Red, Black
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -All -WhatIf -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -All -WhatIf -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be changed matches expected data."
|
||||
} -LineBreak
|
||||
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -All -Verbose -LimitProcessing 2
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -All -Verbose -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed adds Authenticated Users (GpoRead permission) only on first X non-compliant Group Policies. "
|
||||
"Use LimitProcessing parameter to prevent mass change and increase the counter when no errors occur. "
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. "
|
||||
"In case of any issues please review and action accordingly."
|
||||
}
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Add Administrative Groups permissions' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command will find any GPO which doesn't have Domain Admins and Enterprise Admins added with GpoEditDeleteModifySecurity and will add it as GpoEditDeleteModifySecurity. ",
|
||||
"This change doesn't change GpoApply permission, therefore it won't change to whom the GPO applies to. ",
|
||||
"It ensures that Domain Admins and Enterprise Admins can manage GPO. ",
|
||||
"Make sure when running it for the first time to run it with ",
|
||||
"WhatIf",
|
||||
" parameter as shown below to prevent accidental adding of permissions."
|
||||
) -FontWeight normal, normal, normal, normal, bold, normal -Color Black, Black, Black, Black, Red, Black
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -All -WhatIf -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -All -WhatIf -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be changed matches expected data."
|
||||
} -LineBreak
|
||||
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -All -Verbose -LimitProcessing 2
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -All -Verbose -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed adds Enterprise Admins or/and Domain Admins (GpoEditDeleteModifySecurity permission) only on first X non-compliant Group Policies. "
|
||||
"Use LimitProcessing parameter to prevent mass change and increase the counter when no errors occur. "
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. "
|
||||
"In case of any issues please review and action accordingly. "
|
||||
}
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Add SYSTEM permissions' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command will find any GPO which doesn't have SYSTEM account added with GpoEditDeleteModifySecurity and will add it as GpoEditDeleteModifySecurity. ",
|
||||
"This change doesn't change GpoApply permission, therefore it won't change to whom the GPO applies to. ",
|
||||
"It ensures that SYSTEM can manage GPO. ",
|
||||
"Make sure when running it for the first time to run it with ",
|
||||
"WhatIf",
|
||||
" parameter as shown below to prevent accidental adding of permissions."
|
||||
) -FontWeight normal, normal, normal, normal, bold, normal -Color Black, Black, Black, Black, Red, Black
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type WellKnownAdministrative -PermissionType GpoEditDeleteModifySecurity -All -WhatIf -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type WellKnownAdministrative -PermissionType GpoEditDeleteModifySecurity -All -WhatIf -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be changed matches expected data."
|
||||
} -LineBreak
|
||||
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type WellKnownAdministrative -PermissionType GpoEditDeleteModifySecurity -All -Verbose -LimitProcessing 2
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Add-GPOZaurrPermission -Type WellKnownAdministrative -PermissionType GpoEditDeleteModifySecurity -All -Verbose -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed adds SYSTEM account (GpoEditDeleteModifySecurity permission) only on first X non-compliant Group Policies. "
|
||||
"Use LimitProcessing parameter to prevent mass change and increase the counter when no errors occur. "
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. "
|
||||
"In case of any issues please review and action accordingly. "
|
||||
}
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove UNKNOWN permissions' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command will find any GPO which has an unknown SID and will remove it. ",
|
||||
"This change doesn't change any other permissions. ",
|
||||
"It ensures that GPOs have no unknown permissions present. ",
|
||||
"Make sure when running it for the first time to run it with ",
|
||||
"WhatIf",
|
||||
" parameter as shown below to prevent accidental adding of permissions."
|
||||
) -FontWeight normal, normal, normal, normal, bold, normal -Color Black, Black, Black, Black, Red, Black
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrPermission -Verbose -Type Unknown -WhatIf
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrPermission -Verbose -Type Unknown -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be changed matches expected data."
|
||||
} -LineBreak
|
||||
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 2
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed removes only first X unknwon permissions from Group Policies. "
|
||||
"Use LimitProcessing parameter to prevent mass change and increase the counter when no errors occur. "
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. "
|
||||
"In case of any issues please review and action accordingly. "
|
||||
}
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Verification report' {
|
||||
New-HTMLText -TextBlock {
|
||||
"Once cleanup task was executed properly, we need to verify that report now shows no problems."
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOPermissionsAfter.html -Verbose -Type GPOPermissions
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOPermissions']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissions']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
Execute = {
|
||||
[ordered] @{
|
||||
Permissions = Get-GPOZaurrPermission -Type AuthenticatedUsers -ReturnSecurityWhenNoData -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
Issues = Get-GPOZaurrPermissionIssue
|
||||
Issues = Get-GPOZaurrPermissionIssue -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
}
|
||||
Processing = {
|
||||
@@ -93,7 +93,7 @@
|
||||
} -FontStyle italic -FontSize 10pt -FontWeight bold -LineBreak
|
||||
New-HTMLText -FontSize 10pt -Text @(
|
||||
"There are two parts to this assesment. Reading all Group Policies Permissions that account ",
|
||||
$($Env:USERNAME.ToUpper()),
|
||||
"$($Env:USERDOMAIN)\$($Env:USERNAME.ToUpper())",
|
||||
" has permissions to read and provide detailed assesment about permissions. ",
|
||||
"Second assesment checks for permissions that this account is not able to read at all, and therefore it has no visibility about permissions set on it. "
|
||||
"We just were able to detect the problem, but hopefully higher level account (Domain Admin) should be able to provide full assesment. "
|
||||
@@ -142,7 +142,7 @@
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Name 'Yes', 'No' -Color LightGreen, Salmon
|
||||
New-ChartLegend -Name 'Yes', 'No' -Color SpringGreen, Salmon
|
||||
New-ChartBar -Name 'Authenticated Users Available' -Value $Script:Reporting['GPOPermissionsRead']['Variables']['WillNotTouch'], $Script:Reporting['GPOPermissionsRead']['Variables']['WillFix']
|
||||
New-ChartBar -Name 'Accessible Group Policies' -Value $Script:Reporting['GPOPermissionsRead']['Variables']['Read'], $Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotRead']
|
||||
} -Title 'Group Policy Permissions' -TitleAlignment center
|
||||
@@ -151,12 +151,12 @@
|
||||
New-HTMLSection -Name 'Group Policy Authenticated Users Analysis' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsRead']['Data'].Permissions -Filtering {
|
||||
New-HTMLTableCondition -Name 'Permission' -Value '' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 7, 15, 30, 45, 60
|
||||
} -PagingOptions 7, 15, 30, 45, 60 -SearchBuilder
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policy Issues Assesment' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsRead']['Data'].Issues -Filtering {
|
||||
New-HTMLTableCondition -Name 'PermissionIssue' -Value $true -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 7, 15, 30, 45, 60 -DefaultSortColumn PermissionIssue -DefaultSortOrder Descending
|
||||
} -PagingOptions 7, 15, 30, 45, 60 -DefaultSortColumn PermissionIssue -DefaultSortOrder Descending -SearchBuilder
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix Group Policy Authenticated Users' {
|
||||
@@ -249,7 +249,7 @@
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsRoot']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
}
|
||||
} -SearchBuilder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
New-HTMLSection -Name 'Group Policy Unknown Permissions Analysis' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsUnknown']['Data'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Permission' -Value '' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 7, 15, 30, 45, 60
|
||||
} -PagingOptions 7, 15, 30, 45, 60 -SearchBuilder
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix Group Policy Unknown Permissions' {
|
||||
@@ -164,7 +164,7 @@
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
function New-GPOZaurrReportConsole {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[System.Collections.IDictionary] $Results
|
||||
[System.Collections.IDictionary] $Results,
|
||||
[string] $ComputerName
|
||||
)
|
||||
Begin {
|
||||
$GPODeny = @{
|
||||
@@ -20,26 +21,40 @@
|
||||
$UserWhereApplied = ($Results.UserResults.GroupPolicies | Sort-Object -Property Name).Where( { $_.Status -eq 'Applied' }, 'split')
|
||||
}
|
||||
Process {
|
||||
Write-Color -Text 'Computer Settings' -Color White -LinesBefore 1
|
||||
Write-Color -Text '[>] Last time Group Policy was applied: ', $Results.ComputerResults.Summary.ReadTime @WriteSummary
|
||||
Write-Color -Text '[>] Computer Name: ', $Results.ComputerResults.Summary.ComputerName @WriteSummary
|
||||
Write-Color -Text '[>] Domain Name: ', $Results.ComputerResults.Summary.DomainName @WriteSummary
|
||||
Write-Color -Text '[>] Organizational Unit: ', $Results.ComputerResults.Summary.OrganizationalUnit @WriteSummary
|
||||
Write-Color -Text '[>] Site: ', $Results.ComputerResults.Summary.Site @WriteSummary
|
||||
Write-Color -Text '[>] GPO Types: ', ($Results.ComputerResults.Summary.GPOTypes -replace [System.Environment]::NewLine, ', ') @WriteSummary
|
||||
Write-Color -Text '[>] Slow link: ', ($Results.ComputerResults.Summary.SlowLink) @WriteSummary
|
||||
if ($Results.ComputerResults) {
|
||||
Write-Color -Text 'Computer Settings' -Color Yellow -LinesBefore 1
|
||||
Write-Color -Text '[>] Last time Group Policy was applied: ', $Results.ComputerResults.Summary.ReadTime @WriteSummary
|
||||
Write-Color -Text '[>] Computer Name: ', $Results.ComputerResults.Summary.ComputerName @WriteSummary
|
||||
Write-Color -Text '[>] Domain Name: ', $Results.ComputerResults.Summary.DomainName @WriteSummary
|
||||
Write-Color -Text '[>] Organizational Unit: ', $Results.ComputerResults.Summary.OrganizationalUnit @WriteSummary
|
||||
Write-Color -Text '[>] Site: ', $Results.ComputerResults.Summary.Site @WriteSummary
|
||||
Write-Color -Text '[>] GPO Types: ', ($Results.ComputerResults.Summary.GPOTypes -replace [System.Environment]::NewLine, ', ') @WriteSummary
|
||||
Write-Color -Text '[>] Slow link: ', ($Results.ComputerResults.Summary.SlowLink) @WriteSummary
|
||||
|
||||
Write-Color -Text 'Applied Group Policy Objects' -StartSpaces 3 -LinesBefore 1
|
||||
foreach ($GPO in $ComputerWhereApplied[0]) {
|
||||
Write-Color -Text '[+] [', $GPO.DomainName, '] ', $GPO.Name @GPOSuccess
|
||||
}
|
||||
Write-Color -Text 'Applied Group Policy Objects' -StartSpaces 3 -LinesBefore 1
|
||||
foreach ($GPO in $ComputerWhereApplied[0]) {
|
||||
Write-Color -Text '[+] [', $GPO.DomainName, '] ', $GPO.Name @GPOSuccess
|
||||
}
|
||||
|
||||
Write-Color -Text 'Denied Group Policy Objects' -StartSpaces 3
|
||||
foreach ($GPO in $ComputerWhereApplied[1]) {
|
||||
Write-Color -Text '[-] [', $GPO.DomainName, '] ', $GPO.Name @GPODeny
|
||||
Write-Color -Text 'Denied Group Policy Objects' -StartSpaces 3
|
||||
foreach ($GPO in $ComputerWhereApplied[1]) {
|
||||
Write-Color -Text '[-] [', $GPO.DomainName, '] ', $GPO.Name @GPODeny
|
||||
}
|
||||
} else {
|
||||
Write-Color -Text 'Computer Settings' -Color Yellow -LinesBefore 1
|
||||
Write-Color -Text '[>] Last time Group Policy was applied: ', 'Unable to get? No administrative permission?' @WriteSummary
|
||||
Write-Color -Text '[>] Computer Name: ', $ComputerName @WriteSummary
|
||||
}
|
||||
|
||||
Write-Color -Text 'User Settings' -Color Yellow -LinesBefore 1
|
||||
Write-Color -Text '[>] Last time Group Policy was applied: ', $Results.UserResults.Summary.ReadTime @WriteSummary
|
||||
Write-Color -Text '[>] Computer Name: ', $Results.UserResults.Summary.ComputerName @WriteSummary
|
||||
Write-Color -Text '[>] Domain Name: ', $Results.UserResults.Summary.DomainName @WriteSummary
|
||||
Write-Color -Text '[>] Organizational Unit: ', $Results.UserResults.Summary.OrganizationalUnit @WriteSummary
|
||||
Write-Color -Text '[>] Site: ', $Results.UserResults.Summary.Site @WriteSummary
|
||||
Write-Color -Text '[>] GPO Types: ', ($Results.UserResults.Summary.GPOTypes -replace [System.Environment]::NewLine, ', ') @WriteSummary
|
||||
Write-Color -Text '[>] Slow link: ', ($Results.UserResults.Summary.SlowLink) @WriteSummary
|
||||
|
||||
Write-Color -Text 'Applied Group Policy Objects' -StartSpaces 3
|
||||
foreach ($GPO in $UserWhereApplied[0] ) {
|
||||
Write-Color -Text '[+] [', $GPO.DomainName, '] ', $GPO.Name @GPOSuccess
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
function New-GPOZaurrReportHTML {
|
||||
function New-GPOZaurrReportHTML {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[System.Collections.IDictionary] $Support,
|
||||
[string] $Path,
|
||||
[switch] $Offline,
|
||||
[switch] $Online,
|
||||
[switch] $Open
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$PSDefaultParameterValues = @{
|
||||
"New-HTMLTable:WarningAction" = 'SilentlyContinue'
|
||||
}
|
||||
@@ -23,43 +18,42 @@ function New-GPOZaurrReportHTML {
|
||||
New-HTML -TitleText "Group Policy Report - $ComputerName" {
|
||||
#New-HTMLTabOptions -SlimTabs -Transition -LinearGradient -SelectorColor Akaroa
|
||||
New-HTMLTableOption -DataStore JavaScript -BoolAsString
|
||||
New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow
|
||||
New-HTMLPanelStyle -BorderRadius 0px
|
||||
New-HTMLTabOptions -SlimTabs `
|
||||
-BorderBottomStyleActive solid -BorderBottomColorActive LightSkyBlue -BackgroundColorActive none `
|
||||
-TextColorActive Black -Align left -BorderRadius 0px -RemoveShadow -TextColor Grey -TextTransform capitalize
|
||||
New-HTMLTab -Name 'Information' {
|
||||
New-HTMLTable -DataTable $Support.ResultantSetPolicy -HideFooter -Transpose
|
||||
|
||||
New-HTMLSection {
|
||||
New-HTMLSection {
|
||||
#New-HTMLTable -DataTable $Support.ResultantSetPolicy -HideFooter -Transpose
|
||||
New-HTMLSection -HeaderText 'General Information' {
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.Time -Filtering -Transpose {
|
||||
New-TableHeader -Names 'Name', 'Value' -Title 'Time Information'
|
||||
}
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.BIOS -Filtering -Transpose
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.BIOS -Filtering -Transpose {
|
||||
New-TableHeader -Names 'Name', 'Value' -Title 'BIOS Information'
|
||||
}
|
||||
}
|
||||
New-HTMLContainer {
|
||||
New-HTMLSection {
|
||||
New-HTMLSection -HeaderText 'CPU Information' {
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.CPU -Filtering
|
||||
}
|
||||
New-HTMLSection {
|
||||
New-HTMLSection -HeaderText 'RAM Information' {
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.RAM -Filtering
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
New-HTMLSection {
|
||||
New-HTMLSection -HeaderText 'Operating System Information' {
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.OperatingSystem -Filtering
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.System -Filtering
|
||||
}
|
||||
New-HTMLSection {
|
||||
New-HTMLSection -HeaderText 'Disk Information' {
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.Disk -Filtering
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.DiskLogical -Filtering
|
||||
}
|
||||
New-HTMLSection {
|
||||
New-HTMLSection -HeaderText 'Services Information' {
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.Services -Filtering
|
||||
}
|
||||
New-HTMLSection {
|
||||
|
||||
}
|
||||
}
|
||||
foreach ($Key in $Support.Keys) {
|
||||
if ($Key -in 'ResultantSetPolicy', 'ComputerInformation') {
|
||||
@@ -81,9 +75,9 @@ function New-GPOZaurrReportHTML {
|
||||
New-HTMLTable -DataTable $Support.$Key.SummaryDownload -HideFooter
|
||||
}
|
||||
#>
|
||||
New-HTMLSection -HeaderText 'Resultant Set Policy' {
|
||||
New-HTMLTable -DataTable $Support.$Key.ResultantSetPolicy -HideFooter
|
||||
}
|
||||
#New-HTMLSection -HeaderText 'Resultant Set Policy' {
|
||||
# New-HTMLTable -DataTable $Support.$Key.ResultantSetPolicy -HideFooter
|
||||
#}
|
||||
}
|
||||
New-HTMLTab -Name 'Group Policies' {
|
||||
New-HTMLSection -Invisible {
|
||||
@@ -195,5 +189,5 @@ function New-GPOZaurrReportHTML {
|
||||
}
|
||||
}
|
||||
}
|
||||
} -Online:(-not $Offline.IsPresent) -Open:$Open.IsPresent -FilePath $Path
|
||||
} -Online:$Online.IsPresent -Open:$Open.IsPresent -FilePath $Path
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
$Script:GPOConfiguration = [ordered] @{
|
||||
GPOOrphans = $GPOZaurrOrphans
|
||||
GPOBroken = $GPOZaurrOrphans
|
||||
GPOBrokenLink = $GPOZaurrBrokenLink
|
||||
GPOOwners = $GPOZaurrOwners
|
||||
GPOConsistency = $GPOZaurrConsistency
|
||||
GPODuplicates = $GPOZaurrDuplicates
|
||||
GPOList = $GPOZaurrList
|
||||
GPOLinks = $GPOZaurrLinks
|
||||
GPOPassword = $GPOZaurrPassword
|
||||
GPOPermissions = $GPOZaurrPermissions
|
||||
GPOPermissions = $GPOZaurrPermissionsAnalysis
|
||||
GPOPermissionsAdministrative = $GPOZaurrPermissionsAdministrative
|
||||
GPOPermissionsRead = $GPOZaurrPermissionsRead
|
||||
GPOPermissionsRoot = $GPOZaurrPermissionsRoot
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
$Script:GPODitionary = [ordered] @{
|
||||
AccountPolicies = [ordered] @{
|
||||
AccountPolicies = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'SecuritySettings'
|
||||
@@ -14,7 +14,7 @@
|
||||
ConvertTo-XMLAccountPolicy -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
Audit = [ordered] @{
|
||||
Audit = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'SecuritySettings'
|
||||
@@ -36,7 +36,7 @@
|
||||
ConvertTo-XMLAudit -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
Autologon = [ordered] @{
|
||||
Autologon = [ordered] @{
|
||||
# We want to process this based on other report called RegistrySettings
|
||||
# This is because registry settings can be stored in Collections or nested within other registry settings
|
||||
# The original function ConvertTo-XMLRegistryAutologon was processing it in limited ordered and potentially would skip some entries.
|
||||
@@ -50,7 +50,7 @@
|
||||
ConvertTo-XMLRegistryAutologonOnReport -GPO $GPO
|
||||
}
|
||||
}
|
||||
AutoPlay = @{
|
||||
AutoPlay = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -65,7 +65,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/AutoPlay Policies*' -SingleObject
|
||||
}
|
||||
}
|
||||
Biometrics = @{
|
||||
Biometrics = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -78,7 +78,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Biometrics*'
|
||||
}
|
||||
}
|
||||
Bitlocker = @{
|
||||
Bitlocker = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -95,7 +95,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/BitLocker Drive Encryption*' -SingleObject
|
||||
}
|
||||
}
|
||||
ControlPanel = [ordered]@{
|
||||
ControlPanel = [ordered]@{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -110,7 +110,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel' -SingleObject
|
||||
}
|
||||
}
|
||||
ControlPanelAddRemove = [ordered]@{
|
||||
ControlPanelAddRemove = [ordered]@{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -125,7 +125,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Add or Remove Programs' -SingleObject
|
||||
}
|
||||
}
|
||||
ControlPanelDisplay = [ordered]@{
|
||||
ControlPanelDisplay = [ordered]@{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -140,7 +140,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Display' -SingleObject
|
||||
}
|
||||
}
|
||||
ControlPanelPersonalization = [ordered]@{
|
||||
ControlPanelPersonalization = [ordered]@{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -155,7 +155,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Personalization' -SingleObject
|
||||
}
|
||||
}
|
||||
ControlPanelPrinters = [ordered]@{
|
||||
ControlPanelPrinters = [ordered]@{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -170,7 +170,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Printers' -SingleObject
|
||||
}
|
||||
}
|
||||
ControlPanelPrograms = [ordered]@{
|
||||
ControlPanelPrograms = [ordered]@{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -185,7 +185,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Programs' -SingleObject
|
||||
}
|
||||
}
|
||||
ControlPanelRegional = [ordered]@{
|
||||
ControlPanelRegional = [ordered]@{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -200,7 +200,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Control Panel/Regional and Language Options' -SingleObject
|
||||
}
|
||||
}
|
||||
CredentialsDelegation = @{
|
||||
CredentialsDelegation = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -215,7 +215,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Credentials Delegation*' -SingleObject
|
||||
}
|
||||
}
|
||||
CustomInternationalSettings = [ordered]@{
|
||||
CustomInternationalSettings = [ordered]@{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -230,7 +230,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Custom International Settings*' -SingleObject
|
||||
}
|
||||
}
|
||||
Desktop = @{
|
||||
Desktop = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -245,7 +245,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Desktop*' -SingleObject
|
||||
}
|
||||
}
|
||||
DnsClient = @{
|
||||
DnsClient = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -260,7 +260,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Network/DNS Client*' -SingleObject
|
||||
}
|
||||
}
|
||||
DriveMapping = [ordered] @{
|
||||
DriveMapping = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'DriveMapSettings'
|
||||
@@ -275,7 +275,7 @@
|
||||
ConvertTo-XMLDriveMapSettings -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
EventLog = [ordered] @{
|
||||
EventLog = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'SecuritySettings'
|
||||
@@ -290,7 +290,7 @@
|
||||
ConvertTo-XMLEventLog -GPO $GPO
|
||||
}
|
||||
}
|
||||
EventForwarding = @{
|
||||
EventForwarding = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -305,7 +305,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Event Forwarding*' -SingleObject
|
||||
}
|
||||
}
|
||||
EventLogService = @{
|
||||
EventLogService = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -320,7 +320,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Event Log Service*' -SingleObject
|
||||
}
|
||||
}
|
||||
FileExplorer = @{
|
||||
FileExplorer = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -335,7 +335,22 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/File Explorer*' -SingleObject
|
||||
}
|
||||
}
|
||||
FolderRedirection = @{
|
||||
FolderRedirection = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'FolderRedirectionSettings'
|
||||
Settings = 'Folder'
|
||||
}
|
||||
)
|
||||
GPOPath = 'Windows Settings -> Folder Redirection'
|
||||
Code = {
|
||||
ConvertTo-XMLFolderRedirection -GPO $GPO
|
||||
}
|
||||
CodeSingle = {
|
||||
ConvertTo-XMLFolderRedirection -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
FolderRedirectionPolicy = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -350,7 +365,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Folder Redirection' -SingleObject
|
||||
}
|
||||
}
|
||||
FSLogix = @{
|
||||
FSLogix = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -365,7 +380,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'FSLogix' -SingleObject
|
||||
}
|
||||
}
|
||||
GoogleChrome = @{
|
||||
GoogleChrome = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -384,7 +399,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Google Chrome', 'Google/Google Chrome', 'Google Chrome - Default Settings (users can override)' -SingleObject
|
||||
}
|
||||
}
|
||||
GroupPolicy = @{
|
||||
GroupPolicy = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -399,7 +414,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Group Policy*' -SingleObject
|
||||
}
|
||||
}
|
||||
InternetCommunicationManagement = @{
|
||||
InternetCommunicationManagement = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -414,7 +429,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Internet Communication Management*' -SingleObject
|
||||
}
|
||||
}
|
||||
InternetExplorer = @{
|
||||
InternetExplorer = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -429,7 +444,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Internet Explorer*', 'Composants Windows/Celle Internet Explorer' -SingleObject
|
||||
}
|
||||
}
|
||||
InternetExplorerZones = [ordered] @{
|
||||
InternetExplorerZones = [ordered] @{
|
||||
ByReports = @(
|
||||
@{
|
||||
Report = 'RegistrySettings'
|
||||
@@ -440,7 +455,7 @@
|
||||
ConvertTo-XMLRegistryInternetExplorerZones -GPO $GPO
|
||||
}
|
||||
}
|
||||
KDC = @{
|
||||
KDC = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -455,7 +470,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/KDC' -SingleObject
|
||||
}
|
||||
}
|
||||
LAPS = @{
|
||||
LAPS = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -470,7 +485,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'LAPS' -SingleObject
|
||||
}
|
||||
}
|
||||
Lithnet = @{
|
||||
Lithnet = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -486,7 +501,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Lithnet/Password Protection for Active Directory*' -SingleObject
|
||||
}
|
||||
}
|
||||
LocalUsers = [ordered] @{
|
||||
LocalUsers = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'LugsSettings'
|
||||
@@ -501,7 +516,7 @@
|
||||
ConvertTo-XMLLocalUser -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
LocalGroups = [ordered] @{
|
||||
LocalGroups = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'LugsSettings'
|
||||
@@ -516,7 +531,7 @@
|
||||
ConvertTo-XMLLocalGroups -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
Logon = @{
|
||||
Logon = @{
|
||||
Types = @(
|
||||
@{ Category = 'RegistrySettings'; Settings = 'Policy' }
|
||||
)
|
||||
@@ -528,7 +543,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Logon*' -SingleObject
|
||||
}
|
||||
}
|
||||
MicrosoftOutlook2002 = @{
|
||||
MicrosoftOutlook2002 = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -543,7 +558,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Outlook 2002*' -SingleObject
|
||||
}
|
||||
}
|
||||
MicrosoftEdge = @{
|
||||
MicrosoftEdge = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -562,7 +577,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Edge*', 'Windows Components/Microsoft Edge', 'Windows Components/Edge UI' -SingleObject
|
||||
}
|
||||
}
|
||||
MicrosoftOutlook2003 = @{
|
||||
MicrosoftOutlook2003 = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -580,7 +595,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Office Outlook 2003*', 'Outlook 2003 RPC Encryption' -SingleObject
|
||||
}
|
||||
}
|
||||
MicrosoftOutlook2010 = @{
|
||||
MicrosoftOutlook2010 = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -595,7 +610,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Outlook 2010*' -SingleObject
|
||||
}
|
||||
}
|
||||
MicrosoftOutlook2013 = @{
|
||||
MicrosoftOutlook2013 = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -610,7 +625,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Outlook 2013*' -SingleObject
|
||||
}
|
||||
}
|
||||
MicrosoftOutlook2016 = @{
|
||||
MicrosoftOutlook2016 = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -625,7 +640,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Microsoft Outlook 2016*' -SingleObject
|
||||
}
|
||||
}
|
||||
MicrosoftManagementConsole = @{
|
||||
MicrosoftManagementConsole = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -640,7 +655,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Microsoft Management Console*' -SingleObject
|
||||
}
|
||||
}
|
||||
NetMeeting = @{
|
||||
NetMeeting = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -655,7 +670,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/NetMeeting*' -SingleObject
|
||||
}
|
||||
}
|
||||
MSSLegacy = @{
|
||||
MSSLegacy = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -670,7 +685,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'MSS (Legacy)' -SingleObject
|
||||
}
|
||||
}
|
||||
MSSecurityGuide = @{
|
||||
MSSecurityGuide = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -685,7 +700,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'MS Security Guide' -SingleObject
|
||||
}
|
||||
}
|
||||
OneDrive = @{
|
||||
OneDrive = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -700,7 +715,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/OneDrive*' -SingleObject
|
||||
}
|
||||
}
|
||||
Policies = @{
|
||||
Policies = @{
|
||||
Comment = "This isn't really translated"
|
||||
Types = @(
|
||||
@{
|
||||
@@ -716,7 +731,7 @@
|
||||
ConvertTo-XMLPolicies -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
Printers = @{
|
||||
Printers = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'PrintersSettings'
|
||||
@@ -735,7 +750,7 @@
|
||||
ConvertTo-XMLPrinter -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
PrintersPolicies = @{
|
||||
PrintersPolicies = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -753,7 +768,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Printers*', 'Control Panel/Printers*' -SingleObject
|
||||
}
|
||||
}
|
||||
PublicKeyPoliciesCertificates = [ordered] @{
|
||||
PublicKeyPoliciesCertificates = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'PublicKeySettings'
|
||||
@@ -805,7 +820,7 @@
|
||||
}
|
||||
}
|
||||
#>
|
||||
PublicKeyPoliciesAutoEnrollment = [ordered] @{
|
||||
PublicKeyPoliciesAutoEnrollment = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'PublicKeySettings'
|
||||
@@ -820,7 +835,7 @@
|
||||
ConvertTo-XMLGenericPublicKey -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
PublicKeyPoliciesEFS = [ordered] @{
|
||||
PublicKeyPoliciesEFS = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'PublicKeySettings'
|
||||
@@ -835,7 +850,7 @@
|
||||
ConvertTo-XMLGenericPublicKey -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
PublicKeyPoliciesRootCA = [ordered] @{
|
||||
PublicKeyPoliciesRootCA = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'PublicKeySettings'
|
||||
@@ -850,7 +865,7 @@
|
||||
ConvertTo-XMLGenericPublicKey -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
PublicKeyPoliciesEnrollmentPolicy = @{
|
||||
PublicKeyPoliciesEnrollmentPolicy = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -867,7 +882,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Internet Communication Management*' -SingleObject
|
||||
}
|
||||
}
|
||||
RegistrySetting = [ordered] @{
|
||||
RegistrySetting = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -882,7 +897,7 @@
|
||||
ConvertTo-XMLGenericPublicKey -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
RegistrySettings = [ordered] @{
|
||||
RegistrySettings = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -897,7 +912,7 @@
|
||||
ConvertTo-XMLRegistrySettings -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
OnlineAssistance = @{
|
||||
OnlineAssistance = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -912,7 +927,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Online Assistance*' -SingleObject
|
||||
}
|
||||
}
|
||||
RemoteAssistance = @{
|
||||
RemoteAssistance = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -927,7 +942,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Remote Assistance*' -SingleObject
|
||||
}
|
||||
}
|
||||
RemoteDesktopServices = @{
|
||||
RemoteDesktopServices = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -942,7 +957,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Remote Desktop Services*' -SingleObject
|
||||
}
|
||||
}
|
||||
RSSFeeds = @{
|
||||
RSSFeeds = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -957,7 +972,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/RSS Feeds*' -SingleObject
|
||||
}
|
||||
}
|
||||
Scripts = [ordered] @{
|
||||
Scripts = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'Scripts'
|
||||
@@ -972,7 +987,7 @@
|
||||
ConvertTo-XMLScripts -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
SecurityOptions = [ordered] @{
|
||||
SecurityOptions = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'SecuritySettings'
|
||||
@@ -987,7 +1002,7 @@
|
||||
ConvertTo-XMLSecurityOptions -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
SoftwareInstallation = [ordered] @{
|
||||
SoftwareInstallation = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'SoftwareInstallationSettings'
|
||||
@@ -1002,7 +1017,7 @@
|
||||
ConvertTo-XMLSoftwareInstallation -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
SystemServices = [ordered] @{
|
||||
SystemServices = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'SecuritySettings'
|
||||
@@ -1018,7 +1033,7 @@
|
||||
ConvertTo-XMLSystemServices -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
SystemServicesNT = [ordered] @{
|
||||
SystemServicesNT = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'ServiceSettings'
|
||||
@@ -1052,7 +1067,7 @@
|
||||
}
|
||||
}
|
||||
#>
|
||||
TaskScheduler = [ordered] @{
|
||||
TaskScheduler = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'ScheduledTasksSettings'
|
||||
@@ -1068,7 +1083,7 @@
|
||||
ConvertTo-XMLTaskScheduler -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
TaskSchedulerPolicies = @{
|
||||
TaskSchedulerPolicies = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -1101,7 +1116,7 @@
|
||||
}
|
||||
}
|
||||
#>
|
||||
UserRightsAssignment = [ordered] @{
|
||||
UserRightsAssignment = [ordered] @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'SecuritySettings'
|
||||
@@ -1116,7 +1131,7 @@
|
||||
ConvertTo-XMLUserRightsAssignment -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsDefender = @{
|
||||
WindowsDefender = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -1131,7 +1146,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Defender*' -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsDefenderExploitGuard = @{
|
||||
WindowsDefenderExploitGuard = @{
|
||||
# this needs improvements because of DropDownList
|
||||
Types = @(
|
||||
@{
|
||||
@@ -1147,7 +1162,103 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Microsoft Defender Antivirus/Microsoft Defender Exploit Guard*' -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsHelloForBusiness = @{
|
||||
# WindowsFirewall = @{
|
||||
# # Contains only one setting showing version
|
||||
# Types = @(
|
||||
# @{
|
||||
# Category = 'WindowsFirewallSettings'
|
||||
# Settings = 'GlobalSettings'
|
||||
# }
|
||||
# )
|
||||
# GPOPath = 'Policies -> Windows Settings -> Security Settings -> Windows Firewall with Advanced Security'
|
||||
# Code = {
|
||||
# ConvertTo-XMLWindowsFirewall -GPO $GPO
|
||||
# }
|
||||
# CodeSingle = {
|
||||
# ConvertTo-XMLWindowsFirewall -GPO $GPO -SingleObject
|
||||
# }
|
||||
# }
|
||||
WindowsFirewallConnectionSecurityRules = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'WindowsFirewallSettings'
|
||||
Settings = 'ConnectionSecurityRules'
|
||||
}
|
||||
)
|
||||
GPOPath = 'Policies -> Windows Settings -> Security Settings -> Windows Firewall with Advanced Security'
|
||||
Code = {
|
||||
ConvertTo-XMLWindowsFirewallSecurityRules -GPO $GPO
|
||||
}
|
||||
CodeSingle = {
|
||||
ConvertTo-XMLWindowsFirewallSecurityRules -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsFirewallConnectionSecurityAuthentication = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'WindowsFirewallSettings'
|
||||
Settings = 'Phase1AuthenticationSets'
|
||||
}
|
||||
@{
|
||||
Category = 'WindowsFirewallSettings'
|
||||
Settings = 'Phase2AuthenticationSets'
|
||||
}
|
||||
#@{
|
||||
# Category = 'WindowsFirewallSettings'
|
||||
# Settings = 'DefaultPhase1CryptoSet'
|
||||
#}
|
||||
)
|
||||
GPOPath = 'Policies -> Windows Settings -> Security Settings -> Windows Firewall with Advanced Security'
|
||||
Code = {
|
||||
ConvertTo-XMLWindowsFirewallConnectionSecurityAuthentiation -GPO $GPO
|
||||
}
|
||||
CodeSingle = {
|
||||
ConvertTo-XMLWindowsFirewallConnectionSecurityAuthentiation -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsFirewallProfiles = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'WindowsFirewallSettings'
|
||||
Settings = 'DomainProfile'
|
||||
}
|
||||
@{
|
||||
Category = 'WindowsFirewallSettings'
|
||||
Settings = 'PublicProfile'
|
||||
}
|
||||
@{
|
||||
Category = 'WindowsFirewallSettings'
|
||||
Settings = 'PrivateProfile'
|
||||
}
|
||||
)
|
||||
GPOPath = 'Policies -> Windows Settings -> Security Settings -> Windows Firewall with Advanced Security'
|
||||
Code = {
|
||||
ConvertTo-XMLWindowsFirewallProfile -GPO $GPO
|
||||
}
|
||||
CodeSingle = {
|
||||
ConvertTo-XMLWindowsFirewallProfile -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsFirewallRules = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'WindowsFirewallSettings'
|
||||
Settings = 'InboundFirewallRules'
|
||||
}
|
||||
@{
|
||||
Category = 'WindowsFirewallSettings'
|
||||
Settings = 'OutboundFirewallRules'
|
||||
}
|
||||
)
|
||||
GPOPath = 'Policies -> Windows Settings -> Security Settings -> Windows Firewall with Advanced Security -> '
|
||||
Code = {
|
||||
ConvertTo-XMLWindowsFirewallRules -GPO $GPO
|
||||
}
|
||||
CodeSingle = {
|
||||
ConvertTo-XMLWindowsFirewallRules -GPO $GPO -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsHelloForBusiness = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -1162,7 +1273,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Hello For Business*' -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsInstaller = @{
|
||||
WindowsInstaller = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -1177,7 +1288,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Installer*' -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsLogon = @{
|
||||
WindowsLogon = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -1192,7 +1303,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Logon Options*' -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsMediaPlayer = @{
|
||||
WindowsMediaPlayer = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -1207,7 +1318,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Media Player*' -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsMessenger = @{
|
||||
WindowsMessenger = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -1222,7 +1333,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Messenger*' -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsPowerShell = @{
|
||||
WindowsPowerShell = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -1237,7 +1348,7 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows PowerShell*' -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsRemoteManagement = @{
|
||||
WindowsRemoteManagement = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
@@ -1252,7 +1363,22 @@
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'Windows Components/Windows Remote Management (WinRM)*' -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsUpdate = @{
|
||||
WindowsTimeService = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
Settings = 'Policy'
|
||||
}
|
||||
)
|
||||
GPOPath = 'Policies -> Administrative Templates -> System/Windows Time Service'
|
||||
Code = {
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Windows Time Service*'
|
||||
}
|
||||
CodeSingle = {
|
||||
ConvertTo-XMLGenericPolicy -GPO $GPO -Category 'System/Windows Time Service*' -SingleObject
|
||||
}
|
||||
}
|
||||
WindowsUpdate = @{
|
||||
Types = @(
|
||||
@{
|
||||
Category = 'RegistrySettings'
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
)
|
||||
$Differences = @{ }
|
||||
$SysvolHash = @{ }
|
||||
|
||||
$GPOGUIDS = $GPOs.ID.GUID
|
||||
$GPOGUIDS = ConvertFrom-DistinguishedName -DistinguishedName $GPOs.DistinguishedName
|
||||
$SysVolPath = "\\$($Server)\SYSVOL\$Domain\Policies"
|
||||
Write-Verbose "Get-GPOZaurrBroken - Processing SYSVOL from \\$($Server)\SYSVOL\$Domain\Policies"
|
||||
try {
|
||||
@@ -19,10 +18,10 @@
|
||||
$Sysvol = $Null
|
||||
}
|
||||
foreach ($_ in $SYSVOL) {
|
||||
$GUID = $_.Name -replace '{' -replace '}'
|
||||
$GUID = $_.Name
|
||||
$SysvolHash[$GUID] = $_
|
||||
}
|
||||
$Files = $SYSVOL.Name -replace '{' -replace '}'
|
||||
$Files = $SYSVOL.Name
|
||||
if ($Files) {
|
||||
$Comparing = Compare-Object -ReferenceObject $GPOGUIDS -DifferenceObject $Files -IncludeEqual
|
||||
foreach ($_ in $Comparing) {
|
||||
@@ -30,8 +29,10 @@
|
||||
# we skip policy definitions
|
||||
continue
|
||||
}
|
||||
$ADStatus = $PoliciesAD[$_.InputObject]
|
||||
if ($_.SideIndicator -eq '==') {
|
||||
$Found = 'Exists'
|
||||
#$Found = 'Exists'
|
||||
$Found = $ADStatus
|
||||
} elseif ($_.SideIndicator -eq '<=') {
|
||||
$Found = 'Not available on SYSVOL'
|
||||
} elseif ($_.SideIndicator -eq '=>') {
|
||||
@@ -41,8 +42,10 @@
|
||||
$Found = 'Not available in AD'
|
||||
}
|
||||
} else {
|
||||
# This shouldn't happen at all
|
||||
$Found = 'Orphaned GPO'
|
||||
}
|
||||
|
||||
$Differences[$_.InputObject] = $Found
|
||||
}
|
||||
}
|
||||
@@ -50,85 +53,60 @@
|
||||
$Count = 0
|
||||
foreach ($GPO in $GPOS) {
|
||||
$Count++
|
||||
Write-Verbose "Get-GPOZaurrBroken - Processing [$($GPO.DomainName)]($Count/$($GPOS.Count)) $($GPO.DisplayName)"
|
||||
if ($null -ne $SysvolHash[$GPO.Id.GUID].FullName) {
|
||||
$FullPath = $SysvolHash[$GPO.Id.GUID].FullName
|
||||
try {
|
||||
$ACL = Get-Acl -Path $SysvolHash[$GPO.Id.GUID].FullName -ErrorAction Stop -Verbose:$false
|
||||
$Owner = $ACL.Owner
|
||||
$ErrorMessage = ''
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrBroken - ACL reading (1) failed for $FullPath with error: $($_.Exception.Message)"
|
||||
$ACL = $null
|
||||
$Owner = ''
|
||||
$ErrorMessage = $_.Exception.Message
|
||||
}
|
||||
$GPOGuid = ConvertFrom-DistinguishedName -DistinguishedName $GPO.DistinguishedName
|
||||
if ($GPO.DisplayName) {
|
||||
$GPODisplayName = $GPO.DisplayName
|
||||
$GPOName = $GPO.Name
|
||||
Write-Verbose "Get-GPOZaurrBroken - Processing [$($Domain)]($Count/$($GPOS.Count)) $($GPO.DisplayName)"
|
||||
} else {
|
||||
$FullPath = -join ($SysVolPath, "\{$($GPO.Id.Guid)}")
|
||||
$ACL = $null
|
||||
$Owner = ''
|
||||
$GPOName = $GPOGuid
|
||||
$GPODisplayName = $GPOGuid
|
||||
Write-Verbose "Get-GPOZaurrBroken - Processing [$($Domain)]($Count/$($GPOS.Count)) $($GPOGuid)"
|
||||
}
|
||||
if ($null -ne $SysvolHash[$GPOGuid].FullName) {
|
||||
$FullPath = $SysvolHash[$GPOGuid].FullName
|
||||
$ErrorMessage = ''
|
||||
} else {
|
||||
$FullPath = -join ($SysVolPath, "\$($GPOGuid)")
|
||||
$ErrorMessage = 'Not found on SYSVOL'
|
||||
}
|
||||
if ($null -eq $Differences[$GPO.Id.Guid]) {
|
||||
$SysVolStatus = 'Unknown Issue'
|
||||
if ($null -eq $Differences[$GPOGuid]) {
|
||||
$SysVolStatus = 'Unknown issue'
|
||||
} else {
|
||||
$SysVolStatus = $Differences[$GPO.Id.Guid]
|
||||
$SysVolStatus = $Differences[$GPOGuid]
|
||||
}
|
||||
[PSCustomObject] @{
|
||||
DisplayName = $GPO.DisplayName
|
||||
DisplayName = $GPODisplayName
|
||||
Status = $SysVolStatus
|
||||
DomainName = $GPO.DomainName
|
||||
DomainName = $Domain
|
||||
SysvolServer = $Server
|
||||
SysvolStatus = $SysVolStatus
|
||||
GpoStatus = $GPO.GpoStatus
|
||||
Owner = $GPO.Owner
|
||||
FileOwner = $Owner
|
||||
Id = $GPO.Id.Guid
|
||||
ObjectClass = $GPO.ObjectClass
|
||||
Id = $GPOName
|
||||
Path = $FullPath
|
||||
DistinguishedName = -join ("CN={", $GPO.Id.Guid, "},", $PoliciesSearchBase)
|
||||
DistinguishedName = -join ("CN=", $GPOGuid, ",", $PoliciesSearchBase)
|
||||
Description = $GPO.Description
|
||||
CreationTime = $GPO.CreationTime
|
||||
ModificationTime = $GPO.ModificationTime
|
||||
UserVersion = $GPO.UserVersion
|
||||
ComputerVersion = $GPO.ComputerVersion
|
||||
WmiFilter = $GPO.WmiFilter
|
||||
CreationTime = $GPO.Created
|
||||
ModificationTime = $GPO.Modified
|
||||
Error = $ErrorMessage
|
||||
}
|
||||
}
|
||||
# Now we need to list thru Sysvol files and fine those that do not exists as GPO and create dummy GPO objects to show orphaned gpos
|
||||
Write-Verbose "Get-GPOZaurrBroken - Processing SYSVOL differences"
|
||||
foreach ($_ in $Differences.Keys) {
|
||||
if ($Differences[$_] -in 'Not available in AD', 'Permissions issue') {
|
||||
if ($Differences[$_] -in 'Not available in AD') {
|
||||
$FullPath = $SysvolHash[$_].FullName
|
||||
try {
|
||||
$ACL = Get-Acl -Path $FullPath -ErrorAction Stop
|
||||
$Owner = $ACL.Owner
|
||||
$ErrorMessage = ''
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrBroken - ACL reading (2) failed for $FullPath with error: $($_.Exception.Message)"
|
||||
$ACL = $null
|
||||
$Owner = $null
|
||||
$ErrorMessage = $_.Exception.Message
|
||||
}
|
||||
|
||||
[PSCustomObject] @{
|
||||
DisplayName = $SysvolHash[$_].BaseName
|
||||
Status = $Differences[$_]
|
||||
DomainName = $Domain
|
||||
SysvolServer = $Server
|
||||
SysvolStatus = 'Exists' #$Differences[$GPO.Id.Guid]
|
||||
GpoStatus = $Differences[$_]
|
||||
Owner = ''
|
||||
FileOwner = $Owner
|
||||
ObjectClass = ''
|
||||
Id = $_
|
||||
Path = $FullPath
|
||||
DistinguishedName = -join ("CN={", $_, "},", $PoliciesSearchBase)
|
||||
DistinguishedName = -join ("CN=", $_, ",", $PoliciesSearchBase)
|
||||
Description = $null
|
||||
CreationTime = $SysvolHash[$_].CreationTime
|
||||
ModificationTime = $SysvolHash[$_].LastWriteTime
|
||||
UserVersion = $null
|
||||
ComputerVersion = $null
|
||||
WmiFilter = $null
|
||||
Error = $ErrorMessage
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
}
|
||||
}
|
||||
#>
|
||||
if (-not $PermissionsAnalysis['Skip']) {
|
||||
if (-not $PermissionsAnalysis.'Skip') {
|
||||
if (-not $GPOPermissions) {
|
||||
# This is bad - things went wrong
|
||||
Write-Warning "Add-GPOZaurrPermission - Couldn't get permissions for GPO. Things aren't what they should be. Skipping!"
|
||||
@@ -118,7 +118,7 @@
|
||||
# We asked, we got response, now we need to check if maybe we're missing one of the two administrative groups
|
||||
if ($Type -eq 'Administrative') {
|
||||
# this is a case where something was returned. Be it Domain Admins or Enterprise Admins or both. But we still need to check because it may have been Domain Admins from other domain or just one of the two required groups
|
||||
if ($PermissionsAnalysis['DomainAdmins'] -eq $false) {
|
||||
if ($PermissionsAnalysis.'DomainAdmins' -eq $false) {
|
||||
$Principal = $ADAdministrativeGroups[$GPO.DomainName]['DomainAdmins']
|
||||
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
|
||||
$CountFixed++
|
||||
@@ -132,7 +132,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($PermissionsAnalysis['EnterpriseAdmins'] -eq $false) {
|
||||
if ($PermissionsAnalysis.'EnterpriseAdmins' -eq $false) {
|
||||
$Principal = $ADAdministrativeGroups[$ForestInformation.Forest.RootDomain]['EnterpriseAdmins']
|
||||
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
|
||||
$CountFixed++
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function Clear-GPOZaurrSysvolDFSR {
|
||||
function Clear-GPOZaurrSysvolDFSR {
|
||||
[cmdletBinding(SupportsShouldProcess)]
|
||||
param(
|
||||
[alias('ForestName')][string] $Forest,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function ConvertFrom-CSExtension {
|
||||
function ConvertFrom-CSExtension {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[string[]] $CSE,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function Find-CSExtension {
|
||||
function Find-CSExtension {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[string[]] $CSE,
|
||||
|
||||
+41
-52
@@ -5,7 +5,7 @@
|
||||
[string] $GPOName,
|
||||
[alias('GUID', 'GPOID')][string] $GPOGuid,
|
||||
|
||||
[validateset('Empty', 'Unlinked', 'Disabled', 'All')][string[]] $Type,
|
||||
[validateset('Empty', 'Unlinked', 'Disabled', 'NoApplyPermission', 'All')][string[]] $Type,
|
||||
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
@@ -47,6 +47,10 @@
|
||||
if ($OwnerOnly -or $PermissionsOnly -and $Type) {
|
||||
Write-Warning "Get-GPOZaurr - Using PermissionOnly or OwnerOnly with Type is not supported. "
|
||||
}
|
||||
if (-not $GPOPath) {
|
||||
# This is needed, because Get-GPOReport doesn't deliver full scope of links, just some of it. It doesn't cover OUs with blocked inheritance, sites or crosslinked
|
||||
$LinksSummaryCache = Get-GPOZaurrLink -AsHashTable -Summary -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
}
|
||||
}
|
||||
Process {
|
||||
if (-not $GPOPath) {
|
||||
@@ -54,68 +58,53 @@
|
||||
$QueryServer = $ForestInformation.QueryServers[$Domain]['HostName'][0]
|
||||
$Count = 0
|
||||
if ($GPOName) {
|
||||
$GroupPolicies = Get-GPO -Name $GPOName -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue
|
||||
$GroupPolicies | ForEach-Object {
|
||||
$Count++
|
||||
#Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
|
||||
Write-Verbose "Get-GPOZaurr - Processing [$($_.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
|
||||
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 -ReturnObject:$ReturnObject.IsPresent -ExcludeGroupPolicies $ExcludeGPO -Type $Type
|
||||
} else {
|
||||
$_
|
||||
}
|
||||
$getGPOSplat = @{
|
||||
Name = $GPOName
|
||||
Domain = $Domain
|
||||
Server = $QueryServer
|
||||
ErrorAction = 'SilentlyContinue'
|
||||
}
|
||||
} elseif ($GPOGuid) {
|
||||
$GroupPolicies = Get-GPO -Guid $GPOGuid -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue
|
||||
$GroupPolicies | ForEach-Object {
|
||||
$Count++
|
||||
#Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
|
||||
Write-Verbose "Get-GPOZaurr - Processing [$($_.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
|
||||
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 -ReturnObject:$ReturnObject.IsPresent -ExcludeGroupPolicies $ExcludeGPO -Type $Type
|
||||
} else {
|
||||
$_
|
||||
}
|
||||
$getGPOSplat = @{
|
||||
Guid = $GPOGuid
|
||||
Domain = $Domain
|
||||
Server = $QueryServer
|
||||
ErrorAction = 'SilentlyContinue'
|
||||
}
|
||||
} else {
|
||||
$GroupPolicies = Get-GPO -All -Server $QueryServer -Domain $Domain -ErrorAction SilentlyContinue
|
||||
$GroupPolicies | ForEach-Object {
|
||||
$Count++
|
||||
#Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain"
|
||||
Write-Verbose "Get-GPOZaurr - Processing [$($_.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
|
||||
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 -ReturnObject:$ReturnObject.IsPresent -ExcludeGroupPolicies $ExcludeGPO -Type $Type
|
||||
} else {
|
||||
$_
|
||||
$getGPOSplat = @{
|
||||
All = $true
|
||||
Server = $QueryServer
|
||||
Domain = $Domain
|
||||
ErrorAction = 'SilentlyContinue'
|
||||
}
|
||||
}
|
||||
$GroupPolicies = Get-GPO @getGPOSplat
|
||||
foreach ($GPO in $GroupPolicies) {
|
||||
$Count++
|
||||
Write-Verbose "Get-GPOZaurr - Processing [$($GPO.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
|
||||
if (-not $Limited) {
|
||||
try {
|
||||
$XMLContent = Get-GPOReport -ID $GPO.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurr - Failed to get [$($GPO.DomainName)]($Count/$($GroupPolicies.Count)) $($GPO.DisplayName) GPOReport: $($_.Exception.Message). Skipping."
|
||||
continue
|
||||
}
|
||||
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $GPO -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups -ReturnObject:$ReturnObject.IsPresent -ExcludeGroupPolicies $ExcludeGPO -Type $Type -LinksSummaryCache $LinksSummaryCache
|
||||
} else {
|
||||
$GPO
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($Path in $GPOPath) {
|
||||
Write-Verbose "Get-GPOZaurr - Getting GPO content from XML files"
|
||||
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 -ExcludeGroupPolicies $ExcludeGPO -Type $Type
|
||||
Get-ChildItem -LiteralPath $Path -Recurse -Filter *.xml -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
if ($_.Name -ne 'GPOList.xml') {
|
||||
$XMLContent = [XML]::new()
|
||||
$XMLContent.Load($_.FullName)
|
||||
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -PermissionsOnly:$PermissionsOnly.IsPresent -ExcludeGroupPolicies $ExcludeGPO -Type $Type
|
||||
}
|
||||
}
|
||||
Write-Verbose "Get-GPOZaurr - Finished GPO content from XML files"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,47 @@
|
||||
function Get-GPOZaurrBroken {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Detects broken or otherwise damaged Group Policies
|
||||
|
||||
.DESCRIPTION
|
||||
Detects broken or otherwise damaged Group Policies providing insight whether GPO exists in both AD and SYSVOL.
|
||||
It provides few statuses:
|
||||
- Permissions issue - means account couldn't read GPO due to permissions
|
||||
- ObjectClass issue - means that ObjectClass is of type Container, rather than expected groupPolicyContainer
|
||||
- Not available on SYSVOL - means SYSVOL data is missing, yet AD metadata is available
|
||||
- Not available in AD - means AD metadata is missing, yet SYSVOL data is available
|
||||
- Exists - means AD metadata and SYSVOL data are available
|
||||
|
||||
.PARAMETER Forest
|
||||
Target different Forest, by default current forest is used
|
||||
|
||||
.PARAMETER ExcludeDomains
|
||||
Exclude domain from search, by default whole forest is scanned
|
||||
|
||||
.PARAMETER ExcludeDomainControllers
|
||||
Exclude specific domain controllers, by default there are no exclusions, as long as VerifyDomainControllers switch is enabled. Otherwise this parameter is ignored.
|
||||
|
||||
.PARAMETER IncludeDomains
|
||||
Include only specific domains, by default whole forest is scanned
|
||||
|
||||
.PARAMETER IncludeDomainControllers
|
||||
Include only specific domain controllers, by default all domain controllers are included, as long as VerifyDomainControllers switch is enabled. Otherwise this parameter is ignored.
|
||||
|
||||
.PARAMETER SkipRODC
|
||||
Skip Read-Only Domain Controllers. By default all domain controllers are included.
|
||||
|
||||
.PARAMETER ExtendedForestInformation
|
||||
Ability to provide Forest Information from another command to speed up processing
|
||||
|
||||
.PARAMETER VerifyDomainControllers
|
||||
Forces cmdlet to check GPO Existance on Domain Controllers rather then per domain
|
||||
|
||||
.EXAMPLE
|
||||
Get-GPOZaurrBroken -Verbose | Format-Table
|
||||
|
||||
.NOTES
|
||||
General notes
|
||||
#>
|
||||
[alias('Get-GPOZaurrSysvol')]
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
@@ -8,7 +51,6 @@
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[alias('DomainControllers')][string[]] $IncludeDomainControllers,
|
||||
[switch] $SkipRODC,
|
||||
[Array] $GPOs,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
[switch] $VerifyDomainControllers
|
||||
)
|
||||
@@ -21,31 +63,31 @@
|
||||
$PoliciesAD = @{}
|
||||
if ($SystemsContainer) {
|
||||
$PoliciesSearchBase = -join ("CN=Policies,", $SystemsContainer)
|
||||
$PoliciesInAD = Get-ADObject -SearchBase $PoliciesSearchBase -SearchScope OneLevel -Filter * -Server $QueryServer
|
||||
$PoliciesInAD = Get-ADObject -SearchBase $PoliciesSearchBase -SearchScope OneLevel -Filter * -Server $QueryServer -Properties Name, gPCFileSysPath, DisplayName, DistinguishedName, Description, Created, Modified, ObjectClass, ObjectGUID
|
||||
foreach ($Policy in $PoliciesInAD) {
|
||||
$GUIDFromDN = ConvertFrom-DistinguishedName -DistinguishedName $Policy.DistinguishedName
|
||||
$GUIDFromDN = $GUIDFromDN -replace '{' -replace '}'
|
||||
$GUID = $Policy.Name -replace '{' -replace '}'
|
||||
if ($GUID -and $GUIDFromDN) {
|
||||
$PoliciesAD[$GUIDFromDN] = 'Exists'
|
||||
if ($Policy.ObjectClass -eq 'Container') {
|
||||
# This usually means GPO deletion process somehow failed and while object itself stayed it isn't groupPolicyContainer anymore
|
||||
$PoliciesAD[$GUIDFromDN] = 'ObjectClass issue'
|
||||
} else {
|
||||
$PoliciesAD[$GUIDFromDN] = 'Permissions issue'
|
||||
$GUID = $Policy.Name
|
||||
if ($GUID -and $GUIDFromDN) {
|
||||
$PoliciesAD[$GUIDFromDN] = 'Exists'
|
||||
} else {
|
||||
$PoliciesAD[$GUIDFromDN] = 'Permissions issue'
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Get-GPOZaurrBroken - Couldn't get GPOs from $Domain. Skipping"
|
||||
}
|
||||
Try {
|
||||
[Array]$GPOs = Get-GPO -All -Domain $Domain -Server $QueryServer
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrBroken - Couldn't get GPOs from $Domain. Error: $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
if ($GPOs.Count -ge 2) {
|
||||
if ($PoliciesInAD.Count -ge 2) {
|
||||
if (-not $VerifyDomainControllers) {
|
||||
Test-SysVolFolders -GPOs $GPOs -Server $Domain -Domain $Domain -PoliciesAD $PoliciesAD -PoliciesSearchBase $PoliciesSearchBase
|
||||
Test-SysVolFolders -GPOs $PoliciesInAD -Server $Domain -Domain $Domain -PoliciesAD $PoliciesAD -PoliciesSearchBase $PoliciesSearchBase
|
||||
} else {
|
||||
foreach ($Server in $ForestInformation['DomainDomainControllers']["$Domain"]) {
|
||||
Write-Verbose "Get-GPOZaurrBroken - Processing $Domain \ $($Server.HostName.Trim())"
|
||||
Test-SysVolFolders -GPOs $GPOs -Server $Server.Hostname -Domain $Domain -PoliciesAD $PoliciesAD -PoliciesSearchBase $PoliciesSearchBase
|
||||
Test-SysVolFolders -GPOs $PoliciesInAD -Server $Server.Hostname -Domain $Domain -PoliciesAD $PoliciesAD -PoliciesSearchBase $PoliciesSearchBase
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
function Get-GPOZaurrBrokenLink {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Finds any GPO link that doesn't have a matching GPO (already removed GPO).
|
||||
|
||||
.DESCRIPTION
|
||||
Finds any GPO link that doesn't have a matching GPO (already removed GPO).
|
||||
|
||||
.PARAMETER Forest
|
||||
Target different Forest, by default current forest is used
|
||||
|
||||
.PARAMETER ExcludeDomains
|
||||
Exclude domain from search, by default whole forest is scanned
|
||||
|
||||
.PARAMETER IncludeDomains
|
||||
Include only specific domains, by default whole forest is scanned
|
||||
|
||||
.PARAMETER ExtendedForestInformation
|
||||
Ability to provide Forest Information from another command to speed up processing
|
||||
|
||||
.EXAMPLE
|
||||
Get-GPOZaurrBrokenLink -Verbose | Format-Table -AutoSize *
|
||||
|
||||
.EXAMPLE
|
||||
Get-GPOZaurrBrokenLink -Verbose -IncludeDomains ad.evotec.pl | Format-Table -AutoSize *
|
||||
|
||||
.NOTES
|
||||
General notes
|
||||
#>
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
)
|
||||
$ErrorFound = $false
|
||||
$PoliciesAD = @{}
|
||||
# We need to request all GPOS from Forest. Requesting just for any domain won't be enough
|
||||
$ForestInformation = Get-WinADForestDetails -Forest $Forest -Extended # -Extended
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
$QueryServer = $ForestInformation['QueryServers']["$Domain"].HostName[0]
|
||||
$SystemsContainer = $ForestInformation['DomainsExtended'][$Domain].SystemsContainer
|
||||
if ($SystemsContainer) {
|
||||
$PoliciesSearchBase = -join ("CN=Policies,", $SystemsContainer)
|
||||
try {
|
||||
$PoliciesInAD = Get-ADObject -ErrorAction Stop -SearchBase $PoliciesSearchBase -SearchScope OneLevel -Filter * -Server $QueryServer -Properties Name, gPCFileSysPath, DisplayName, DistinguishedName, Description, Created, Modified, ObjectClass, ObjectGUID
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrBrokenLink - An error occured while searching $PoliciesSearchBase. Error $($_.Exception.Message). Please resolve this before continuing."
|
||||
$ErrorFound = $true
|
||||
break
|
||||
}
|
||||
foreach ($Policy in $PoliciesInAD) {
|
||||
$GUIDFromDN = ConvertFrom-DistinguishedName -DistinguishedName $Policy.DistinguishedName
|
||||
# $Key = "$($Domain)$($GuidFromDN)"
|
||||
$Key = $Policy.DistinguishedName
|
||||
if ($Policy.ObjectClass -eq 'Container') {
|
||||
# This usually means GPO deletion process somehow failed and while object itself stayed it isn't groupPolicyContainer anymore
|
||||
$PoliciesAD[$Key] = 'ObjectClass issue'
|
||||
} else {
|
||||
$GUID = $Policy.Name
|
||||
if ($GUID -and $GUIDFromDN) {
|
||||
$PoliciesAD[$Key] = 'Exists'
|
||||
} else {
|
||||
$PoliciesAD[$Key] = 'Permissions issue'
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Get-GPOZaurrBroken - Couldn't get GPOs from $Domain. Skipping"
|
||||
}
|
||||
}
|
||||
if ($ErrorFound) {
|
||||
return
|
||||
}
|
||||
# In case of links we can request here whatever user requested.
|
||||
# This will search for broken links in domain user requested
|
||||
$ForestInformation = Get-WinADForestDetails -Forest $Forest -Extended -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
$Links = Get-GPOZaurrLinkLoop -Linked 'All' -ForestInformation $ForestInformation
|
||||
foreach ($Link in $Links) {
|
||||
if (-not $PoliciesAD[$Link.GPODistinguishedName]) {
|
||||
$Link
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
function Get-GPOZaurrFilesPolicyDefinition {
|
||||
function Get-GPOZaurrFilesPolicyDefinition {
|
||||
[alias('Get-GPOZaurrFilesPolicyDefinitions')]
|
||||
[cmdletbinding()]
|
||||
param(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function Get-GPOZaurrFolders {
|
||||
function Get-GPOZaurrFolders {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[ValidateSet('All', 'Netlogon', 'Sysvol')][string[]] $Type = 'All',
|
||||
|
||||
@@ -1,8 +1,49 @@
|
||||
function Get-GPOZaurrInheritance {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Short description
|
||||
|
||||
.DESCRIPTION
|
||||
Long description
|
||||
|
||||
.PARAMETER IncludeBlockedObjects
|
||||
Include OU's with blocked inheritance. Default disabled
|
||||
|
||||
.PARAMETER OnlyBlockedInheritance
|
||||
Show only OU's with blocked inheritance
|
||||
|
||||
.PARAMETER IncludeExcludedObjects
|
||||
Show excluded objets. Default disabled
|
||||
|
||||
.PARAMETER Exclusions
|
||||
Provide exclusions for OU's approved by IT. You can provide OU by canonical name or distinguishedName
|
||||
|
||||
.PARAMETER Forest
|
||||
Target different Forest, by default current forest is used
|
||||
|
||||
.PARAMETER ExcludeDomains
|
||||
Exclude domain from search, by default whole forest is scanned
|
||||
|
||||
.PARAMETER IncludeDomains
|
||||
Include only specific domains, by default whole forest is scanned
|
||||
|
||||
.PARAMETER ExtendedForestInformation
|
||||
Ability to provide Forest Information from another command to speed up processing
|
||||
|
||||
.EXAMPLE
|
||||
$Objects = Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance -Exclusions $ExcludedOU
|
||||
$Objects | Format-Table
|
||||
|
||||
.NOTES
|
||||
General notes
|
||||
#>
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[switch] $IncludeBlockedObjects,
|
||||
[switch] $OnlyBlockedInheritance,
|
||||
[switch] $IncludeExcludedObjects,
|
||||
[switch] $IncludeGroupPoliciesForBlockedObjects,
|
||||
[string[]] $Exclusions,
|
||||
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
@@ -10,7 +51,11 @@
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
)
|
||||
Begin {
|
||||
$ExclusionsCache = @{}
|
||||
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
foreach ($Exclusion in $Exclusions) {
|
||||
$ExclusionsCache[$Exclusion] = $true
|
||||
}
|
||||
}
|
||||
Process {
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
@@ -19,6 +64,37 @@
|
||||
$InheritanceInformation = [Ordered] @{
|
||||
CanonicalName = $OU.canonicalName
|
||||
BlockedInheritance = if ($OU.gpOptions -eq 1) { $true } else { $false }
|
||||
Exclude = $false
|
||||
DomainName = ConvertFrom-DistinguishedName -ToDomainCN -DistinguishedName $OU.DistinguishedName
|
||||
}
|
||||
if ($InheritanceInformation.BlockedInheritance -and $IncludeGroupPoliciesForBlockedObjects.IsPresent) {
|
||||
$GPInheritance = Get-GPInheritance -Target $OU.distinguishedName
|
||||
$ActiveGroupPolicies = foreach ($GPO in $GPInheritance.InheritedGpoLinks) {
|
||||
[PSCustomObject] @{
|
||||
OrganizationalUnit = $OU.canonicalName
|
||||
DisplayName = $GPO.DisplayName
|
||||
DomainName = $GPO.GpoDomainName
|
||||
LinkedDirectly = if ($OU.DistinguishedName -eq $GPO.Target) { $true } else { $false }
|
||||
GPOID = $GPO.GPOID
|
||||
Enabled = $GPO.Enabled
|
||||
Enforced = $GPO.Enforced
|
||||
Order = $GPO.Order
|
||||
LinkedTo = $GPO.Target
|
||||
OrganizationalUnitDN = $OU.DistinguishedName
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$ActiveGroupPolicies = $null
|
||||
}
|
||||
if ($Exclusions) {
|
||||
if ($ExclusionsCache[$OU.canonicalName]) {
|
||||
$InheritanceInformation['Exclude'] = $true
|
||||
} elseif ($ExclusionsCache[$OU.DistinguishedName]) {
|
||||
$InheritanceInformation['Exclude'] = $true
|
||||
}
|
||||
}
|
||||
if (-not $IncludeExcludedObjects -and $InheritanceInformation['Exclude']) {
|
||||
continue
|
||||
}
|
||||
if (-not $IncludeBlockedObjects) {
|
||||
if ($OnlyBlockedInheritance) {
|
||||
@@ -44,6 +120,8 @@
|
||||
$InheritanceInformation['Computers'] = $null
|
||||
}
|
||||
}
|
||||
$InheritanceInformation['DistinguishedName'] = $OU.DistinguishedName
|
||||
$InheritanceInformation['GroupPolicies'] = $ActiveGroupPolicies
|
||||
if ($OnlyBlockedInheritance) {
|
||||
if ($InheritanceInformation.BlockedInheritance -eq $true) {
|
||||
[PSCustomObject] $InheritanceInformation
|
||||
@@ -52,17 +130,7 @@
|
||||
[PSCustomObject] $InheritanceInformation
|
||||
}
|
||||
}
|
||||
$InheritanceInformation['DistinguishedName'] = $OU.DistinguishedName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
|
||||
$OrganizationalUnits = Get-ADOrganizationalUnit -Filter *
|
||||
$Output = foreach ($OU in $OrganizationalUnits) {
|
||||
Get-GPInheritance -Target $OU.DistinguishedName
|
||||
}
|
||||
$Output | Format-Table
|
||||
#>
|
||||
}
|
||||
+104
-166
@@ -1,13 +1,15 @@
|
||||
function Get-GPOZaurrLink {
|
||||
[cmdletbinding()]
|
||||
[cmdletbinding(DefaultParameterSetName = 'Linked')]
|
||||
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')",
|
||||
# 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 = 'Linked')][validateset('All', 'Root', 'DomainControllers', 'Site', 'OrganizationalUnit')][string[]] $Linked,
|
||||
|
||||
[parameter(ParameterSetName = 'Site')][string[]] $Site,
|
||||
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
@@ -19,30 +21,47 @@
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[switch] $SkipDuplicates,
|
||||
|
||||
[parameter(ParameterSetName = 'Site')]
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[System.Collections.IDictionary] $GPOCache,
|
||||
|
||||
[parameter(ParameterSetName = 'Site')]
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[alias('ForestName')][string] $Forest,
|
||||
|
||||
[parameter(ParameterSetName = 'Site')]
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[string[]] $ExcludeDomains,
|
||||
|
||||
[parameter(ParameterSetName = 'Site')]
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
|
||||
[parameter(ParameterSetName = 'Site')]
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
|
||||
[parameter(ParameterSetName = 'Site')]
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[switch] $AsHashTable,
|
||||
|
||||
[parameter(ParameterSetName = 'Site')]
|
||||
[parameter(ParameterSetName = 'Filter')]
|
||||
[parameter(ParameterSetName = 'ADObject')]
|
||||
[parameter(ParameterSetName = 'Linked')]
|
||||
[switch] $Summary
|
||||
)
|
||||
Begin {
|
||||
$CacheReturnedGPOs = [ordered] @{}
|
||||
@@ -52,6 +71,7 @@
|
||||
# While initially we used $ForestInformation.Domains but the thing is GPOs can be linked to other domains so we need to get them all so we can use cache of it later on even if we're processing just one domain
|
||||
# That's why we use $ForestInformation.Forest.Domains instead
|
||||
foreach ($Domain in $ForestInformation.Forest.Domains) {
|
||||
Write-Verbose "Get-GPOZaurrLink - Building GPO cache for domain $Domain"
|
||||
$QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
|
||||
Get-GPO -All -DomainName $Domain -Server $QueryServer | ForEach-Object {
|
||||
$GPOCache["$Domain$($_.ID.Guid)"] = $_
|
||||
@@ -60,173 +80,91 @@
|
||||
}
|
||||
}
|
||||
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]
|
||||
$getGPOLoopSplat = @{
|
||||
Linked = $Linked
|
||||
ForestInformation = $ForestInformation
|
||||
SearchScope = $SearchScope
|
||||
SearchBase = $SearchBase
|
||||
ADObject = $ADObject
|
||||
Filter = $Filter
|
||||
SkipDuplicates = $SkipDuplicates
|
||||
Site = $Site
|
||||
}
|
||||
Remove-EmptyValue -Hashtable $getGPOLoopSplat -Recursive
|
||||
$getGPOLoopSplat['CacheReturnedGPOs'] = $CacheReturnedGPOs
|
||||
if ($AsHashTable -or $Summary) {
|
||||
$HashTable = [ordered] @{}
|
||||
$SummaryHashtable = [ordered] @{}
|
||||
$Links = Get-GPOZaurrLinkLoop @getGPOLoopSplat
|
||||
foreach ($Link in $Links) {
|
||||
$Key = -join ($Link.DomainName, $Link.GUID)
|
||||
if (-not $HashTable[$Key]) {
|
||||
$HashTable[$Key] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
}
|
||||
$HashTable[$Key].Add($Link)
|
||||
}
|
||||
foreach ($Key in $HashTable.Keys) {
|
||||
[Array] $Link = $HashTable[$Key]
|
||||
$EnabledLinks = $Link.Enabled.Where( { $_ -eq $true }, 'split')
|
||||
|
||||
$LinkedRoot = $false
|
||||
$LinkedRootPlaces = [System.Collections.Generic.List[string]]::new()
|
||||
$LinkedSite = $false
|
||||
$LinkedSitePlaces = [System.Collections.Generic.List[string]]::new()
|
||||
$LinkedOU = $false
|
||||
$LinkedCrossDomain = $false
|
||||
$LinkedCrossDomainPlaces = [System.Collections.Generic.List[string]]::new()
|
||||
foreach ($InternalLink in $Link) {
|
||||
if ($InternalLink.ObjectClass -eq 'domainDNS') {
|
||||
$LinkedRoot = $true
|
||||
$LinkedRootPlaces.Add($InternalLink.DistinguishedName)
|
||||
} elseif ($InternalLink.ObjectClass -eq 'site') {
|
||||
$LinkedSite = $true
|
||||
$LinkedSitePlaces.Add($InternalLink.Name)
|
||||
} else {
|
||||
$LinkedOU = $true
|
||||
}
|
||||
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
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
foreach ($_ in $ADObjectGPO) {
|
||||
$OutputGPOs = Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
||||
foreach ($OutputGPO in $OutputGPOs) {
|
||||
if (-not $SkipDuplicates) {
|
||||
$OutputGPO
|
||||
} else {
|
||||
$UniqueGuid = -join ($OutputGPO.DomainName, $OutputGPO.Guid)
|
||||
if (-not $CacheReturnedGPOs[$UniqueGuid]) {
|
||||
$CacheReturnedGPOs[$UniqueGuid] = $OutputGPO
|
||||
$OutputGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
foreach ($_ in $ADObjectGPO) {
|
||||
$OutputGPOs = Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
||||
foreach ($OutputGPO in $OutputGPOs) {
|
||||
if (-not $SkipDuplicates) {
|
||||
$OutputGPO
|
||||
} else {
|
||||
$UniqueGuid = -join ($OutputGPO.DomainName, $OutputGPO.Guid)
|
||||
if (-not $CacheReturnedGPOs[$UniqueGuid]) {
|
||||
$CacheReturnedGPOs[$UniqueGuid] = $OutputGPO
|
||||
$OutputGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
foreach ($_ in $ADObjectGPO) {
|
||||
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
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
foreach ($_ in $ADObjectGPO) {
|
||||
if ($_.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']) {
|
||||
# other skips Domain Root
|
||||
} elseif ($_.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']) {
|
||||
# other skips Domain Controllers
|
||||
} else {
|
||||
$OutputGPOs = Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
||||
foreach ($OutputGPO in $OutputGPOs) {
|
||||
if (-not $SkipDuplicates) {
|
||||
$OutputGPO
|
||||
} else {
|
||||
$UniqueGuid = -join ($OutputGPO.DomainName, $OutputGPO.Guid)
|
||||
if (-not $CacheReturnedGPOs[$UniqueGuid]) {
|
||||
$CacheReturnedGPOs[$UniqueGuid] = $OutputGPO
|
||||
$OutputGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$CN = ConvertFrom-DistinguishedName -ToDomainCN -DistinguishedName $InternalLink.distinguishedName
|
||||
$GPOCN = ConvertFrom-DistinguishedName -ToDomainCN -DistinguishedName $InternalLink.GPODomainDistinguishedName
|
||||
if ($CN -ne $GPOCN) {
|
||||
$LinkedCrossDomain = $true
|
||||
$LinkedCrossDomainPlaces.Add($InternalLink.DistinguishedName)
|
||||
}
|
||||
}
|
||||
} 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']
|
||||
$SearchBaseDC = ConvertFrom-DistinguishedName -DistinguishedName $SearchBase -ToDC
|
||||
if ($SearchBaseDC -ne $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
|
||||
}
|
||||
|
||||
try {
|
||||
$ADObjectGPO = Get-ADObject @Splat
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrLink - Get-ADObject error $($_.Exception.Message)"
|
||||
}
|
||||
foreach ($_ in $ADObjectGPO) {
|
||||
$OutputGPOs = Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
||||
foreach ($OutputGPO in $OutputGPOs) {
|
||||
if (-not $SkipDuplicates) {
|
||||
$OutputGPO
|
||||
} else {
|
||||
$UniqueGuid = -join ($OutputGPO.DomainName, $OutputGPO.Guid)
|
||||
if (-not $CacheReturnedGPOs[$UniqueGuid]) {
|
||||
$CacheReturnedGPOs[$UniqueGuid] = $OutputGPO
|
||||
$OutputGPO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($EnabledLinks[0].Count -gt 0) {
|
||||
$IsLinked = $true
|
||||
} else {
|
||||
$IsLinked = $false
|
||||
}
|
||||
$SummaryLink = [PSCustomObject] @{
|
||||
DisplayName = $Link[0].DisplayName
|
||||
DomainName = $Link[0].DomainName
|
||||
GUID = $Link[0].GUID
|
||||
Linked = $IsLinked
|
||||
LinksCount = $Link.Count
|
||||
LinksEnabledCount = $EnabledLinks[0].Count
|
||||
LinksDisabledCount = $EnabledLinks[1].Count
|
||||
LinkedCrossDomain = $LinkedCrossDomain
|
||||
LinkedRoot = $LinkedRoot
|
||||
LinkedSite = $LinkedSite
|
||||
LinkedOU = $LinkedOU
|
||||
LinkedSitePlaces = $LinkedSitePlaces
|
||||
LinkedRootPlaces = $LinkedRootPlaces
|
||||
LinkedCrossDomainPlaces = $LinkedCrossDomainPlaces
|
||||
Links = $Link.DistinguishedName
|
||||
LinksObjects = $Link
|
||||
}
|
||||
$SummaryHashtable[$Key] = $SummaryLink
|
||||
}
|
||||
if ($AsHashTable -and $Summary) {
|
||||
$SummaryHashtable
|
||||
} elseif ($AsHashTable) {
|
||||
$HashTable
|
||||
} elseif ($Summary) {
|
||||
$SummaryHashtable.Values
|
||||
}
|
||||
} else {
|
||||
foreach ($Object in $ADObject) {
|
||||
Get-PrivGPOZaurrLink -Object $Object -Limited:$Limited.IsPresent -GPOCache $GPOCache
|
||||
}
|
||||
Get-GPOZaurrLinkLoop @getGPOLoopSplat
|
||||
}
|
||||
}
|
||||
End {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
$CacheSummaryLinks = [ordered] @{} # cache
|
||||
|
||||
# Get all links
|
||||
$Links = Get-GPOZaurrLink -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
$Links = Get-GPOZaurrLink -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -Linked Root, DomainControllers, OrganizationalUnit
|
||||
foreach ($Link in $Links) {
|
||||
if (-not $CacheSummaryLinks["$($Link.DomainName)$($Link.Guid)"]) {
|
||||
$CacheSummaryLinks["$($Link.DomainName)$($Link.Guid)"] = [System.Collections.Generic.List[System.Object]]::new()
|
||||
@@ -121,13 +121,13 @@
|
||||
for ($i = 0; $i -le $HighestCount; $i++) {
|
||||
"Level$i"
|
||||
}
|
||||
'Owner'
|
||||
'GpoStatus'
|
||||
'Description'
|
||||
'CreationTime'
|
||||
'ModificationTime'
|
||||
'GPODomainDistinguishedName'
|
||||
'GPODistinguishedName'
|
||||
#'Owner'
|
||||
#'GpoStatus'
|
||||
#'Description'
|
||||
#'CreationTime'
|
||||
#'ModificationTime'
|
||||
#'GPODomainDistinguishedName'
|
||||
#'GPODistinguishedName'
|
||||
)
|
||||
$ReturnObject.MultipleLinks = $ReturnObject.MultipleLinks | Select-Object -Property $Properties
|
||||
}
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
} catch {
|
||||
Write-Warning "Get-GPOZaurrNetLogon - ACL reading failed for $($File.FullName) with error $($_.Exception.Message) ($($_.CategoryInfo.Reason))"
|
||||
}
|
||||
#if ($ACL.Owner) {
|
||||
$IdentityOwner = Convert-Identity -Identity $ACL.Owner -Verbose:$false
|
||||
$IdentityOwnerAdvanced = Get-WinADObject -Identity $ACL.Owner -Cache -Verbose:$false
|
||||
#} else {
|
||||
# $IdentityOwner = [PSCustomObject] @{ SID = ''; Type = 'Unknown' }
|
||||
# $IdentityOwnerAdvanced = [PSCustomObject] @{ ObjectClass = '' }
|
||||
#}
|
||||
if ($ACL.Owner) {
|
||||
$IdentityOwner = Convert-Identity -Identity $ACL.Owner -Verbose:$false
|
||||
$IdentityOwnerAdvanced = Get-WinADObject -Identity $ACL.Owner -Cache -Verbose:$false
|
||||
} else {
|
||||
$IdentityOwner = [PSCustomObject] @{ Name = ''; SID = ''; Type = 'Unknown' }
|
||||
$IdentityOwnerAdvanced = [PSCustomObject] @{ ObjectClass = '' }
|
||||
}
|
||||
if (-not $OwnerOnly) {
|
||||
if (-not $SkipOwner) {
|
||||
if ($IdentityOwner.SID -eq "S-1-5-32-544") {
|
||||
|
||||
@@ -44,25 +44,6 @@
|
||||
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) {
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
function Get-GPOZaurrPermissionAnalysis {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
|
||||
[Array] $Permissions
|
||||
)
|
||||
if (-not $ADAdministrativeGroups) {
|
||||
$ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
}
|
||||
|
||||
if (-not $Permissions) {
|
||||
$Permissions = Get-GPOZaurrPermission -IncludePermissionType GpoEditDeleteModifySecurity, GpoApply, GpoCustom, GpoRead -ReturnSecurityWhenNoData -IncludeGPOObject -ReturnSingleObject -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
foreach ($GPO in $Permissions) {
|
||||
$AdministrativeExists = [ordered] @{
|
||||
DisplayName = $GPO[0].DisplayName
|
||||
DomainName = $GPO[0].DomainName
|
||||
GUID = $GPO[0].GUID
|
||||
Status = $false
|
||||
Administrative = $false
|
||||
AuthenticatedUsers = $false
|
||||
System = $false
|
||||
Unknown = $false
|
||||
#StatusAuthenticatedUsers = $false
|
||||
#StatusSystem = $false
|
||||
DomainAdmins = $false
|
||||
EnterpriseAdmins = $false
|
||||
AuthenticatedUsersPermission = $null
|
||||
DomainAdminsPermission = $null
|
||||
EnterpriseAdminsPermission = $null
|
||||
SystemPermission = $null
|
||||
UnknownPermission = $null
|
||||
}
|
||||
foreach ($Permission in $GPO) {
|
||||
if ($Permission.GPOSecurityPermissionItem) {
|
||||
# We are looking for administrative but we need to make sure we got correct administrative
|
||||
$AdministrativeGroup = $ADAdministrativeGroups['BySID'][$Permission.PrincipalSid]
|
||||
if ($AdministrativeGroup) {
|
||||
$PermissionType = [Microsoft.GroupPolicy.GPPermissionType]::GpoEditDeleteModifySecurity, [Microsoft.GroupPolicy.GPPermissionType]::GpoCustom
|
||||
if ($Permission.Permission -in $PermissionType) {
|
||||
if ($AdministrativeGroup.SID -like '*-519') {
|
||||
$AdministrativeExists['EnterpriseAdmins'] = $true
|
||||
$AdministrativeExists['EnterpriseAdminsPermission'] = $Permission.Permission
|
||||
} elseif ($AdministrativeGroup.SID -like '*-512') {
|
||||
$AdministrativeExists['DomainAdmins'] = $true
|
||||
$AdministrativeExists['DomainAdminsPermission'] = $Permission.Permission
|
||||
}
|
||||
} else {
|
||||
if ($AdministrativeGroup.SID -like '*-519') {
|
||||
$AdministrativeExists['EnterpriseAdminsPermission'] = $Permission.Permission
|
||||
} elseif ($AdministrativeGroup.SID -like '*-512') {
|
||||
$AdministrativeExists['DomainAdminsPermission'] = $Permission.Permission
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($AdministrativeExists['DomainAdmins'] -and $AdministrativeExists['EnterpriseAdmins']) {
|
||||
$AdministrativeExists['Administrative'] = $true
|
||||
}
|
||||
if ($Permission.PrincipalSid -eq 'S-1-5-11') {
|
||||
$PermissionType = [Microsoft.GroupPolicy.GPPermissionType]::GpoApply, [Microsoft.GroupPolicy.GPPermissionType]::GpoRead
|
||||
if ($Permission.Permission -in $PermissionType) {
|
||||
$AdministrativeExists['AuthenticatedUsers'] = $true
|
||||
}
|
||||
$AdministrativeExists['AuthenticatedUsersPermission'] = $Permission.Permission
|
||||
}
|
||||
if ($Permission.PrincipalSid -eq 'S-1-5-18') {
|
||||
$PermissionType = [Microsoft.GroupPolicy.GPPermissionType]::GpoEditDeleteModifySecurity
|
||||
if ($Permission.Permission -in $PermissionType) {
|
||||
$AdministrativeExists['System'] = $true
|
||||
}
|
||||
$AdministrativeExists['SystemPermission'] = $Permission.Permission
|
||||
}
|
||||
if ($Permission.PrincipalSidType -eq 'Unknown') {
|
||||
$AdministrativeExists['Unknown'] = $true
|
||||
$AdministrativeExists['UnknownPermission'] = $Permission.Permission
|
||||
}
|
||||
if ( $AdministrativeExists['System'] -eq $true -and $AdministrativeExists['AuthenticatedUsers'] -eq $true -and $AdministrativeExists['Administrative'] -eq $true -and $AdministrativeExists['Unknown'] -eq $false) {
|
||||
$AdministrativeExists['Status'] = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
[PSCustomObject] $AdministrativeExists
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
function Get-GPOZaurrSysvolDFSR {
|
||||
function Get-GPOZaurrSysvolDFSR {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[alias('ForestName')][string] $Forest,
|
||||
|
||||
+15
-28
@@ -2,7 +2,7 @@
|
||||
[alias('Show-GPOZaurr', 'Show-GPO')]
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[Parameter(Position = 1)][scriptblock] $ExcludeGroupPolicies,
|
||||
[alias('ExcludeGroupPolicies', 'ExclusionsCode')][Parameter(Position = 1)][object] $Exclusions,
|
||||
[string] $FilePath,
|
||||
[Parameter(Position = 0)][string[]] $Type,
|
||||
[switch] $PassThru,
|
||||
@@ -12,7 +12,8 @@
|
||||
[switch] $ShowWarning,
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[switch] $Online
|
||||
)
|
||||
Reset-GPOZaurrStatus # This makes sure types are at it's proper status
|
||||
|
||||
@@ -49,27 +50,6 @@
|
||||
Write-Color '[i]', "[GPOZaurr] ", 'Domain Information', ' [Informative] ', "Included Domains: ", $DisplayIncludedDomains -Color Yellow, DarkGray, Yellow, DarkGray, Yellow, Magenta
|
||||
Write-Color '[i]', "[GPOZaurr] ", 'Domain Information', ' [Informative] ', "Excluded Domains: ", $DisplayExcludedDomains -Color Yellow, DarkGray, Yellow, DarkGray, Yellow, Magenta
|
||||
|
||||
# Exclusions support, converts ScriptBlock into list of GPOs
|
||||
<#
|
||||
$Exclusions = [ordered]@{}
|
||||
if ($Extension) {
|
||||
$Exclusions['All'] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
[Array] $ExecuteExtension = & $Extension
|
||||
foreach ($Ext in $ExecuteExtension) {
|
||||
if ($Ext.Type -eq 'Exclusion') {
|
||||
if ($Ext.Type) {
|
||||
if (-not $Exclusions[$Ext.Type]) {
|
||||
$Exclusions[$Ext.Type] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
}
|
||||
$Exclusions[$Ext.Type].Add($Ext)
|
||||
} else {
|
||||
$Exclusions['All'].Add($Ext)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#>
|
||||
|
||||
# Lets make sure we only enable those types which are requestd by user
|
||||
if ($Type) {
|
||||
foreach ($T in $Script:GPOConfiguration.Keys) {
|
||||
@@ -95,8 +75,12 @@
|
||||
Variables = Copy-Dictionary -Dictionary $Script:GPOConfiguration[$T]['Variables']
|
||||
}
|
||||
if ($Exclusions) {
|
||||
$Script:Reporting[$T]['ExclusionsCode'] = $ExcludeGroupPolicies
|
||||
$Script:Reporting[$T]['Exclusions'] = & $ExcludeGroupPolicies
|
||||
if ($Exclusions -is [scriptblock]) {
|
||||
$Script:Reporting[$T]['ExclusionsCode'] = $Exclusions
|
||||
}
|
||||
if ($Exclusions -is [Array]) {
|
||||
$Script:Reporting[$T]['Exclusions'] = $Exclusions
|
||||
}
|
||||
}
|
||||
|
||||
$TimeLogGPOList = Start-TimeLog
|
||||
@@ -143,12 +127,15 @@
|
||||
|
||||
# Generate pretty HTML
|
||||
$TimeLogHTML = Start-TimeLog
|
||||
Write-Color -Text '[i]', '[HTML ] ', 'Generating HTML report' -Color Yellow, DarkGray, Yellow
|
||||
if (-not $FilePath) {
|
||||
$FilePath = Get-FileName -Extension 'html' -Temporary
|
||||
}
|
||||
Write-Color -Text '[i]', '[HTML ] ', "Generating HTML report ($FilePath)" -Color Yellow, DarkGray, Yellow
|
||||
New-HTML -Author 'Przemysław Kłys' -TitleText 'GPOZaurr Report' {
|
||||
New-HTMLTabStyle -BorderRadius 0px -TextTransform capitalize -BackgroundColorActive SlateGrey
|
||||
New-HTMLSectionStyle -BorderRadius 0px -HeaderBackGroundColor Grey -RemoveShadow
|
||||
New-HTMLPanelStyle -BorderRadius 0px
|
||||
New-HTMLTableOption -DataStore JavaScript -BoolAsString
|
||||
New-HTMLTableOption -DataStore JavaScript -BoolAsString -ArrayJoinString ', ' -ArrayJoin
|
||||
|
||||
New-HTMLHeader {
|
||||
New-HTMLSection -Invisible {
|
||||
@@ -182,7 +169,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
} -Online -ShowHTML:(-not $HideHTML) -FilePath $FilePath
|
||||
} -Online:$Online.IsPresent -ShowHTML:(-not $HideHTML) -FilePath $FilePath
|
||||
$TimeLogEndHTML = Stop-TimeLog -Time $TimeLogHTML -Option OneLiner
|
||||
Write-Color -Text '[i]', '[HTML ] ', 'Generating HTML report', " [Time to execute: $TimeLogEndHTML]" -Color Yellow, DarkGray, Yellow, DarkGray
|
||||
if ($PassThru) {
|
||||
|
||||
@@ -95,7 +95,10 @@
|
||||
$Output['CategoriesFull'] = [ordered] @{}
|
||||
|
||||
Write-Verbose "Invoke-GPOZaurrContent - Loading GPO Report to Categories"
|
||||
$CountGPO = 0
|
||||
[Array] $GPOCategories = foreach ($GPO in $GPOs) {
|
||||
$CountGPO++
|
||||
Write-Verbose "Invoke-GPOZaurrContent - Processing [$CountGPO/$($GPOs.Count)] $($GPO.DisplayName)"
|
||||
if ($GPOPath) {
|
||||
$GPOOutput = $GPO.GPOOutput
|
||||
} else {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
[parameter(ParameterSetName = 'Level', Mandatory)][int] $Limit,
|
||||
|
||||
# ParameterSet4
|
||||
[parameter(ParameterSetName = 'Linked', Mandatory)][validateset('Root', 'DomainControllers', 'Site', 'Other')][string] $Linked,
|
||||
[parameter(ParameterSetName = 'Linked', Mandatory)][validateset('Root', 'DomainControllers', 'Site', 'OrganizationalUnit')][string] $Linked,
|
||||
|
||||
# ParameterSet5
|
||||
[parameter(ParameterSetName = 'ADObject', ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user