Compare commits

...

54 Commits

Author SHA1 Message Date
Przemyslaw Klys 7adfd1ef65 PSD1 2020-12-23 11:06:39 +01:00
Przemyslaw Klys 828c221ac9 Renamed GPOBroken 2020-12-23 10:46:07 +01:00
Przemyslaw Klys 8e80fd423d Update readme 2020-12-23 10:45:55 +01:00
Przemyslaw Klys f52fd60fef Update 2020-12-23 10:33:30 +01:00
Przemyslaw Klys 9594afb246 Update example 2020-12-23 10:00:53 +01:00
Przemyslaw Klys 7c52284b48 Improved Remove-GPOZaurrBroken 2020-12-23 09:47:14 +01:00
Przemyslaw Klys 2fd64952af Update readme 2020-12-23 09:47:04 +01:00
Przemyslaw Klys 15538e8559 Improve Get-GPOZaurrBroken 2020-12-23 09:32:07 +01:00
Przemyslaw Klys a36a470538 Update readme 2020-12-23 09:31:57 +01:00
Przemyslaw Klys 0a5d65761c PSD1 / README update 2020-12-21 13:22:20 +01:00
Przemyslaw Klys 7ed3cb6dad Update 2020-12-21 13:21:29 +01:00
Przemyslaw Klys 4d9edde212 Update example 2020-12-15 19:11:24 +01:00
Przemyslaw Klys 7ba40e3981 Small update to permission analysis 2020-12-13 15:44:33 +01:00
Przemyslaw Klys ec81655019 Update readme 2020-12-13 15:44:22 +01:00
Przemyslaw Klys 752a34204b Update readme 2020-12-13 15:41:44 +01:00
Przemyslaw Klys 0afe6c6d23 Update readme 2020-12-13 15:40:58 +01:00
Przemyslaw Klys 2a300747a1 Update example 2020-12-13 15:37:43 +01:00
Przemyslaw Klys 94b8a71192 Fix encoding 2020-12-13 14:54:36 +01:00
Przemyslaw Klys 49b9eccfd1 Update Example 2020-12-13 14:54:27 +01:00
Przemyslaw Klys 92b5f00d7f update gpo example 2020-12-13 14:54:14 +01:00
Przemyslaw Klys 1f625e4e90 Permissions report 2020-12-13 14:53:58 +01:00
Przemyslaw Klys 7ac406ca24 Update examples 2020-12-13 14:52:23 +01:00
Przemyslaw Klys 4d584902e8 Repair-GPOZaurrPermission new 2020-12-13 14:51:54 +01:00
Przemyslaw Klys 7e6efb81f1 Update PSD1/Readme 2020-12-13 14:51:47 +01:00
Przemyslaw Klys 16b0a0f4b6 Update report steps to be clickable 2020-12-13 14:06:36 +01:00
Przemyslaw Klys 85eaa4e5d6 Update report permission analysis 2020-12-13 14:04:05 +01:00
Przemyslaw Klys 8c555a4fa9 Update Perm Analisys 2020-12-13 14:03:55 +01:00
Przemyslaw Klys 8bc85a4c91 Encoding update 2020-12-13 13:33:41 +01:00
Przemyslaw Klys 84ad1df972 Update 2020-12-13 13:33:31 +01:00
Przemyslaw Klys 71a12316e3 Update Get-GPOZaurrPermissionAnalysis 2020-12-13 09:39:01 +01:00
Przemyslaw Klys 4a3a49440f Force encoding utf 8 with bom 2020-12-12 23:14:02 +01:00
Przemyslaw Klys 0b2e2ea96c Update examples 2020-12-12 22:16:02 +01:00
Przemyslaw Klys 4ae3bbce12 Update examples 2020-12-12 22:15:28 +01:00
Przemyslaw Klys 471bc04fb2 Update examples 2020-12-12 22:15:18 +01:00
Przemyslaw Klys 4d050c536d Update examples 2020-12-12 22:15:07 +01:00
Przemyslaw Klys 508402b4bf Update examples 2020-12-12 22:14:42 +01:00
Przemyslaw Klys 6f1ac33df8 Update examples 2020-12-12 22:14:27 +01:00
Przemyslaw Klys 5130ef77e5 Update 2020-12-12 22:14:04 +01:00
Przemyslaw Klys 19c2b6bf90 Update 2020-12-12 19:44:56 +01:00
Przemyslaw Klys 5b1aaae915 Update 2020-12-12 19:44:51 +01:00
Przemyslaw Klys d239c979e9 modified readme 2020-12-12 19:41:01 +01:00
Przemyslaw Klys 35c04c88c0 added Get-GPOZaurrPermissionAnalysis 2020-12-12 19:40:54 +01:00
Przemyslaw Klys 048347c830 Internal Get-PermissionsAnalysis update 2020-12-11 22:43:04 +01:00
Przemyslaw Klys 563ba55342 readme update 2020-12-11 22:42:41 +01:00
Przemyslaw Klys 5a62968925 PSD1 update 2020-12-11 22:42:30 +01:00
Przemyslaw Klys a47fa85a8c RequireDays for Remove-GPOZaurr added 2020-12-11 10:49:00 +01:00
Przemyslaw Klys b156c91c7c Improvement to GPOList 2020-12-11 10:48:51 +01:00
Przemyslaw Klys d44e27e68c Day counting adding 2020-12-11 10:48:41 +01:00
Przemyslaw Klys e5dc00007f Remove dead code 2020-12-11 10:48:34 +01:00
Przemyslaw Klys c31c8257a3 Color adjustment 2020-12-10 11:16:20 +01:00
Przemyslaw Klys b135fc3c7f Update Readme/PSD1 2020-12-10 11:16:08 +01:00
Przemyslaw Klys 0699cdf2ff Fix and Improvement Get-GPOZaurr 2020-12-10 11:04:10 +01:00
Przemyslaw Klys fb366e5e78 Update for Invoke-GPOZaurrSupport 2020-12-10 11:03:59 +01:00
Przemyslaw Klys 6456325584 update PSD1 2020-12-10 11:03:21 +01:00
64 changed files with 1326 additions and 361 deletions
@@ -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
+41
View File
@@ -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, SYSVOL -LimitProcessing 1 #-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
@@ -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 -1
View File
@@ -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
+2 -2
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
# Extracts CSE from registry
$AllRegistryExtensions = Find-CSExtension
+2 -5
View File
@@ -1,7 +1,4 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$Output = Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOOrphans -PassThru
$Output
Write-Color -Text 'Output of nested report' -Color DarkYellow -LinesBefore 1 -LinesAfter 1
$Output.GPOOrphans
#$Output = Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -PassThru -Type GPOConsistency, GPOList, GPODuplicates, GPOOrphans, GPOOwners, NetLogonOwners, GPOPermissionsRead, GPOPermissionsAdministrative,GPOPermissionsUnknown
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOPermissions,GPOPermissionsRead
+1 -1
View File
@@ -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, GPOOrphans, GPOOwners, NetLogonOwners, GPOPermissionsRead, GPOPermissionsAdministrative, GPOPermissionsUnknown, GPOPermissions
+7
View File
@@ -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 *
+2 -2
View File
@@ -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 *
+3
View File
@@ -0,0 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Repair-GPOZaurrPermission -Verbose -WhatIf -Type Administrative -LimitProcessing 1
+3 -3
View File
@@ -6,9 +6,9 @@
CompatiblePSEditions = @('Desktop')
Copyright = '(c) 2011 - 2020 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-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-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.97'
ModuleVersion = '0.0.101'
PowerShellVersion = '5.1'
PrivateData = @{
PSData = @{
@@ -18,7 +18,7 @@
}
}
RequiredModules = @(@{
ModuleVersion = '0.0.189'
ModuleVersion = '0.0.192'
ModuleName = 'PSSharedGoods'
Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
}, @{
+2 -2
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLDriveMapSettings {
function ConvertTo-XMLDriveMapSettings {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+1 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLGenericPolicy {
function ConvertTo-XMLGenericPolicy {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+1 -1
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLLocalGroups {
function ConvertTo-XMLLocalGroups {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+1 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLPrinter {
function ConvertTo-XMLPrinter {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+1 -1
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
function ConvertTo-XMLTaskScheduler {
function ConvertTo-XMLTaskScheduler {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+1 -1
View File
@@ -1,4 +1,4 @@
function Get-GPOCategories {
function Get-GPOCategories {
[cmdletBinding()]
param(
[PSCustomObject] $GPO,
+5 -2
View File
@@ -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
}
+1
View File
@@ -217,6 +217,7 @@
'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
+1 -1
View File
@@ -155,7 +155,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 -1
View File
@@ -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
}
}
}
+38 -22
View File
@@ -47,7 +47,16 @@
if (-not $Script:Reporting['GPOList']['Variables']['GPOApplypermissionNoPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOList']['Variables']['GPOApplypermissionNoPerDomain'][$GPO.DomainName] = 0
}
if ($GPO.Enabled -eq $false -or $GPO.Empty -eq $true -or $GPO.Linked -eq $false -or $GPO.ApplyPermission -eq $false) {
if ($GPO.Days -le $Script:Reporting['GPOList']['Variables']['GPOOlderThan']) {
# Skip GPOS that are younger than 7 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 7 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 {
@@ -133,13 +142,14 @@
}
}
$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 = @{
GPOOlderThan = 7
GPONotValidPerDomain = $null
GPOValidPerDomain = $null
GPONotOptimizedPerDomain = $null
@@ -170,8 +180,10 @@
GPOLinkedButEmpty = 0
GPOEnabled = 0
GPODisabled = 0
GPOSkip = 0
GPOValid = 0
GPONotValid = 0
GPONotValidButSkip = 0
GPOLinkedButLinkDisabled = 0
GPOTotal = 0
ApplyPermissionYes = 0
@@ -191,7 +203,7 @@
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
@@ -200,7 +212,11 @@
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'], " (not older than $($Script:Reporting['GPOList']['Variables']['GPOOlderThan']) days)"
) -FontWeight 'normal', 'bold', 'normal', 'bold', 'normal' -Color 'Black', 'Red', 'Black', 'Red', 'Black'
New-HTMLListItem -Text "Group Policies younger than $($Script:Reporting['GPOList']['Variables']['GPOOlderThan']) days: ", $Script:Reporting['GPOList']['Variables']['GPOSkip'], " (not older than $($Script:Reporting['GPOList']['Variables']['GPOOlderThan']) days)" -FontWeight normal, bold
} -FontSize 10pt
New-HTMLText -Text 'Following domains require actions (permissions required):' -FontSize 10pt -FontWeight bold
@@ -392,7 +408,7 @@
"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 7 -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'
@@ -416,26 +432,26 @@
"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 -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
Remove-GPOZaurr -RequireDays 7 -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 -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
Remove-GPOZaurr -RequireDays 7 -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 -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
Remove-GPOZaurr -RequireDays 7 -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 -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
Remove-GPOZaurr -RequireDays 7 -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."
@@ -455,26 +471,26 @@
"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 Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
Remove-GPOZaurr -RequireDays 7 -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 Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
Remove-GPOZaurr -RequireDays 7 -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 Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
Remove-GPOZaurr -RequireDays 7 -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 Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
Remove-GPOZaurr -RequireDays 7 -Type Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"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."
@@ -497,26 +513,26 @@
""
}
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -Type Disabled -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
Remove-GPOZaurr -RequireDays 7 -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 7 -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 7 -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 7 -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. "
@@ -539,26 +555,26 @@
""
}
New-HTMLCodeBlock -Code {
Remove-GPOZaurr -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
Remove-GPOZaurr -RequireDays 7 -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 -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
Remove-GPOZaurr -RequireDays 7 -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 -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
Remove-GPOZaurr -RequireDays 7 -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 -Type NoApplyPermission -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
Remove-GPOZaurr -RequireDays 7 -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. "
@@ -612,7 +628,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
}
}
}
+3 -3
View File
@@ -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
}
}
@@ -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
# }
# }
# }
@@ -283,7 +283,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
}
}
}
+93 -42
View File
@@ -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
}
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 {
@@ -243,6 +256,44 @@
"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."
@@ -252,14 +303,14 @@
}
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
}
+1 -1
View File
@@ -217,7 +217,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
}
}
}
@@ -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,17 +85,22 @@
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
}
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
}
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
New-HTMLSection -Name 'Steps to fix Group Policy Administrative Users' {
New-HTMLContainer {
@@ -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,576 @@
$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 users 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
}
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
}
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
}
}
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'
}
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
}
}
}
}
}
+4 -4
View File
@@ -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
@@ -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
}
}
}
@@ -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
}
}
}
+31 -16
View File
@@ -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
+16 -17
View File
@@ -1,4 +1,4 @@
function New-GPOZaurrReportHTML {
function New-GPOZaurrReportHTML {
[cmdletBinding()]
param(
[System.Collections.IDictionary] $Support,
@@ -23,43 +23,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 +80,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 {
+2 -2
View File
@@ -1,11 +1,11 @@
$Script:GPOConfiguration = [ordered] @{
GPOOrphans = $GPOZaurrOrphans
GPOBroken = $GPOZaurrOrphans
GPOOwners = $GPOZaurrOwners
GPOConsistency = $GPOZaurrConsistency
GPODuplicates = $GPOZaurrDuplicates
GPOList = $GPOZaurrList
GPOPassword = $GPOZaurrPassword
GPOPermissions = $GPOZaurrPermissions
GPOPermissions = $GPOZaurrPermissionsAnalysis
GPOPermissionsAdministrative = $GPOZaurrPermissionsAdministrative
GPOPermissionsRead = $GPOZaurrPermissionsRead
GPOPermissionsRoot = $GPOZaurrPermissionsRoot
+35 -57
View File
@@ -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
}
}
+3 -3
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
function Clear-GPOZaurrSysvolDFSR {
function Clear-GPOZaurrSysvolDFSR {
[cmdletBinding(SupportsShouldProcess)]
param(
[alias('ForestName')][string] $Forest,
+1 -1
View File
@@ -1,4 +1,4 @@
function ConvertFrom-CSExtension {
function ConvertFrom-CSExtension {
[cmdletBinding()]
param(
[string[]] $CSE,
+1 -1
View File
@@ -1,4 +1,4 @@
function Find-CSExtension {
function Find-CSExtension {
[cmdletBinding()]
param(
[string[]] $CSE,
+30 -47
View File
@@ -54,58 +54,41 @@
$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
} else {
$GPO
}
}
}
+58 -16
View File
@@ -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 {
+1 -1
View File
@@ -1,4 +1,4 @@
function Get-GPOZaurrFilesPolicyDefinition {
function Get-GPOZaurrFilesPolicyDefinition {
[alias('Get-GPOZaurrFilesPolicyDefinitions')]
[cmdletbinding()]
param(
+1 -1
View File
@@ -1,4 +1,4 @@
function Get-GPOZaurrFolders {
function Get-GPOZaurrFolders {
[cmdletBinding()]
param(
[ValidateSet('All', 'Netlogon', 'Sysvol')][string[]] $Type = 'All',
-19
View File
@@ -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) {
+87
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
function Get-GPOZaurrSysvolDFSR {
function Get-GPOZaurrSysvolDFSR {
[cmdletBinding()]
param(
[alias('ForestName')][string] $Forest,
+68 -45
View File
@@ -7,8 +7,8 @@
[string] $Path,
[string] $Splitter = [System.Environment]::NewLine,
[switch] $PreventShow,
[switch] $Offline,
[switch] $ForceGPResult
[switch] $Offline #,
# [switch] $ForceGPResult
)
# if user didn't choose anything, lets run as currently logged in user locally
if (-not $UserName -and -not $ComputerName) {
@@ -54,39 +54,43 @@
if ($UserName) {
$SplatPolicy['User'] = $UserName
}
if ($Command -and -not $ForceGPResult) {
try {
#Write-Verbose "Request-GPOZaurr - ComputerName: $($SplatPolicy['Computer']) UserName: $($SplatPolicy['User'])"
$ResultantSetPolicy = Get-GPResultantSetOfPolicy @SplatPolicy -ErrorAction Stop
} catch {
if ($_.Exception.Message -eq 'Exception from HRESULT: 0x80041003') {
Write-Warning "Request-GPOZaurr - Are you running as admin? $($_.Exception.Message)"
return
} else {
$ErrorMessage = $($_.Exception.Message).Replace([Environment]::NewLine, ' ')
Write-Warning "Request-GPOZaurr - Error: $ErrorMessage"
return
}
$SplatPolicy['TempXmlPath'] = [io.path]::GetTempFileName().Replace('.tmp', ".xml")
# Originally planned to use Get-GPResultantSetOfPolicy but it only works with administrative rights
# if ($Command -and -not $ForceGPResult) {
# try {
# Write-Verbose "Invoke-GPOZaurrSupport - ComputerName: $($SplatPolicy['Computer']), UserName: $($SplatPolicy['User']), ReportType: $($SplatPolicy['ReportType']), Path: $($SplatPolicy['Path'])"
# $ResultantSetPolicy = Get-GPResultantSetOfPolicy @SplatPolicy -ErrorAction Stop
# } catch {
# if ($_.Exception.Message -eq 'Exception from HRESULT: 0x80041003') {
# Write-Warning "Invoke-GPOZaurrSupport - Are you running as admin? $($_.Exception.Message)"
# return
# } else {
# $ErrorMessage = $($_.Exception.Message).Replace([Environment]::NewLine, ' ')
# Write-Warning "Invoke-GPOZaurrSupport - Error: $ErrorMessage"
# return
# }
# }
# } else {
$Arguments = @(
if ($SplatPolicy['Computer']) {
"/S $ComputerName"
}
} else {
$Arguments = @(
if ($SplatPolicy['Computer']) {
"/S $ComputerName"
}
if ($SplatPolicy['User']) {
"/USER $($SplatPolicy['User'])"
}
if ($SplatPolicy['ReportType'] -eq 'HTML') {
'/H'
} elseif ($SplatPolicy['ReportType'] -eq 'XML') {
'/X'
}
if ($SplatPolicy['User']) {
"/USER $($SplatPolicy['User'])"
}
if ($SplatPolicy['ReportType'] -eq 'HTML') {
'/H'
$SplatPolicy['Path']
"/F"
)
Write-Verbose "Invoke-GPOZaurrSupport - GPResult Arguments: $Arguments"
Start-Process -NoNewWindow -FilePath 'gpresult' -ArgumentList $Arguments -Wait
}
} elseif ($SplatPolicy['ReportType'] -eq 'XML') {
'/X'
$SplatPolicy['TempXmlPath']
}
"/F"
)
Write-Verbose "Invoke-GPOZaurrSupport - GPResult Arguments: $Arguments"
Start-Process -NoNewWindow -FilePath 'gpresult' -ArgumentList $Arguments -Wait
#}
if ($Type -eq 'NativeHTML') {
if (-not $PreventShow) {
Write-Verbose "Invoke-GPOZaurrSupport - Opening up file $($SplatPolicy['Path'])"
@@ -95,39 +99,58 @@
return
}
# Loads created XML by resultant Output
if ($SplatPolicy.Path -and (Test-Path -LiteralPath $SplatPolicy.Path)) {
[xml] $PolicyContent = Get-Content -LiteralPath $SplatPolicy.Path
if ($SplatPolicy.TempXmlPath -and (Test-Path -LiteralPath $SplatPolicy.TempXmlPath)) {
[xml] $PolicyContent = Get-Content -LiteralPath $SplatPolicy.TempXmlPath
if ($PolicyContent) {
# lets remove temporary XML file
Remove-Item -LiteralPath $SplatPolicy.Path
Remove-Item -LiteralPath $SplatPolicy.TempXmlPath
} else {
Write-Warning "Request-GPOZaurr - Couldn't load XML file from drive $($SplatPolicy.Path). Terminating."
Write-Warning "Invoke-GPOZaurrSupport - Couldn't load XML file from drive $($SplatPolicy.TempXmlPath). Terminating."
return
}
} else {
Write-Warning "Request-GPOZaurr - Couldn't find XML file on drive $($SplatPolicy.Path). Terminating."
Write-Warning "Invoke-GPOZaurrSupport - Couldn't find XML file on drive $($SplatPolicy.TempXmlPath). Terminating."
return
}
if ($ComputerName) {
if (-not $PolicyContent.Rsop.'ComputerResults'.EventsDetails) {
Write-Warning "Request-GPOZaurr - Windows Events for Group Policy are missing. Amount of data will be limited. Firewall issue?"
Write-Warning "Invoke-GPOZaurrSupport - Windows Events for Group Policy are missing. Amount of data will be limited. Firewall issue?"
}
}
if (-not $ComputerName) {
# Ok, user haven't given computername, and we're not admin, so RSOP won't be there, but we will use $ComputerName further down to get additional data, even without administrative rights
# Also for display purposes
$ComputerName = $Env:COMPUTERNAME
}
if ($Type -eq 'XML') {
$PolicyContent.Rsop
} else {
if ($VerbosePreference -ne 'SilentlyContinue') {
$Verbose = $true
} else {
$Verbose = $false
}
$Output = [ordered] @{
ComputerInformation = Get-Computer -ComputerName $ComputerName
ResultantSetPolicy = $ResultantSetPolicy
ComputerInformation = Get-Computer -ComputerName $ComputerName -Verbose:$Verbose
#ResultantSetPolicy = $ResultantSetPolicy
<# ResultantSetPolicy = $ResultantSetPolicy
RunspaceId : 5a4931ea-915e-42d3-80d8-6a86b16eb271
RsopMode : Logging
Namespace : \\EVOSPEED\Root\Rsop\NS103F4892_39E9_42B8_B0FF_E438EC0796B5
LoggingComputer : EVOSPEED
LoggingUser : EVOTEC\przemyslaw.klys
LoggingMode : UserAndComputer
#>
}
if ($PolicyContent.Rsop.ComputerResults) {
$Output.ComputerResults = ConvertFrom-XMLRSOP -Content $PolicyContent.Rsop -ResultantSetPolicy $ResultantSetPolicy -ResultsType 'ComputerResults' -Splitter $Splitter
$Output.ComputerResults = ConvertFrom-XMLRSOP -Content $PolicyContent.Rsop -ResultsType 'ComputerResults' -Splitter $Splitter
}
if ($PolicyContent.Rsop.UserResults) {
$Output.UserResults = ConvertFrom-XMLRSOP -Content $PolicyContent.Rsop -ResultantSetPolicy $ResultantSetPolicy -ResultsType 'UserResults' -Splitter $Splitter
$Output.UserResults = ConvertFrom-XMLRSOP -Content $PolicyContent.Rsop -ResultsType 'UserResults' -Splitter $Splitter
}
New-GPOZaurrReportConsole -Results $Output
New-GPOZaurrReportConsole -Results $Output -ComputerName $ComputerName
if ($Type -contains 'Object') {
$Output
} elseif ($Type -contains 'HTML') {
+10 -3
View File
@@ -10,7 +10,8 @@
[System.Collections.IDictionary] $ExtendedForestInformation,
[string[]] $GPOPath,
[string] $BackupPath,
[switch] $BackupDated
[switch] $BackupDated,
[int] $RequireDays
)
Begin {
if ($BackupPath) {
@@ -60,13 +61,19 @@
$DeleteRequired = $true
}
}
if ($RequireDays) {
if ($RequireDays -ge $_.Days) {
# GPO was modified recently and we don't want to touch it yet, maybe edit is in progress
$DeleteRequired = $false
}
}
if ($_.Exclude -eq $true) {
Write-Verbose "Remove-GPOZaurr - Excluded GPO $($_.DisplayName) from $($_.DomainName). Skipping!"
} elseif ($DeleteRequired) {
if ($BackupRequired) {
try {
Write-Verbose "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)"
$BackupInfo = Backup-GPO -Guid $_.Guid -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer
$BackupInfo = Backup-GPO -Guid $_.Guid -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop
$BackupInfo
$BackupOK = $true
} catch {
@@ -77,7 +84,7 @@
if (($BackupRequired -and $BackupOK) -or (-not $BackupRequired)) {
try {
Write-Verbose "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName)"
Remove-GPO -Domain $_.DomainName -Guid $_.Guid -ErrorAction Stop #-Server $QueryServer
Remove-GPO -Domain $_.DomainName -Guid $_.Guid -ErrorAction Stop
} catch {
Write-Warning "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)"
}
+58 -6
View File
@@ -1,8 +1,54 @@
function Remove-GPOZaurrBroken {
<#
.SYNOPSIS
Finds and removes broken Group Policies from SYSVOL or AD or both.
.DESCRIPTION
Finds and removes broken Group Policies from SYSVOL or AD or both. Assesment is based on Get-GPOZaurrBroken and there are 3 supported types:
- AD - meaning GPOs which have no SYSVOL content will be deleted from AD
- SYSVOL - meaning GPOs which have no AD content will be deleted from SYSVOL
- ObjectClass - meaning GPOs which have ObjectClass category of Container rather than groupPolicyContainer will be deleted from AD & SYSVOL
.PARAMETER Type
Choose one or more types to delete. Options are AD, ObjectClass, SYSVOL
.PARAMETER BackupPath
Path to optional backup of SYSVOL content before deletion
.PARAMETER BackupDated
Forces backup to be created within folder that has date in it
.PARAMETER LimitProcessing
Allows to specify maximum number of items that will be fixed in a single run. It doesn't affect amount of GPOs processed
.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
Remove-GPOZaurrBroken -Verbose -WhatIf -Type AD, SYSVOL
.EXAMPLE
Remove-GPOZaurrBroken -Verbose -WhatIf -Type AD, SYSVOL -IncludeDomains 'ad.evotec.pl' -LimitProcessing 2
.EXAMPLE
Remove-GPOZaurrBroken -Verbose -IncludeDomains 'ad.evotec.xyz' -BackupPath $Env:UserProfile\Desktop\MyBackup1 -WhatIf -Type AD, SYSVOL
.NOTES
General notes
#>
[alias('Remove-GPOZaurrOrphaned')]
[cmdletBinding(SupportsShouldProcess)]
param(
[ValidateSet('SYSVOL', 'AD')][string[]] $Type = @('SYSVOL', 'AD'),
[parameter(Mandatory, Position = 0)][ValidateSet('SYSVOL', 'AD', 'ObjectClass')][string[]] $Type,
[string] $BackupPath,
[switch] $BackupDated,
[int] $LimitProcessing = [int32]::MaxValue,
@@ -32,10 +78,15 @@
$_
}
}
if ($Type -contains 'ObjectClass') {
if ($_.Status -eq 'ObjectClass issue') {
$_
}
}
} | Select-Object | Select-Object -First $LimitProcessing | ForEach-Object {
$GPO = $_
if ($GPO.Status -eq 'Not available in AD') {
Write-Verbose "Remove-GPOZaurrBroken - Processing [AD] $($GPO.Path)"
if ($GPO.Status -in 'Not available in AD', 'ObjectClass issue') {
Write-Verbose "Remove-GPOZaurrBroken - Removing from SYSVOL [$($GPO.Status)] $($GPO.Path)"
if ($BackupFinalPath) {
Try {
Write-Verbose "Remove-GPOZaurrBroken - Backing up $($GPO.Path)"
@@ -47,15 +98,16 @@
}
}
if ($BackupWorked -or $BackupFinalPath -eq '') {
Write-Verbose "Remove-GPOZaurrBroken - Deleting $($GPO.Path)"
Write-Verbose "Remove-GPOZaurrBroken - Removing $($GPO.Path)"
try {
Remove-Item -Recurse -Force -LiteralPath $GPO.Path -ErrorAction Stop
} catch {
Write-Warning "Remove-GPOZaurrBroken - Failed to remove file $($GPO.Path): $($_.Exception.Message)."
}
}
} elseif ($GPO.Status -eq 'Not available on SYSVOL') {
Write-Verbose "Remove-GPOZaurrBroken - Processing [SYSVOL] $($GPO.DistinguishedName)"
}
if ($GPO.Status -in 'Not available on SYSVOL', 'ObjectClass issue') {
Write-Verbose "Remove-GPOZaurrBroken - Removing from AD [$($GPO.Status)] $($GPO.DistinguishedName)"
try {
$ExistingObject = Get-ADObject -Identity $GPO.DistinguishedName -Server $GPO.DomainName -ErrorAction Stop
} catch {
+1 -1
View File
@@ -1,4 +1,4 @@
function Remove-GPOZaurrFolders {
function Remove-GPOZaurrFolders {
[cmdletBinding(SupportsShouldProcess)]
param(
[string] $BackupPath,
+57
View File
@@ -0,0 +1,57 @@
function Repair-GPOZaurrPermission {
[cmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory)][ValidateSet('AuthenticatedUsers', 'Unknown', 'System', 'Administrative', 'All')][string[]] $Type,
[alias('ForestName')][string] $Forest,
[string[]] $ExcludeDomains,
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[System.Collections.IDictionary] $ExtendedForestInformation,
[int] $LimitProcessing = [int32]::MaxValue
)
Get-GPOZaurrPermissionAnalysis -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains | Where-Object {
$RequiresProcessing = $false
if ($_.Status -eq $false) {
if ($Type -contains 'System' -or $Type -contains 'All') {
if ($_.System -eq $false) {
$RequiresProcessing = $true
}
}
if ($Type -contains 'Administrative' -or $Type -contains 'All') {
if ($_.Administrative -eq $false) {
$RequiresProcessing = $true
}
}
if ($Type -contains 'AuthenticatedUsers' -or $Type -contains 'All') {
if ($_.AuthenticatedUsers -eq $false) {
$RequiresProcessing = $true
}
}
if ($Type -contains 'Unknown' -or $Type -contains 'All') {
if ($_.Unknown -eq $true) {
$RequiresProcessing = $true
}
}
if ($RequiresProcessing -eq $true) {
$_
}
}
} | Select-Object -First $LimitProcessing | ForEach-Object {
$GPO = $_
if ($GPO.Status -eq $false) {
if ($GPO.System -eq $false) {
Add-GPOZaurrPermission -Type WellKnownAdministrative -PermissionType GpoEditDeleteModifySecurity -GPOGuid $GPO.GUID -IncludeDomains $GPO.DomainName
}
if ($GPO.Administrative -eq $false) {
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -GPOGuid $GPO.GUID -IncludeDomains $GPO.DomainName
}
if ($GPO.AuthenticatedUsers -eq $false) {
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -GPOGuid $GPO.GUID -IncludeDomains $GPO.DomainName
}
if ($GPO.Unknown -eq $true) {
Remove-GPOZaurrPermission -Type Unknown -GPOGuid $GPO.GUID -IncludeDomains $GPO.DomainName
}
}
}
}
+35
View File
@@ -57,6 +57,41 @@ That's it. Whenever there's a new version, you run the command, and you can enjo
## Changelog
- 0.0.101 - 23.12.2020
- [x] Improved `Get-GPOZaurrBroken`
- [x] It now detects `ObjectClass Issue`
- [x] Heavily improved performance
- [x] Removed some useless properties for this particular cmdlet
- [x] All states: `Not available on SYSVOL`, `Not available in AD`, `Exists`, `Permissions Issue`, `ObjectClass Issue`
- [x] Improved help
- [x] Improved `Remove-GPOZaurrBroken`
- [x] It now deals with `ObjectClass Issue`
- [x] Heavily improved performance
- [x] Removed some useless properties for this particular cmdlet
- [x] Now requires manual type insert AD, SYSVOL or ObjectClass (or all of them). Before it was auto using AD/SYSVOL.
- [x] Improved help
- [x] Improved `Invoke-GPOZaurr`
- [x] Type `GPOList`
- [x] Renamed `GPOOrphans` to `GPOBroken`
- [x] Improved `GPOBroken` with `ObjectClass issue`
- 0.0.100 - 21.12.2020
- [x] Improved `Invoke-GPOZaurr`
- [x] Type `GPOPermissionsRead`
- [x] Type `GPOPermissions`
- 0.0.99 - 13.12.2020
- [x] Improved `Invoke-GPOZaurr`
- [x] Type `GPOList` - require GPO to be 7 days old for deletion to be proposed
- [x] Type `GPOPermissions` - one stop for permissions
- [x] Allows Steps to be chosen via their menu and out-of-order
- [x] Improved `Remove-GPOZaurr` - added `RequireDays` parameter to prevent deletion of just modified GPOs
- [x] Added `Get-GPOZaurrPermissionAnalysis`
- [x] Added `Repair-GPOZaurrPermission`
- 0.0.98 - 10.12.2020
- [x] Improved `Invoke-GPOZaurr`
- [x] Type `GPOList` - fixed unexpected ending of cmdlet when error occurs (for example deleted GPO while script is running) which could impact results
- [x] Other types - small color adjustment
- [x] Fixed/Improved `Get-GPOZaurr` - fixed unexpected ending of cmdlet when error occurs (for example deleted GPO while script is running), improved code base
- [x] Improved `Invoke-GPOZaurrSupport`
- 0.0.97 - 07.12.2020
- [x] Improved `Invoke-GPOZaurr`
- [x] Type `GPOList` - added more data, did small reorganization