Compare commits

..

28 Commits

Author SHA1 Message Date
Przemyslaw Klys 7eefe96ee7 Update 2020-11-12 13:38:51 +01:00
Przemyslaw Klys a54f183ed3 Update 2020-11-12 12:18:35 +01:00
Przemyslaw Klys f5b73918bb Update 2020-11-11 22:36:53 +01:00
Przemyslaw Klys 25a59572dd Update 2020-11-11 22:34:29 +01:00
Przemyslaw Klys a6a847d720 Update 2020-11-11 21:27:04 +01:00
Przemyslaw Klys 20d005f600 Update 2020-11-11 21:24:07 +01:00
Przemyslaw Klys 7b2f2c69be Update 2020-11-11 17:12:22 +01:00
Przemyslaw Klys 1126071fc4 Examples update 2020-11-11 17:06:29 +01:00
Przemyslaw Klys 70fbc2d5f8 More improvements to Add-GPOZaurrPermission 2020-11-11 17:06:06 +01:00
Przemyslaw Klys fd844fd7a2 Add-GPOZaurrPermission improvements 2020-11-11 17:05:51 +01:00
Przemyslaw Klys a258689880 Added support for -All 2020-11-11 12:58:40 +01:00
Przemyslaw Klys 268b2f76f5 Update PSD1 2020-11-10 22:23:03 +01:00
Przemyslaw Klys ec90f38ad9 Update 2020-11-10 22:21:36 +01:00
Przemyslaw Klys aaf83b68de Update 2020-11-10 22:11:40 +01:00
Przemyslaw Klys 7ba8891b26 Update readme 2020-11-10 09:38:20 +01:00
Przemyslaw Klys 2df56e72b5 Update 2020-11-10 09:31:38 +01:00
Przemyslaw Klys 1bc966c409 Tests 2020-11-10 09:30:46 +01:00
Przemyslaw Klys 887608b7b8 Update Example 2020-11-09 23:36:41 +01:00
Przemyslaw Klys f8b3be0f68 Update 2020-11-09 23:35:21 +01:00
Przemyslaw Klys 826460f739 readme update 2020-11-09 09:45:28 +01:00
Przemyslaw Klys 9e34f4297c Update 2020-11-09 09:45:04 +01:00
Przemyslaw Klys 0da051a53b PSD1 update 2020-11-08 17:40:55 +01:00
Przemyslaw Klys f5fb9e2dee Update 2020-11-08 17:40:36 +01:00
Przemyslaw Klys 9784370c77 PSD1 update 2020-11-08 17:11:23 +01:00
Przemyslaw Klys 83363bb843 Update 2020-11-08 17:11:17 +01:00
Przemyslaw Klys 6c2e774b10 Update readme 2020-11-08 15:25:53 +01:00
Przemyslaw Klys b70cccf0db Update 2020-11-08 15:25:26 +01:00
Przemyslaw Klys 1788615711 Update 2020-11-07 23:06:02 +01:00
35 changed files with 840 additions and 329 deletions
+1 -2
View File
@@ -1,8 +1,7 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
# Backup GPOs
$BackupPath = "$Env:UserProfile\Desktop\GPO"
$GPOSummary = Backup-GPOZaurr -BackupPath $BackupPath -Verbose -Type All #-BackupDated #-LimitProcessing 1
$GPOSummary = Backup-GPOZaurr -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -Type All -IncludeDomains 'ad.evotec.pl' #-BackupDated #-LimitProcessing 1
$GPOSummary | Format-Table -AutoSize
## Confirm GPOs are backed up properly
+7
View File
@@ -0,0 +1,7 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
#$GPOS = Get-GPOZaurr -GPOName 'TEST | Office Configuration'
#$GPOS | Format-Table -AutoSize *
$GPOS = Get-GPOZaurr -GPOName 'New Group Policy Object3'
$GPOS | Format-Table -AutoSize *
@@ -9,7 +9,7 @@ $GPOs | Format-Table DisplayName, Owner, OwnerSID, OwnerType
Set-GPOZaurrOwner -GPOName 'ALL | Enable RDP' -WhatIf
# If principal is given it is set (of course if it exits). Otherwise warning is returned.
Set-GPOZaurrOwner -GPOName 'ALL | Enable RDP' -Principal 'przemyslaw.klys' #-WhatIf
Set-GPOZaurrOwner -GPOName 'ALL | Enable RDP' -Principal 'przemyslaw.klys' -WhatIf
$GPOs = Get-GPOZaurr #-GPOName 'New Group Policy Object'
$GPOs | Format-Table DisplayName, Owner, OwnerSID, OwnerType
+5
View File
@@ -0,0 +1,5 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -LimitProcessing 3 -All -WhatIf -Verbose #-IncludeDomains 'ad.evotec.pl'
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -LimitProcessing 100 -All -WhatIf -Verbose #-IncludeDomains 'ad.evotec.pl'
+3
View File
@@ -0,0 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Add-GPOZaurrPermission -GPOName 'New Group Policy Object' -Type AuthenticatedUsers -PermissionType GpoRead -Verbose -WhatIf
+3
View File
@@ -0,0 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Get-GPOZaurrPermission -IncludePermissionType GpoRead -Type AuthenticatedUsers -ReturnSecurityWhenNoData | Format-Table
@@ -1,17 +1,23 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Clear-Host
$T = Get-GPOZaurrPermission -GPOName 'ALL | Enable RDP' #-IncludeGPOObject #-ExcludePermissionType GpoApply,GpoRead -IncludeGPOObject
$T | Format-Table -AutoSize *
Add-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEdit -Principal 'przemyslaw.klys' -Verbose
#Add-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEdit -Principal 'CN=Przemysław Kłys,OU=Users,OU=Accounts,OU=Production,DC=ad,DC=evotec,DC=xyz' -PrincipalType DistinguishedName -Verbose #-WhatIf
#Add-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEdit -Principal 'CN=Administrator,OU=Special,OU=Accounts,OU=Production,DC=ad,DC=evotec,DC=xyz' -PrincipalType DistinguishedName -Verbose #-WhatIf
Add-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEdit -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose #-WhatIf
Add-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEdit -Principal 'S-1-5-21-853615985-2870445339-3163598659-1105' -PrincipalType Sid -Verbose #-WhatIf
$T = Get-GPOZaurrPermission -GPOName 'ALL | Enable RDP' #-ExcludePermissionType GpoApply,GpoRead -IncludeGPOObject
$T | Format-Table -AutoSize *
Add-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEditDeleteModifySecurity -Principal 'Domain Admins' -Verbose
Remove-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEdit -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose
Add-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEditDeleteModifySecurity -Principal 'Domain Admins' -PrincipalType Name -Verbose #-WhatIf
Remove-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEdit -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose #-WhatIf
Remove-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEdit -Principal 'EVOTEC\przemyslaw.klys' -PrincipalType NetbiosName -Verbose #-WhatIf
Remove-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEdit -Principal 'CN=Przemysław Kłys,OU=Users,OU=Accounts,OU=Production,DC=ad,DC=evotec,DC=xyz' -PrincipalType DistinguishedName -Verbose #-WhatIf
Remove-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEdit -Type NotAdministrative -Verbose
Remove-GPOZaurrPermission -GPOName 'ALL | Enable RDP' -PermissionType GpoEditDeleteModifySecurity -PrincipalType DistinguishedName -Principal 'CN=Domain Admins,CN=Users,DC=ad,DC=evotec,DC=pl' -Verbose
$T = Get-GPOZaurrPermission -GPOName 'ALL | Enable RDP' #-ExcludePermissionType GpoApply,GpoRead -IncludeGPOObject
$T | Format-Table -AutoSize *
@@ -1,7 +1,10 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
# Find broken GPOs
Get-GPOZaurrBroken -Verbose -IncludeDomains 'ad.evotec.pl' | Format-Table
# this allows you to process X amount of orphaned folders/files (good for testing)
Remove-GPOZaurrOrphaned -Verbose -WhatIf -IncludeDomains 'ad.evotec.xyz' #-LimitProcessing 2
Remove-GPOZaurrBroken -Verbose -WhatIf -IncludeDomains 'ad.evotec.pl' #-LimitProcessing 2
# this runs for whole SYSVOL and checks things against GPOS
Remove-GPOZaurrOrphaned -Verbose -IncludeDomains 'ad.evotec.xyz' -BackupPath $Env:UserProfile\Desktop\MyBackup1 -WhatIf
Remove-GPOZaurrBroken -Verbose -IncludeDomains 'ad.evotec.xyz' -BackupPath $Env:UserProfile\Desktop\MyBackup1 -WhatIf
+2 -2
View File
@@ -1,7 +1,7 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$Output = Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOPassword -PassThru
$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.GPOPassword
$Output.GPOOrphans
+1 -1
View File
@@ -1,3 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Verbose -Type NetLogonPermissions, GPOOrphans, GPOList, GPOConsistency,GPOOwners
Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type NetLogonPermissions, GPOOrphans, GPOList, GPOConsistency, GPOOwners, GPODuplicates
+15
View File
@@ -0,0 +1,15 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$Types = @(
@{ Name = 'GPOOwners'; Path = "$PSScriptRoot\Reports\GPOOwners.html" }
@{ Name = 'GPOConsistency'; Path = "$PSScriptRoot\Reports\GPOConsistency.html" }
@{ Name = 'GPODuplicates'; Path = "$PSScriptRoot\Reports\GPODuplicates.html" }
@{ Name = 'GPOList'; Path = "$PSScriptRoot\Reports\GPOList.html" }
@{ Name = 'GPOOrphans'; Path = "$PSScriptRoot\Reports\GPOOrphans.html" }
@{ Name = 'GPOPassword'; Path = "$PSScriptRoot\Reports\GPOPassword.html" }
@{ Name = 'NetLogonPermissions'; Path = "$PSScriptRoot\Reports\NetLogonPermissions.html" }
)
foreach ($Type in $Types) {
Invoke-GPOZaurr -FilePath $Type.Path -Type $Type.Name -HideHTML
}
+2
View File
@@ -0,0 +1,2 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
+59
View File
@@ -0,0 +1,59 @@
$ModuleName = (Get-ChildItem $PSScriptRoot\*.psd1).BaseName
$PrimaryModule = Get-ChildItem -Path $PSScriptRoot -Filter '*.psd1' -Recurse -ErrorAction SilentlyContinue -Depth 1
if (-not $PrimaryModule) {
throw "Path $PSScriptRoot doesn't contain PSD1 files. Failing tests."
}
if ($PrimaryModule.Count -ne 1) {
throw 'More than one PSD1 files detected. Failing tests.'
}
$PSDInformation = Import-PowerShellDataFile -Path $PrimaryModule.FullName
$RequiredModules = @(
'Pester'
'PSWriteColor'
'PSParseHTML'
if ($PSDInformation.RequiredModules) {
$PSDInformation.RequiredModules
}
)
foreach ($Module in $RequiredModules) {
if ($Module -is [System.Collections.IDictionary]) {
$Exists = Get-Module -ListAvailable -Name $Module.ModuleName
if (-not $Exists) {
Write-Warning "$ModuleName - Downloading $($Module.ModuleName) from PSGallery"
Install-Module -Name $Module.ModuleName -Force -SkipPublisherCheck
}
} else {
$Exists = Get-Module -ListAvailable $Module -ErrorAction SilentlyContinue
if (-not $Exists) {
Install-Module -Name $Module -Force -SkipPublisherCheck
}
}
}
Write-Color 'ModuleName: ', $ModuleName, ' Version: ', $PSDInformation.ModuleVersion -Color Yellow, Green, Yellow, Green -LinesBefore 2
Write-Color 'PowerShell Version: ', $PSVersionTable.PSVersion -Color Yellow, Green
Write-Color 'PowerShell Edition: ', $PSVersionTable.PSEdition -Color Yellow, Green
Write-Color 'Required modules: ' -Color Yellow
foreach ($Module in $PSDInformation.RequiredModules) {
if ($Module -is [System.Collections.IDictionary]) {
Write-Color ' [>] ', $Module.ModuleName, ' Version: ', $Module.ModuleVersion -Color Yellow, Green, Yellow, Green
} else {
Write-Color ' [>] ', $Module -Color Yellow, Green
}
}
Write-Color
Import-Module $PSScriptRoot\*.psd1 -Force
Import-Module Pester -Force
$Configuration = [PesterConfiguration]::Default
$Configuration.Run.Path = "$PSScriptRoot\Tests"
$Configuration.Run.Exit = $true
$Configuration.Should.ErrorAction = 'Continue'
$Configuration.CodeCoverage.Enabled = $false
$Configuration.Output.Verbosity = 'Detailed'
$Result = Invoke-Pester -Configuration $Configuration
#$result = Invoke-Pester -Script $PSScriptRoot\Tests -Verbose -Output Detailed #-EnableExit
if ($Result.FailedCount -gt 0) {
throw "$($Result.FailedCount) tests failed."
}
+4 -4
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-GPOZaurrPermissionRoot', 'Get-GPOZaurrPermissionSummary', 'Get-GPOZaurrSysvolDFSR', 'Get-GPOZaurrWMI', 'Invoke-GPOZaurr', 'Invoke-GPOZaurrContent', 'Invoke-GPOZaurrPermission', 'Invoke-GPOZaurrSupport', 'New-GPOZaurrWMI', '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')
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-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')
GUID = 'f7d4c9e4-0298-4f51-ad77-e8e3febebbde'
ModuleVersion = '0.0.73'
ModuleVersion = '0.0.80'
PowerShellVersion = '5.1'
PrivateData = @{
PSData = @{
@@ -18,11 +18,11 @@
}
}
RequiredModules = @(@{
ModuleVersion = '0.0.186'
ModuleVersion = '0.0.187'
ModuleName = 'PSSharedGoods'
Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
}, @{
ModuleVersion = '0.0.100'
ModuleVersion = '0.0.102'
ModuleName = 'ADEssentials'
Guid = '9fc9fd61-7f11-4f4b-a527-084086f1905f'
}, @{
+62 -14
View File
@@ -6,7 +6,8 @@
[switch] $PermissionsOnly,
[switch] $OwnerOnly,
[System.Collections.IDictionary] $ADAdministrativeGroups,
[string] $Splitter = [System.Environment]::NewLine
[string] $Splitter = [System.Environment]::NewLine,
[switch] $ReturnObject
)
if ($XMLContent.GPO.LinksTo) {
$LinkSplit = ([Array] $XMLContent.GPO.LinksTo).Where( { $_.Enabled -eq $true }, 'Split')
@@ -26,13 +27,11 @@
$LinksDisabledCount = 0
$LinksTotalCount = 0
}
if ($null -eq $XMLContent.GPO.Computer.ExtensionData -and $null -eq $XMLContent.GPO.User.ExtensionData) {
$Empty = $true
} else {
$Empty = $false
}
#if ($null -eq $XMLContent.GPO.Computer.ExtensionData -and $null -eq $XMLContent.GPO.User.ExtensionData) {
# $Empty = $true
#} else {
# $Empty = $false
#}
# Find proper values for enabled/disabled user/computer settings
if ($XMLContent.GPO.Computer.Enabled -eq 'False') {
$ComputerEnabled = $false
@@ -58,12 +57,55 @@
$ComputerSettingsAvailable = if ($null -eq $XMLContent.GPO.Computer.ExtensionData) { $false } else { $true }
$UserSettingsAvailable = if ($null -eq $XMLContent.GPO.User.ExtensionData) { $false } else { $true }
if ($ComputerSettingsAvailable -eq $false -and $UserSettingsAvailable -eq $false) {
$Empty = $true
} else {
$Empty = $false
}
# $OutputUser = $XMLContent.GPO.User.ExtensionData.Extension | Where-Object { $_.PSObject.Properties.TypeNameOfValue -in 'System.Xml.XmlElement', 'System.Object[]' }
# $OutputComputer = $XMLContent.GPO.Computer.ExtensionData.Extension | Where-Object { $_.PSObject.Properties.TypeNameOfValue -in 'System.Xml.XmlElement', 'System.Object[]' }
$OutputUser = foreach ($ExtensionType in $XMLContent.GPO.User.ExtensionData.Extension) {
if ($ExtensionType) {
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
try {
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
} catch {
Write-Warning "Get-XMLStandard - things went sideways $($_.Exception.Message)"
continue
}
}
$KeysToLoop
}
$OutputComputer = foreach ($ExtensionType in $XMLContent.GPO.Computer.ExtensionData.Extension) {
if ($ExtensionType) {
$GPOSettingTypeSplit = ($ExtensionType.type -split ':')
try {
$KeysToLoop = $ExtensionType | Get-Member -MemberType Properties -ErrorAction Stop | Where-Object { $_.Name -notin 'type', $GPOSettingTypeSplit[0] -and $_.Name -notin @('Blocked') }
} catch {
Write-Warning "Get-XMLStandard - things went sideways $($_.Exception.Message)"
continue
}
}
$KeysToLoop
}
$ComputerSettingsAvailableReal = if ($OutputComputer) { $true } else { $false }
$UserSettingsAvailableReal = if ($OutputUser) { $true } else { $false }
if (-not $ComputerSettingsAvailableReal -and -not $UserSettingsAvailableReal) {
$EmptyMaybe = $true
} else {
$EmptyMaybe = $false
}
$ComputerProblem = $false
if ($ComputerEnabled -eq $true -and $ComputerSettingsAvailable -eq $true) {
if ($ComputerEnabled -eq $true -and $ComputerSettingsAvailableReal -eq $true) {
$ComputerOptimized = $true
} elseif ($ComputerEnabled -eq $true -and $ComputerSettingsAvailable -eq $false) {
} elseif ($ComputerEnabled -eq $true -and $ComputerSettingsAvailableReal -eq $false) {
$ComputerOptimized = $false
} elseif ($ComputerEnabled -eq $false -and $ComputerSettingsAvailable -eq $false) {
} elseif ($ComputerEnabled -eq $false -and $ComputerSettingsAvailableReal -eq $false) {
$ComputerOptimized = $true
} else {
# Enabled $false, but ComputerData is there.
@@ -72,11 +114,11 @@
}
$UserProblem = $false
if ($UserEnabled -eq $true -and $UserSettingsAvailable -eq $true) {
if ($UserEnabled -eq $true -and $UserSettingsAvailableReal -eq $true) {
$UserOptimized = $true
} elseif ($UserEnabled -eq $true -and $UserSettingsAvailable -eq $false) {
} elseif ($UserEnabled -eq $true -and $UserSettingsAvailableReal -eq $false) {
$UserOptimized = $false
} elseif ($UserEnabled -eq $false -and $UserSettingsAvailable -eq $false) {
} elseif ($UserEnabled -eq $false -and $UserSettingsAvailableReal -eq $false) {
$UserOptimized = $true
} else {
# Enabled $false, but UserData is there.
@@ -147,6 +189,7 @@
'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text'
'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}'
'Empty' = $Empty
'EmptyMaybe' = $EmptyMaybe
'Linked' = $Linked
'LinksCount' = $LinksTotalCount
'LinksEnabledCount' = $LinksEnabledCount
@@ -160,6 +203,10 @@
'UserProblem' = $UserProblem
'ComputerSettingsAvailable' = $ComputerSettingsAvailable
'UserSettingsAvailable' = $UserSettingsAvailable
'ComputerSettingsAvailableReal' = $ComputerSettingsAvailableReal
'UserSettingsAvailableReal' = $UserSettingsAvailableReal
'ComputerSettingsTypes' = $OutputComputer.Name
'UserSettingsTypes' = $OutputUser.Name
'ComputerSettingsStatus' = if ($XMLContent.GPO.Computer.VersionDirectory -eq 0 -and $XMLContent.GPO.Computer.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" }
'ComputerSetttingsVersionIdentical' = if ($XMLContent.GPO.Computer.VersionDirectory -eq $XMLContent.GPO.Computer.VersionSysvol) { $true } else { $false }
'ComputerSettings' = $XMLContent.GPO.Computer.ExtensionData.Extension
@@ -215,6 +262,7 @@
}
}
}
'GPOObject' = $GPO
}
}
}
+1 -2
View File
@@ -73,9 +73,8 @@
}
New-HTMLPanel {
New-HTMLChart {
# New-ChartLegend -Names 'Bad', 'Good' -Color PaleGreen, Salmon
New-ChartBarOptions -Type barStacked
New-ChartLegend -Name 'Consistent', 'Inconsistent'
New-ChartLegend -Name 'Consistent', 'Inconsistent' -Color PaleGreen, Salmon
New-ChartBar -Name 'TopLevel' -Value $Script:Reporting['GPOConsistency']['Variables']['Consistent'], $Script:Reporting['GPOConsistency']['Variables']['Inconsistent']
New-ChartBar -Name 'Inherited' -Value $Script:Reporting['GPOConsistency']['Variables']['ConsistentInside'], $Script:Reporting['GPOConsistency']['Variables']['InconsistentInside']
} -Title 'Permissions Consistency' -TitleAlignment center
+21 -16
View File
@@ -69,26 +69,31 @@
}
}
Summary = {
New-HTMLText -TextBlock {
"NetLogon is crucial part of Active Directory. Files stored there are available on each and every computer or server in the company. "
"Keeping those files clean and secure is very important task. "
"It's important that NetLogon file owners are set to BUILTIN\Administrators (SID: S-1-5-32-544). "
"Owners have full control over the file object. Current owner of the file may be an Administrator but it doesn't guarentee that he/she will be in the future. "
"That's why as a best-practice it's recommended to change any non-administrative owners to BUILTIN\Administrators, and even Administrative accounts should be replaced with it. "
} -FontSize 10pt
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'NetLogon Files in Total: ', $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwners'] -FontWeight normal, bold
New-HTMLListItem -Text 'NetLogon BUILTIN\Administrators as Owner: ', $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrators'] -FontWeight normal, bold
New-HTMLListItem -Text "NetLogon Owners requiring change: ", $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersToFix'] -FontWeight normal, bold {
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Not Administrative: ', $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersNotAdministrative'] -FontWeight normal, bold
New-HTMLListItem -Text 'Administrative, but not BUILTIN\Administrators: ', $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrativeNotAdministrators'] -FontWeight normal, bold
}
}
} -FontSize 10pt
New-HTMLText -Text "Follow the steps below table to get NetLogon Owners into compliant state." -FontSize 10pt
}
Solution = {
New-HTMLTab -Name 'NetLogon Owners' {
New-HTMLSection -Invisible {
New-HTMLPanel {
New-HTMLText -TextBlock {
"Following table shows NetLogon file owners. It's important that NetLogon file owners are set to BUILTIN\Administrators (SID: S-1-5-32-544). "
"Owners have full control over the file object. Current owner of the file may be an Administrator but it doesn't guarentee that he will be in the future. "
"That's why as a best-practice it's recommended to change any non-administrative owners to BUILTIN\Administrators, and even Administrative accounts should be replaced with it. "
} -FontSize 10pt
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'NetLogon Files in Total: ', $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwners'] -FontWeight normal, bold
New-HTMLListItem -Text 'NetLogon BUILTIN\Administrators as Owner: ', $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrators'] -FontWeight normal, bold
New-HTMLListItem -Text "NetLogon Owners requiring change: ", $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersToFix'] -FontWeight normal, bold {
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Not Administrative: ', $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersNotAdministrative'] -FontWeight normal, bold
New-HTMLListItem -Text 'Administrative, but not BUILTIN\Administrators: ', $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrativeNotAdministrators'] -FontWeight normal, bold
}
}
} -FontSize 10pt
New-HTMLText -Text "Follow the steps below table to get NetLogon Owners into compliant state." -FontSize 10pt
& $Script:GPOConfiguration['NetLogonPermissions']['Summary']
}
New-HTMLPanel {
New-HTMLChart {
+116 -37
View File
@@ -7,15 +7,26 @@
Get-GPOZaurrBroken
}
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
}
if (-not $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'][$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]++
} 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]++
} elseif ($GPO.Status -eq 'Permissions issue') {
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue']++
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName]++
}
}
if ($Script:Reporting['GPOOrphans']['Variables']['ToBeDeleted'].Count -gt 0) {
@@ -25,17 +36,20 @@
}
}
Variables = @{
NotAvailableInAD = 0
NotAvailableOnSysvol = 0
NotAvailablePermissionIssue = 0
ToBeDeleted = 0
NotAvailableInAD = 0
NotAvailableOnSysvol = 0
NotAvailablePermissionIssue = 0
NotAvailablePermissionIssuePerDomain = $null
ToBeDeleted = 0
ToBeDeletedPerDomain = $null
}
Overview = {
<#
New-HTMLPanel {
New-HTMLText -TextBlock {
"Group Policies are stored in two places - Active Directory (metadata) and SYSVOL (content)."
"Since those are managed in different ways, replicated in different ways it's possible because of different issues they get out of sync."
}
} -LineBreak
New-HTMLText -Text "For example:"
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'USN Rollback in AD could cause group policies to reappar in Active Directory, yet SYSVOL data would be unavailable'
@@ -55,12 +69,13 @@
New-ChartBar -Name 'Orphans' -Value $Script:Reporting['GPOOrphans']['Variables']['NotAvailableInAD'], $Script:Reporting['GPOOrphans']['Variables']['NotAvailableOnSysvol'], $Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssue']
} -Title 'Broken / Orphaned Group Policies' -TitleAlignment center
}
#>
}
Summary = {
New-HTMLText -TextBlock {
"Group Policies are stored in two places - Active Directory (metadata) and SYSVOL (content)."
"Since those are managed in different ways, replicated in different ways it's possible because of different issues they get out of sync."
} -FontSize 10pt
} -FontSize 10pt -LineBreak
New-HTMLText -Text "For example:" -FontSize 10pt -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'USN Rollback in AD could cause already deleted Group Policies to reapper in Active Directory, yet SYSVOL data would be unavailable'
@@ -74,6 +89,12 @@
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
} -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
}
} -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
}
Solution = {
@@ -96,18 +117,9 @@
New-HTMLTableCondition -Name 'Status' -Value "Permissions issue" -BackgroundColor MediumVioletRed -ComparisonType string -Color White
} -PagingOptions 10, 20, 30, 40, 50
}
if ($Script:Reporting['GPOOrphans']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
New-HTMLTable -DataTable $Script:Reporting['GPOOrphans']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
}
}
}
New-HTMLSection -Name 'Steps to fix - Not available on SYSVOL / Active Directory' {
New-HTMLContainer {
New-HTMLSpanStyle -FontSize 10pt {
New-HTMLText -Text 'Following steps will guide you how to fix GPOs which are not available on SYSVOL or AD.'
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."
@@ -128,48 +140,107 @@
}
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
New-HTMLCodeBlock -Code {
$GPOOutput = Get-GPOZaurrBroken
$GPOOutput = Get-GPOZaurrBroken -Verbose
$GPOOutput | 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 'Fix GPOs not available on SYSVOL' {
New-HTMLText -Text "Following command when executed runs cleanup procedure that removes all broken GPOs on SYSVOL side."
New-HTMLText -Text "Make sure when running it for the first time to run it with ", "WhatIf", " parameter as shown below to prevent accidental removal." -FontWeight normal, bold, normal -Color Black, Red, Black
New-HTMLCodeBlock -Code {
Remove-GPOZaurrBroken -Type SYSVOL -WhatIf
}
New-HTMLWizardStep -Name 'Make a backup (optional)' {
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. Once happy with results please follow with command: "
"The process fixing broken GPOs will delete AD or SYSVOL content depending on type of a problem. "
"While it's always useful to have a backup, this backup won't actually backup those broken group policies"
" for a simple reason that those are not backupable. You can't back up GPO if there is no SYSVOL content"
" and you can't backup GPO if there's only SYSVOL content. "
"However, since the script does make changes to GPOs it's advised to have a backup anyways! "
}
New-HTMLCodeBlock -Code {
Remove-GPOZaurrBroken -Type SYSVOL -LimitProcessing 2 -BackupPath $Env:UserProfile\Desktop\GPOSYSVOLBackup
$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 {
"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."
"Above command when executed will make a backup to Desktop, create GPO folder and within it it will put all those GPOs. "
}
New-HTMLText -Text "If there's nothing else to be deleted on SYSVOL side, we can skip to next step step"
}
New-HTMLWizardStep -Name 'Fix GPOs not available on AD' {
New-HTMLText -Text "Following command when executed runs cleanup procedure that removes all broken GPOs on Active Directory side."
New-HTMLText -Text "Make sure when running it for the first time to run it with ", "WhatIf", " parameter as shown below to prevent accidental removal." -FontWeight normal, bold, normal -Color Black, Red, Black
New-HTMLWizardStep -Name 'Fix GPOs not available in AD' {
New-HTMLText -Text @(
"Following command when executed runs cleanup procedure that removes all broken GPOs on SYSVOL side. ",
"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 any GPO remains from SYSVOL, that should not be there, as AD metadata is already gone.'
"Please notice I'm using SYSVOL as a type, because the removal will happen on SYSVOL. "
) -FontWeight normal, normal, bold, normal -Color Black, Black, Red, Black
New-HTMLCodeBlock -Code {
Remove-GPOZaurrBroken -Type SYSVOL -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 SYSVOL -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 what backup command does is simply copy SYSVOL content to given place. "
"Since there is no GPO metadata in AD there's no real restore process for this step. "
"It's there to make sure if someone kept some data in there and wants to get access to it, he/she can. "
} -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 AD -WhatIf
Remove-GPOZaurrBroken -Type SYSVOL -LimitProcessing 2 -BackupPath $Env:UserProfile\Desktop\GPOSYSVOLBackup -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. Once happy with results please follow with command: "
"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 AD -LimitProcessing 2 -BackupPath $Env:UserProfile\Desktop\GPOSYSVOLBackup
Remove-GPOZaurrBroken -Type SYSVOL -LimitProcessing 2 -BackupPath $Env:UserProfile\Desktop\GPOSYSVOLBackup -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."
"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 on SYSVOL side, we can skip to next step step. "
}
}
New-HTMLWizardStep -Name 'Fix GPOs not available on SYSVOL' {
New-HTMLText -Text @(
"Following command when executed runs cleanup procedure that removes all broken GPOs on Active Directory side."
"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 any GPO remains from AD, that should not be there, as SYSVOL content is already gone.'
"Please notice I'm using AD as a type, because the removal will happen on AD side. "
) -FontWeight normal, normal, bold, normal -Color Black, Black, Red, Black
New-HTMLCodeBlock -Code {
Remove-GPOZaurrBroken -Type AD -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 AD -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. "
"Since there is no SYSVOL data, and only AD object is there there's no real restore process for this step. "
"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 AD -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 AD -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 on AD side, we can skip to next step step. "
}
New-HTMLText -Text "If there's nothing else to be deleted on AD side, we can skip to next step step"
}
New-HTMLWizardStep -Name 'Verification report' {
New-HTMLText -TextBlock {
@@ -184,5 +255,13 @@
}
}
}
if ($Script:Reporting['GPOOrphans']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
New-HTMLTable -DataTable $Script:Reporting['GPOOrphans']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
}
}
}
}
}
+64 -10
View File
@@ -5,7 +5,18 @@
Data = $null
Execute = { Get-GPOZaurrOwner -IncludeSysvol }
Processing = {
# Create Per Domain Variables
$Script:Reporting['GPOOwners']['Variables']['RequiresDiffFixPerDomain'] = @{}
$Script:Reporting['GPOOwners']['Variables']['WillFixPerDomain'] = @{}
foreach ($GPO in $Script:Reporting['GPOOwners']['Data']) {
# Create Per Domain Variables
if (-not $Script:Reporting['GPOOwners']['Variables']['RequiresDiffFixPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOOwners']['Variables']['RequiresDiffFixPerDomain'][$GPO.DomainName] = 0
}
if (-not $Script:Reporting['GPOOwners']['Variables']['WillFixPerDomain'][$GPO.DomainName]) {
$Script:Reporting['GPOOwners']['Variables']['WillFixPerDomain'][$GPO.DomainName] = 0
}
# Checks
if ($GPO.IsOwnerConsistent) {
$Script:Reporting['GPOOwners']['Variables']['IsConsistent']++
} else {
@@ -18,8 +29,10 @@
}
if (($GPO.IsOwnerAdministrative -eq $false -or $GPO.IsOwnerConsistent -eq $false) -and $GPO.SysvolExists -eq $true) {
$Script:Reporting['GPOOwners']['Variables']['WillFix']++
$Script:Reporting['GPOOwners']['Variables']['WillFixPerDomain'][$GPO.DomainName]++
} elseif ($GPO.SysvolExists -eq $false) {
$Script:Reporting['GPOOwners']['Variables']['RequiresDiffFix']++
$Script:Reporting['GPOOwners']['Variables']['RequiresDiffFixPerDomain'][$GPO.DomainName]++
} else {
$Script:Reporting['GPOOwners']['Variables']['WillNotTouch']++
}
@@ -31,15 +44,18 @@
}
}
Variables = @{
IsAdministrative = 0
IsNotAdministrative = 0
IsConsistent = 0
IsNotConsistent = 0
WillFix = 0
RequiresDiffFix = 0
WillNotTouch = 0
IsAdministrative = 0
IsNotAdministrative = 0
IsConsistent = 0
IsNotConsistent = 0
WillFix = 0
RequiresDiffFix = 0
WillNotTouch = 0
RequiresDiffFixPerDomain = $null
WillFixPerDomain = $null
}
Overview = {
<#
New-HTMLPanel {
New-HTMLText -Text 'Following chart presents Group Policy owners and whether they are administrative and consistent. By design an owner of Group Policy should be Domain Admins or Enterprise Admins group only to prevent malicious takeover. ', `
"It's also important that owner in Active Directory matches owner on SYSVOL (file system)." -FontSize 10pt
@@ -56,6 +72,7 @@
New-ChartBar -Name 'Is consistent' -Value $Script:Reporting['GPOOwners']['Variables']['IsConsistent'], $Script:Reporting['GPOOwners']['Variables']['IsNotConsistent']
} -Title 'Group Policy Owners' -TitleAlignment center
}
#>
}
Summary = {
New-HTMLText -FontSize 10pt -TextBlock {
@@ -77,12 +94,24 @@
New-HTMLListItem -Text "Owners consistent in AD and SYSVOL: ", $Script:Reporting['GPOOwners']['Variables']['IsConsistent'] -FontWeight normal, bold
New-HTMLListItem -Text "Owners not-consistent in AD and SYSVOL: ", $Script:Reporting['GPOOwners']['Variables']['IsNotConsistent'] -FontWeight normal, bold
} -FontSize 10pt
New-HTMLText -FontSize 10pt -Text "This gives us: "
New-HTMLText -FontSize 10pt -Text "Following will need to happen: " -FontWeight bold
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Group Policies requiring owner change: ', $Script:Reporting['GPOOwners']['Variables']['WillFix'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies which can't be fixed (no SYSVOL?): ", $Script:Reporting['GPOOwners']['Variables']['RequiresDiffFix'] -FontWeight normal, bold
New-HTMLListItem -Text "Group Policies unaffected: ", $Script:Reporting['GPOOwners']['Variables']['WillNotTouch'] -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['GPOOwners']['Variables']['WillFixPerDomain'].Keys) {
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOOwners']['Variables']['WillFixPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
}
} -FontSize 10pt
New-HTMLText -Text 'Following domains require fixing using, ', 'different methods:' -FontSize 10pt -FontWeight bold, bold -Color Black, RedRobin -TextDecoration none, underline
New-HTMLList -Type Unordered {
foreach ($Domain in $Script:Reporting['GPOOwners']['Variables']['RequiresDiffFixPerDomain'].Keys) {
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOOwners']['Variables']['RequiresDiffFixPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
}
} -FontSize 10pt
}
Solution = {
New-HTMLSection -Invisible {
@@ -141,19 +170,44 @@
}
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 Owner does NOT touch GPO content. It simply changes owners on AD and SYSVOL at the same time. "
"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 'Set GPO Owners to Administrative (Domain Admins)' {
New-HTMLText -Text "Following command will find any GPO which doesn't have proper GPO Owner (be it due to inconsistency or not being Domain Admin) and will enforce new GPO Owner. "
New-HTMLText -Text "Make sure when running it for the first time to run it with ", "WhatIf", " parameter as shown below to prevent accidental removal." -FontWeight normal, bold, normal -Color Black, Red, Black
New-HTMLCodeBlock -Code {
Set-GPOZaurrOwner -Type All -Verbose -WhatIf
}
New-HTMLText -TextBlock {
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be changed matches expected data. Once happy with results please follow with command: "
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
}
New-HTMLCodeBlock -Code {
Set-GPOZaurrOwner -Type All -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 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 {
Set-GPOZaurrOwner -Type 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 {
Set-GPOZaurrOwner -Type All -Verbose -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
New-HTMLText -TextBlock {
"This command when executed sets new owner only on first X non-compliant GPO Owners for AD/SYSVOL. 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."
+8 -8
View File
@@ -6,16 +6,16 @@
[PSCustomObject] $GPOPermission,
[alias('PermissionType')][Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType
)
if ($GPOPermission.Name) {
$Text = "Removing SID: $($GPOPermission.Sid), Name: $($GPOPermission.Domain)\$($GPOPermission.Name), SidType: $($GPOPermission.SidType) from domain $($GPOPermission.DomainName)"
if ($GPOPermission.PrincipalName) {
$Text = "Removing SID: $($GPOPermission.PrincipalSid), Name: $($GPOPermission.PrincipalDomainName)\$($GPOPermission.PrincipalName), SidType: $($GPOPermission.PrincipalSidType) from domain $($GPOPermission.DomainName)"
} else {
$Text = "Removing SID: $($GPOPermission.Sid), Name: EMPTY, SidType: $($GPOPermission.SidType) from domain $($GPOPermission.DomainName)"
$Text = "Removing SID: $($GPOPermission.PrincipalSid), Name: EMPTY, SidType: $($GPOPermission.PrincipalSidType) from domain $($GPOPermission.DomainName)"
}
if ($PrincipalType -eq 'DistinguishedName') {
if ($GPOPermission.DistinguishedName -eq $Principal -and $GPOPermission.Permission -eq $IncludePermissionType) {
if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, $Text)) {
try {
Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.Name) / Type: $($GPOPermission.PermissionType)"
Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.PrincipalName) / Type: $($GPOPermission.PermissionType)"
$GPOPermission.GPOSecurity.Remove($GPOPermission.GPOSecurityPermissionItem)
$GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity)
} catch {
@@ -24,10 +24,10 @@
}
}
} elseif ($PrincipalType -eq 'Sid') {
if ($GPOPermission.Sid -eq $Principal -and $GPOPermission.Permission -eq $IncludePermissionType) {
if ($GPOPermission.PrincipalSid -eq $Principal -and $GPOPermission.Permission -eq $IncludePermissionType) {
if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, $Text)) {
try {
Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.Name) / Type: $($GPOPermission.PermissionType)"
Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.PrincipalName) / Type: $($GPOPermission.PermissionType)"
$GPOPermission.GPOSecurity.Remove($GPOPermission.GPOSecurityPermissionItem)
$GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity)
} catch {
@@ -51,10 +51,10 @@
}
}
} elseif ($PrincipalType -eq 'Name') {
if ($GPOPermission.Name -eq $Principal -and $GPOPermission.Permission -eq $IncludePermissionType) {
if ($GPOPermission.PrincipalName -eq $Principal -and $GPOPermission.Permission -eq $IncludePermissionType) {
if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, $Text)) {
try {
Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.Name) / Type: $($GPOPermission.PermissionType)"
Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.PrincipalName) / Type: $($GPOPermission.PermissionType)"
$GPOPermission.GPOSecurity.Remove($GPOPermission.GPOSecurityPermissionItem)
$GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity)
} catch {
+5
View File
@@ -12,6 +12,7 @@
$GPOGUIDS = $GPOs.ID.GUID
$SysVolPath = "\\$($Server)\SYSVOL\$Domain\Policies"
Write-Verbose "Get-GPOZaurrBroken - Processing SYSVOL from \\$($Server)\SYSVOL\$Domain\Policies"
try {
$SYSVOL = Get-ChildItem -Path "\\$($Server)\SYSVOL\$Domain\Policies" -Exclude 'PolicyDefinitions' -ErrorAction Stop -Verbose:$false
} catch {
@@ -46,7 +47,10 @@
}
}
$GPOSummary = @(
$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 {
@@ -92,6 +96,7 @@
}
}
# 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 and creating dummy objects"
foreach ($_ in $Differences.Keys) {
if ($Differences[$_] -in 'Not available in AD', 'Permissions issue') {
$FullPath = $SysvolHash[$_].FullName
+169 -146
View File
@@ -1,11 +1,9 @@
function Add-GPOZaurrPermission {
[cmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'GPOGUID')]
[cmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'GPOName')]
param(
[Parameter(ParameterSetName = 'GPOName', Mandatory)]
[string] $GPOName,
[Parameter(ParameterSetName = 'GPOGUID', Mandatory)]
[alias('GUID', 'GPOID')][string] $GPOGuid,
[Parameter(ParameterSetName = 'GPOName', Mandatory)][string] $GPOName,
[Parameter(ParameterSetName = 'GPOGUID', Mandatory)][alias('GUID', 'GPOID')][string] $GPOGuid,
[Parameter(ParameterSetName = 'All', Mandatory)][switch] $All,
[Parameter(ParameterSetName = 'ADObject', Mandatory)]
[alias('OrganizationalUnit', 'DistinguishedName')][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject,
@@ -55,7 +53,6 @@
}
$Splat['ExcludeDomains'] = $ExcludeDomains
$Splat['ExtendedForestInformation'] = $ExtendedForestInformation
#$Splat['ExcludePermissionType'] = $ExcludePermissionType
$Splat['IncludePermissionType'] = $PermissionType
$Splat['SkipWellKnown'] = $SkipWellKnown.IsPresent
$Splat['SkipAdministrative'] = $SkipAdministrative.IsPresent
@@ -64,150 +61,176 @@
DomainAdmins = $false
EnterpriseAdmins = $false
}
$CountFixed = 0
# This should always return results. When no data is found it should return basic information that will allow us to add credentials.
[Array] $GPOPermissions = Get-GPOZaurrPermission @Splat -ReturnSecurityWhenNoData
# When it has GPOSecurityPermissionItem property it means it has permissions, if it doesn't it means we have clean object to process
if ($GPOPermissions.GPOSecurityPermissionItem) {
# Permission exists, but may be incomplete
foreach ($GPOPermission in $GPOPermissions) {
if ($Type -eq 'Default') {
# We were looking for specific principal and we got it. nothing to do
# this is for standard users such as przemyslaw.klys / adam.gonzales
return
} elseif ($Type -eq 'Administrative') {
# We are looking for administrative but we need to make sure we got correct administrative
if ($GPOPermission.Permission -eq $PermissionType) {
$AdministrativeGroup = $ADAdministrativeGroups['BySID'][$GPOPermission.SID]
if ($AdministrativeGroup.SID -like '*-519') {
$AdministrativeExists['EnterpriseAdmins'] = $true
} elseif ($AdministrativeGroup.SID -like '*-512') {
$AdministrativeExists['DomainAdmins'] = $true
Do {
# This should always return results. When no data is found it should return basic information that will allow us to add credentials.
Get-GPOZaurrPermission @Splat -ReturnSecurityWhenNoData -ReturnSingleObject | ForEach-Object {
# Prepare data to clean
$Skip = $false
$AdministrativeExists['EnterpriseAdmins'] = $false
$AdministrativeExists['DomainAdmins'] = $false
$GPOPermissions = $_
# Verification Phase
# When it has GPOSecurityPermissionItem property it means it has permissions, if it doesn't it means we have clean object to process
if ($GPOPermissions.GPOSecurityPermissionItem) {
# Permission exists, but may be incomplete
foreach ($GPOPermission in $GPOPermissions) {
if ($Type -eq 'Default') {
# We were looking for specific principal and we got it. nothing to do
# this is for standard users such as przemyslaw.klys / adam.gonzales
$Skip = $true
break
} elseif ($Type -eq 'Administrative') {
# We are looking for administrative but we need to make sure we got correct administrative
if ($GPOPermission.Permission -eq $PermissionType) {
$AdministrativeGroup = $ADAdministrativeGroups['BySID'][$GPOPermission.PrincipalSid]
if ($AdministrativeGroup.SID -like '*-519') {
$AdministrativeExists['EnterpriseAdmins'] = $true
} elseif ($AdministrativeGroup.SID -like '*-512') {
$AdministrativeExists['DomainAdmins'] = $true
}
}
if ($AdministrativeExists['DomainAdmins'] -and $AdministrativeExists['EnterpriseAdmins']) {
$Skip = $true
break
}
} elseif ($Type -eq 'WellKnownAdministrative') {
# this is for SYSTEM account
$Skip = $true
break
} elseif ($Type -eq 'AuthenticatedUsers') {
# this is for Authenticated Users
$Skip = $true
break
}
<#
if ($AdministrativeGroup) {
$DomainAdminsSID = -join ($ForestInformation['DomainsExtended'][$GPOPermission.DomainName].DomainSID, '-512')
$EnterpriseAdminsSID = -join ($ForestInformation['DomainsExtended'][$GPOPermission.DomainName].DomainSID, '-519')
if ($GPOPermission.SID -eq $DomainAdminsSID) {
$AdministrativeExists['DomainAdmins'] = $true
} elseif ($GPOPermission.SID -eq $EnterpriseAdminsSID) {
$AdministrativeExists['EnterpriseAdmins'] = $true
}
}
if (-not $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!"
} else {
$GPO = $GPOPermissions[0]
if ($GPOPermissions.GPOSecurityPermissionItem) {
# 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 ($AdministrativeExists['DomainAdmins'] -eq $false) {
$Principal = $ADAdministrativeGroups[$GPO.DomainName]['DomainAdmins']
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
$CountFixed++
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)"
}
}
}
if ($AdministrativeExists['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++
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)"
}
}
}
} elseif ($Type -eq 'Default') {
# This shouldn't really happen, as if we got response, and it didn't exists it wouldn't be here
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType skipped for $($Principal). This shouldn't even happen!"
}
} else {
# We got no response. That means we either asked incorrectly or we need to fix permission. Trying to do so
if ($Type -eq 'Default') {
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
$CountFixed++
if ($PrincipalType -eq 'DistinguishedName') {
$ADIdentity = Get-WinADObject -Identity $Principal
if ($ADIdentity) {
Write-Verbose "Add-GPOZaurrPermission - Need to convert DN $Principal to SID $($ADIdentity.ObjectSID) to $($GPO.DisplayName) at $($GPO.DomainName)"
$Principal = $ADIdentity.ObjectSID
}
}
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal)"
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)"
}
}
} elseif ($Type -eq 'Administrative') {
# this is a case where both Domain Admins/Enterprise Admins were missing
$Principal = $ADAdministrativeGroups[$GPO.DomainName]['DomainAdmins']
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
$CountFixed++
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)"
}
}
$Principal = $ADAdministrativeGroups[$ForestInformation.Forest.RootDomain]['EnterpriseAdmins']
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
$CountFixed++
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)"
}
}
} elseif ($Type -eq 'WellKnownAdministrative') {
$Principal = 'S-1-5-18'
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
$CountFixed++
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal (SYSTEM) / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) (SYSTEM) with error: $($_.Exception.Message)"
}
}
} elseif ($Type -eq 'AuthenticatedUsers') {
$Principal = 'S-1-5-11'
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
$CountFixed++
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal (Authenticated Users) / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) (Authenticated Users) with error: $($_.Exception.Message)"
}
}
}
}
#>
}
} elseif ($Type -eq 'WellKnownAdministrative') {
# this is for SYSTEM account
return
} elseif ($Type -eq 'AuthenticatedUsers') {
# this is for Authenticated Users
return
}
if ($CountFixed -ge $LimitProcessing) {
# We want to exit foreach-object, but ForEach-Object doesn't really allow that
# that's why there is Do/While which will make sure that breaks doesn't break what it's not supposed to
break
}
}
}
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!"
} else {
$GPO = $GPOPermissions[0]
if ($GPOPermissions.GPOSecurityPermissionItem) {
# 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 ($AdministrativeExists['DomainAdmins'] -eq $false) {
$Principal = $ADAdministrativeGroups[$GPO.DomainName]['DomainAdmins']
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)"
}
}
}
if ($AdministrativeExists['EnterpriseAdmins'] -eq $false) {
$Principal = $ADAdministrativeGroups[$ForestInformation.Forest.RootDomain]['EnterpriseAdmins']
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)"
}
}
}
} elseif ($Type -eq 'Default') {
# This shouldn't really happen, as if we got response, and it didn't exists it wouldn't be here
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType skipped for $($Principal). This shouldn't even happen!"
}
} else {
# We got no response. That means we either asked incorrectly or we need to fix permission. Trying to do so
if ($Type -eq 'Default') {
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal)"
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)"
}
}
} elseif ($Type -eq 'Administrative') {
# this is a case where both Domain Admins/Enterprise Admins were missing
$Principal = $ADAdministrativeGroups[$GPO.DomainName]['DomainAdmins']
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)"
}
}
$Principal = $ADAdministrativeGroups[$ForestInformation.Forest.RootDomain]['EnterpriseAdmins']
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)"
}
}
} elseif ($Type -eq 'WellKnownAdministrative') {
$Principal = 'S-1-5-18'
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal (SYSTEM) / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) (SYSTEM) with error: $($_.Exception.Message)"
}
}
} elseif ($Type -eq 'AuthenticatedUsers') {
$Principal = 'S-1-5-11'
Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal) to $($GPO.DisplayName) at $($GPO.DomainName)"
if ($PSCmdlet.ShouldProcess($GPO.DisplayName, "Adding $Principal (Authenticated Users) / $PermissionType to $($GPO.DisplayName) at $($GPO.DomainName)")) {
try {
$AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent)
$GPO.GPOSecurity.Add($AddPermission)
$GPO.GPOObject.SetSecurityInfo($GPO.GPOSecurity)
} catch {
Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) (Authenticated Users) with error: $($_.Exception.Message)"
}
}
}
}
}
} while ($false)
}
+4 -4
View File
@@ -13,7 +13,7 @@
[switch] $PermissionsOnly,
[switch] $OwnerOnly,
[switch] $Limited,
[switch] $ReturnObject,
[System.Collections.IDictionary] $ADAdministrativeGroups
)
Begin {
@@ -43,7 +43,7 @@
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
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups -ReturnObject:$ReturnObject.IsPresent
} else {
$_
}
@@ -61,7 +61,7 @@
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
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups -ReturnObject:$ReturnObject.IsPresent
} else {
$_
}
@@ -79,7 +79,7 @@
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
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups -ReturnObject:$ReturnObject.IsPresent
} else {
$_
}
+31 -24
View File
@@ -13,9 +13,16 @@
$FilesAll = foreach ($Domain in $ForestInformation.Domains) {
$Path = -join ("\\", $Domain, '\Netlogon')
$PathOnSysvol = -join ("\\", $Domain, "\SYSVOL\", $Domain, "\Scripts")
$Files = Get-ChildItem -LiteralPath $Path -Recurse -Force
foreach ($_ in $Files) {
$ACL = Get-Acl -Path $_.FullName
$Files = Get-ChildItem -LiteralPath $Path -Recurse -Force -ErrorVariable Err -ErrorAction SilentlyContinue
foreach ($e in $err) {
Write-Warning "Get-GPOZaurrNetLogon - Listing file failed with error $($e.Exception.Message) ($($e.CategoryInfo.Reason))"
}
foreach ($File in $Files) {
try {
$ACL = Get-Acl -Path $File.FullName -ErrorAction Stop
} catch {
Write-Warning "Get-GPOZaurrNetLogon - ACL reading failed for $($File.FullName) with error $($_.Exception.Message) ($($_.CategoryInfo.Reason))"
}
if ($ACL.Owner) {
$IdentityOwner = Convert-Identity -Identity $ACL.Owner -Verbose:$false
} else {
@@ -24,19 +31,19 @@
if (-not $OwnerOnly) {
if (-not $SkipOwner) {
[PSCustomObject] @{
FullName = $_.FullName
Extension = $_.Extension
CreationTime = $_.CreationTime
LastAccessTime = $_.LastAccessTime
LastWriteTime = $_.LastWriteTime
Attributes = $_.Attributes
FullName = $File.FullName
Extension = $File.Extension
CreationTime = $File.CreationTime
LastAccessTime = $File.LastAccessTime
LastWriteTime = $File.LastWriteTime
Attributes = $File.Attributes
AccessControlType = 'Allow' # : Allow
Principal = $IdentityOwner.Name # : BUILTIN\Administrators
PrincipalSid = $IdentityOwner.SID
PrincipalType = $IdentityOwner.Type
FileSystemRights = 'Owner' # : FullControl
IsInherited = $false
FullNameOnSysVol = $_.FullName.Replace($Path, $PathOnSysvol)
FullNameOnSysVol = $File.FullName.Replace($Path, $PathOnSysvol)
#Owner = $ACL.Owner
}
}
@@ -44,33 +51,33 @@
foreach ($Perm in $FilePermission) {
$Identity = Convert-Identity -Identity $Perm.Principal -Verbose:$false
[PSCustomObject] @{
FullName = $_.FullName
Extension = $_.Extension
CreationTime = $_.CreationTime
LastAccessTime = $_.LastAccessTime
LastWriteTime = $_.LastWriteTime
Attributes = $_.Attributes
FullName = $File.FullName
Extension = $File.Extension
CreationTime = $File.CreationTime
LastAccessTime = $File.LastAccessTime
LastWriteTime = $File.LastWriteTime
Attributes = $File.Attributes
AccessControlType = $Perm.AccessControlType # : Allow
Principal = $Identity.Name # : BUILTIN\Administrators
PrincipalSid = $Identity.SID
PrincipalType = $Identity.Type
FileSystemRights = $Perm.FileSystemRights # : FullControl
IsInherited = $Perm.IsInherited # : True
FullNameOnSysVol = $_.FullName.Replace($Path, $PathOnSysvol)
FullNameOnSysVol = $File.FullName.Replace($Path, $PathOnSysvol)
}
}
} else {
[PSCustomObject] @{
FullName = $_.FullName
Extension = $_.Extension
CreationTime = $_.CreationTime
LastAccessTime = $_.LastAccessTime
LastWriteTime = $_.LastWriteTime
Attributes = $_.Attributes
FullName = $File.FullName
Extension = $File.Extension
CreationTime = $File.CreationTime
LastAccessTime = $File.LastAccessTime
LastWriteTime = $File.LastWriteTime
Attributes = $File.Attributes
Owner = $IdentityOwner.Name
OwnerSid = $IdentityOwner.SID
OwnerType = $IdentityOwner.Type
FullNameOnSysVol = $_.FullName.Replace($Path, $PathOnSysvol)
FullNameOnSysVol = $File.FullName.Replace($Path, $PathOnSysvol)
}
}
}
+7 -2
View File
@@ -31,7 +31,8 @@
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[System.Collections.IDictionary] $ExtendedForestInformation,
[System.Collections.IDictionary] $ADAdministrativeGroups,
[switch] $ReturnSecurityWhenNoData # if no data return all data
[switch] $ReturnSecurityWhenNoData, # if no data return all data
[switch] $ReturnSingleObject # forces return of single object per GPO as one for ForEach-Object processing
)
Begin {
$ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -Extended
@@ -136,7 +137,11 @@
$ReturnObject
}
} else {
$Output
if ($ReturnSingleObject) {
, $Output
} else {
$Output
}
}
}
} catch {
+13 -8
View File
@@ -47,15 +47,20 @@
$GPO = $_
$Count++
Write-Verbose "Get-GPOZaurrPermissionConsistency - Processing [$($_.DomainName)]($Count/$($GroupPolicies.Count)) $($_.DisplayName)"
try {
$IsConsistent = $_.IsAclConsistent()
$ErrorMessage = ''
} catch {
$ErrorMessage = $_.Exception.Message
Write-Warning "Get-GPOZaurrPermissionConsistency - Processing $($GPO.DisplayName) / $($GPO.DomainName) failed to get consistency with error: $($_.Exception.Message)."
$IsConsistent = 'Not available'
$SysVolpath = -join ('\\', $Domain, '\sysvol\', $Domain, '\Policies\{', $GPO.ID.GUID, '}')
if (Test-Path -LiteralPath $SysVolpath) {
try {
$IsConsistent = $GPO.IsAclConsistent()
$ErrorMessage = ''
} catch {
$ErrorMessage = $_.Exception.Message
Write-Warning "Get-GPOZaurrPermissionConsistency - Processing $($GPO.DisplayName) / $($GPO.DomainName) failed to get consistency with error: $($_.Exception.Message)."
$IsConsistent = 'Not available'
}
} else {
Write-Warning "Get-GPOZaurrPermissionConsistency - Processing $($GPO.DisplayName) / $($GPO.DomainName) failed as path $SysvolPath doesn't exists!"
$IsConsistent = $false
}
$SysVolpath = -join ('\\', $Domain, '\sysvol\', $Domain, '\Policies\{', $_.ID.GUID, '}')
if ($VerifyInheritance) {
if ($IsConsistent -eq $true) {
$FolderPermissions = Get-WinADSharePermission -Path $SysVolpath -Verbose:$false
+4
View File
@@ -51,6 +51,7 @@
Data = $null
WarningsAndErrors = $null
Time = $null
Summary = $null
Variables = Copy-Dictionary -Dictionary $Script:GPOConfiguration[$T]['Variables']
}
$TimeLogGPOList = Start-TimeLog
@@ -75,6 +76,9 @@
}
}
)
if ($Script:GPOConfiguration[$T]['Summary']) {
$Script:Reporting[$T]['Summary'] = Invoke-Command -ScriptBlock $Script:GPOConfiguration[$T]['Summary']
}
$TimeEndGPOList = Stop-TimeLog -Time $TimeLogGPOList -Option OneLiner
$Script:Reporting[$T]['Time'] = $TimeEndGPOList
Write-Color -Text '[i]', '[End ] ', $($Script:GPOConfiguration[$T]['Name']), " [Time to execute: $TimeEndGPOList]" -Color Yellow, DarkGray, Yellow, DarkGray
+19
View File
@@ -0,0 +1,19 @@
function Optimize-GPOZaurr {
[cmdletBinding()]
param(
)
$GPOS = Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
foreach ($GPO in $GPOS) {
if ($GPO.UserSettingsAvailable -eq $false -and $GPO.ComputerSettingsAvailable -eq $false) {
if ($GPO.Enabled -ne 'All setttings disabled') {
# $GPO
}
} elseif ($GPO.UserSettingsAvailable -eq $false) {
} elseif ($GPO.ComputerSettingsAvailable -eq $false) {
}
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
} else {
$BackupFinalPath = ''
}
Get-GPOZaurrSysvol -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation | Where-Object {
Get-GPOZaurrBroken -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation | Where-Object {
if ($Type -contains 'SYSVOL') {
if ($_.Status -eq 'Not available in AD') {
$_
+7 -3
View File
@@ -72,11 +72,11 @@
}
}
Get-GPO @getGPOSplat | ForEach-Object -Process {
$GPOSecurity = $_.GetSecurityInfo()
$getPrivPermissionSplat = @{
Principal = $Principal
PrincipalType = $PrincipalType
Accounts = $Accounts
Type = $Type
#Accounts = $Accounts
GPO = $_
SkipWellKnown = $SkipWellKnown.IsPresent
SkipAdministrative = $SkipAdministrative.IsPresent
@@ -85,11 +85,15 @@
IncludePermissionType = $IncludePermissionType
ExcludePermissionType = $ExcludePermissionType
ADAdministrativeGroups = $ADAdministrativeGroups
SecurityRights = $GPOSecurity
}
if ($Type -ne 'Default') {
$getPrivPermissionSplat['Type'] = $Type
}
[Array] $GPOPermissions = Get-PrivPermission @getPrivPermissionSplat
if ($GPOPermissions.Count -gt 0) {
foreach ($Permission in $GPOPermissions) {
Remove-PrivPermission -Principal $Permission.Sid -PrincipalType Sid -GPOPermission $Permission -IncludePermissionType $Permission.Permission #-IncludeDomains $GPO.DomainName
Remove-PrivPermission -Principal $Permission.PrincipalSid -PrincipalType Sid -GPOPermission $Permission -IncludePermissionType $Permission.Permission #-IncludeDomains $GPO.DomainName
}
$Count++
if ($Count -eq $LimitProcessing) {
+41 -35
View File
@@ -76,7 +76,8 @@
[Parameter(ParameterSetName = 'Type')]
[Parameter(ParameterSetName = 'Named')]
[int] $LimitProcessing = [int32]::MaxValue
[int] $LimitProcessing = [int32]::MaxValue,
[switch] $Force
)
Begin {
#Write-Verbose "Set-GPOZaurrOwner - Getting ADAdministrativeGroups"
@@ -114,45 +115,50 @@
$AdministrativeGroupSysvol = $null
}
}
if ($Type -eq 'NotAdministrative') {
if (-not $AdministrativeGroup -or (-not $AdministrativeGroupSysvol -and -not $SkipSysvol)) {
$_
} else {
if ($AdministrativeGroup -ne $AdministrativeGroupSysvol) {
Write-Verbose "Set-GPOZaurrOwner - Detected mismatch GPO: $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner). Fixing required."
$_
}
}
} elseif ($Type -eq 'Unknown') {
if (-not $_.Owner -or (-not $_.SysvolOwner -and -not $SkipSysvol)) {
$_
}
} elseif ($Type -eq 'NotMatching') {
if ($SkipSysvol) {
Write-Verbose "Set-GPOZaurrOwner - Detected mismatch GPO: $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner). SysVol scanning is disabled. Skipping."
} else {
if ($AdministrativeGroup -ne $AdministrativeGroupSysvol) {
#Write-Verbose "Set-GPOZaurrOwner - Detected mismatch GPO: $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner). Fixing required."
$_
}
}
if ($Force) {
Write-Verbose "Set-GPOZaurrOwner - Force was used to push new owner to $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner)."
$_
} else {
# we run with no type, that means we need to either set it to principal or to Administrative
if ($_.Owner) {
# we check if Principal is not set
$AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($_.Owner)"]
if (-not $SkipSysvol -and $_.SysvolOwner) {
$AdministrativeGroupSysvol = $ADAdministrativeGroups['ByNetBIOS']["$($_.SysvolOwner)"]
if (-not $AdministrativeGroup -or -not $AdministrativeGroupSysvol) {
if ($Type -eq 'NotAdministrative') {
if (-not $AdministrativeGroup -or (-not $AdministrativeGroupSysvol -and -not $SkipSysvol)) {
$_
} else {
if ($AdministrativeGroup -ne $AdministrativeGroupSysvol) {
Write-Verbose "Set-GPOZaurrOwner - Detected mismatch GPO: $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner). Fixing required."
$_
}
}
} elseif ($Type -eq 'Unknown') {
if (-not $_.Owner -or (-not $_.SysvolOwner -and -not $SkipSysvol)) {
$_
}
} elseif ($Type -eq 'NotMatching') {
if ($SkipSysvol) {
Write-Verbose "Set-GPOZaurrOwner - Detected mismatch GPO: $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner). SysVol scanning is disabled. Skipping."
} else {
if ($AdministrativeGroup -ne $AdministrativeGroupSysvol) {
#Write-Verbose "Set-GPOZaurrOwner - Detected mismatch GPO: $($_.DisplayName) from domain: $($_.DomainName) - owner $($_.Owner) / sysvol owner $($_.SysvolOwner). Fixing required."
$_
}
}
} else {
# we run with no type, that means we need to either set it to principal or to Administrative
if ($_.Owner) {
# we check if Principal is not set
$AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($_.Owner)"]
if (-not $SkipSysvol -and $_.SysvolOwner) {
$AdministrativeGroupSysvol = $ADAdministrativeGroups['ByNetBIOS']["$($_.SysvolOwner)"]
if (-not $AdministrativeGroup -or -not $AdministrativeGroupSysvol) {
$_
}
} else {
if (-not $AdministrativeGroup) {
$_
}
}
} else {
if (-not $AdministrativeGroup) {
$_
}
$_
}
} else {
$_
}
}
} | Select-Object -First $LimitProcessing | ForEach-Object -Process {
+36 -2
View File
@@ -19,7 +19,15 @@
# GPOZaurr
## To install
## Table of Contents
- [GPOZaurr](#gpozaurr)
- [Table of Contents](#table-of-contents)
- [Installing](#installing)
- [Updating](#updating)
- [Changelog](#changelog)
## Installing
GPOZaurr requires `RSAT` installed to provide results. If you don't have them you can install them as below. Keep in mind it also installs GUI tools so it shouldn't be installed on user workstations.
@@ -37,7 +45,7 @@ Install-Module -Name GPOZaurr -AllowClobber -Force
Force and AllowClobber aren't necessary, but they do skip errors in case some appear.
## And to update
## Updating
```powershell
Update-Module -Name GPOZaurr
@@ -49,6 +57,32 @@ That's it. Whenever there's a new version, you run the command, and you can enjo
## Changelog
- 0.0.80
- [x] Improves `Invoke-GPOZaurr`
- [x] Type `GPOOrphans` clearer options, updated texts, split per domain
- [x] Type `GPOOwners` clearer options, updated texts, split per domain
- [x] Improves `Add-GPOZaurrPermission`
- [x] Fixes LimitProcessing to work correctly
- [x] Added `All` to process all GPOs
- [x] Fixes `Remove-GPOZaurrPermission`
- [x] Improves `Set-GPOZaurrOwner`
- [x] Added `Force` to force `GPO Owner` to any principal (normally only Domain Admins)
- 0.0.79 - 10.11.2020
- Improved `Invoke-GPOZaurr` - type `GPOOrphans`
- 0.0.78 - 10.11.2020
- Improved `Remove-GPOZaurrBroken` more verbose
- Improved `Get-GPOZaurrBroken` more verbose
- Improved `Invoke-GPOZaurr` - type `GPOOrphans`
- Improved `Invoke-GPOZaurr` - type `GPOList` - needs more work
- Improved `Get-GPOZaurr` with better detection of Empty Policies (needs testing)
- 0.0.77 - 9.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
- 0.0.76 - 8.11.2020
- Improved `Get-GPOZaurrNetLogon` to better handle errors
- 0.0.75 - 8.11.2020
- Improved `Get-GPOZaurrPermissionConsistency` to stop checking consistency if path doesn't exists
- 0.0.74 - 8.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
- 0.0.73 - 7.11.2020
- Improved `Invoke-GPOZaurr` (WIP)
- Improved `Get-GPOZaurr`
+42
View File
@@ -0,0 +1,42 @@
Describe 'GPO Owners Management - Simple' {
BeforeAll {
# just in case some tests failed before and added user stays
Import-Module $PSScriptRoot\..\*.psd1 -Force
}
It 'Get-GPOZaurrOwner - Should return proper data' {
$GPOs = Get-GPOZaurrOwner -IncludeSysvol
$GPOs.Count | Should -BeGreaterThan 5
$GPOs[0].PSObject.Properties.Name | Should -Be @(
'DisplayName', 'DomainName',
'GUID', 'Owner', 'OwnerSID',
'OwnerType', 'SysvolOwner', 'SysvolSid',
'SysvolType', 'SysvolPath', 'IsOwnerConsistent',
'IsOwnerAdministrative', 'SysvolExists', 'DistinguishedName'
)
}
It 'Set-GPOZaurrOwner - Should set proper data' {
Set-GPOZaurrOwner -GPOName 'TEST | GPOZaurr Permissions Testing' -Verbose -Principal 'przemyslaw.klys' -WhatIf:$false -Force
}
It 'Get-GPOZaurrOwner - Should return proper data for one GPO' {
$GPOs = Get-GPOZaurrOwner -IncludeSysvol -GPOName 'TEST | GPOZaurr Permissions Testing'
$GPOs.SysvolOwner | Should -Be 'EVOTEC\przemyslaw.klys'
$GPOs.SysvolType | Should -Be 'NotAdministrative'
$GPOs.Owner | Should -Be 'EVOTEC\przemyslaw.klys'
$GPOs.OwnerType | Should -Be 'NotAdministrative'
$GPOS.IsOwnerConsistent | Should -Be $true
$GPOS.IsOwnerAdministrative | Should -Be $false
}
It 'Set-GPOZaurrOwner - Should set proper data' {
Set-GPOZaurrOwner -GPOName 'TEST | GPOZaurr Permissions Testing' -Verbose
}
It 'Get-GPOZaurrOwner - Should return proper data for one GPO (Domain Admins)' {
$GPOs = Get-GPOZaurrOwner -IncludeSysvol -GPOName 'TEST | GPOZaurr Permissions Testing'
$GPOs.SysvolOwner | Should -Be 'EVOTEC\Domain Admins'
$GPOs.SysvolType | Should -Be 'Administrative'
$GPOs.Owner | Should -Be 'EVOTEC\Domain Admins'
$GPOs.OwnerType | Should -Be 'Administrative'
$GPOS.IsOwnerConsistent | Should -Be $true
$GPOS.IsOwnerAdministrative | Should -Be $true
}
}
+70
View File
@@ -0,0 +1,70 @@
Describe 'GPO Permissions Management - Simple' {
BeforeAll {
# just in case some tests failed before and added user stays
Import-Module $PSScriptRoot\..\*.psd1 -Force
Remove-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing' -PermissionType GpoEdit -Principal 'EVOTEC\przemyslaw.klys' -PrincipalType NetbiosName -Verbose
}
It 'Get-GPOZaurrPermission - Should return proper data' {
$GPOPermissions = Get-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing'
($GPOPermissions | Where-Object { $_.Permission -eq 'GPOApply' }) | Should -BeOfType PSCustomObject
($GPOPermissions | Where-Object { $_.Permission -eq 'GPOApply' }).PrincipalNetBiosName | Should -Be 'NT AUTHORITY\Authenticated Users'
$GPOPermissions = Get-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing' -IncludePermissionType GpoEditDeleteModifySecurity -Type NotAdministrative
$GPOPermissions.PrincipalNetBiosName | Should -Be 'NT AUTHORITY\SYSTEM'
$GPOPermissions.PrincipalSidType | Should -Be 'WellKnownAdministrative'
$GPOPermissions.PrincipalObjectClass | Should -Be 'foreignSecurityPrincipal'
$GPOPermissions.DisplayName | Should -be 'TEST | GPOZaurr Permissions Testing'
$GPOPermissions.Permission | Should -Be 'GpoEditDeleteModifySecurity'
[Array] $GPOPermissions = Get-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing' -IncludePermissionType GpoEditDeleteModifySecurity
$GPOPermissions.Count | Should -be 3
$SYSTEM = $GPOPermissions | Where-Object { $_.PrincipalNetBiosName -eq 'NT AUTHORITY\SYSTEM' }
$SYSTEM.PrincipalNetBiosName | Should -Be 'NT AUTHORITY\SYSTEM'
$SYSTEM.PrincipalSidType | Should -Be 'WellKnownAdministrative'
$SYSTEM.PrincipalObjectClass | Should -Be 'foreignSecurityPrincipal'
$SYSTEM.DisplayName | Should -be 'TEST | GPOZaurr Permissions Testing'
$SYSTEM.Permission | Should -Be 'GpoEditDeleteModifySecurity'
$DomainAdmins = $GPOPermissions | Where-Object { $_.PrincipalNetBiosName -eq 'EVOTEC\Domain Admins' }
$DomainAdmins.PrincipalNetBiosName | Should -Be 'EVOTEC\Domain Admins'
$DomainAdmins.PrincipalSidType | Should -Be 'Administrative'
$DomainAdmins.PrincipalObjectClass | Should -Be 'group'
$DomainAdmins.DisplayName | Should -be 'TEST | GPOZaurr Permissions Testing'
$DomainAdmins.Permission | Should -Be 'GpoEditDeleteModifySecurity'
$EnterpriseAdmins = $GPOPermissions | Where-Object { $_.PrincipalNetBiosName -eq 'EVOTEC\Enterprise Admins' }
$EnterpriseAdmins.PrincipalNetBiosName | Should -Be 'EVOTEC\Enterprise Admins'
$EnterpriseAdmins.PrincipalSidType | Should -Be 'Administrative'
$EnterpriseAdmins.PrincipalObjectClass | Should -Be 'group'
$EnterpriseAdmins.DisplayName | Should -be 'TEST | GPOZaurr Permissions Testing'
$EnterpriseAdmins.Permission | Should -Be 'GpoEditDeleteModifySecurity'
}
It 'Add-GPOZaurrPermission - With WHATIF works' {
# Tests WHATIF
Add-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing' -PermissionType GpoEdit -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose -WhatIf
$GPOPermissions = Get-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing' -IncludePermissionType GpoEdit -Principal 'przemyslaw.klys' -PrincipalType Name
$GPOPermissions | Should -be $null
}
It 'Add-GPOZaurrPermission - Without WHATIF works' {
Add-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing' -PermissionType GpoEdit -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose
$GPOPermissions = Get-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing' -IncludePermissionType GpoEdit -Principal 'przemyslaw.klys' -PrincipalType Name
$GPOPermissions | Should -be -Not $null
$GPOPermissions.PrincipalNetBiosName | Should -Be 'EVOTEC\przemyslaw.klys'
}
It 'Remove-GPOZaurrPermission - With WHATIF' {
# Tests WHATIF
Remove-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing' -PermissionType GpoEdit -Principal 'przemyslaw.klys' -PrincipalType Name -Verbose -WhatIf
$GPOPermissions = Get-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing' -IncludePermissionType GpoEdit -Principal 'przemyslaw.klys' -PrincipalType Name
$GPOPermissions | Should -be -Not $null
$GPOPermissions.PrincipalNetBiosName | Should -Be 'EVOTEC\przemyslaw.klys'
}
It 'Remove-GPOZaurrPermission - Without WHATIF' {
Remove-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing' -PermissionType GpoEdit -Principal 'EVOTEC\przemyslaw.klys' -PrincipalType NetbiosName -Verbose
$GPOPermissions = Get-GPOZaurrPermission -GPOName 'TEST | GPOZaurr Permissions Testing' -IncludePermissionType GpoEdit -Principal 'przemyslaw.klys' -PrincipalType Name
$GPOPermissions | Should -be $null
}
}