mirror of
https://github.com/EvotecIT/GPOZaurr.git
synced 2026-07-26 11:49:17 +00:00
Compare commits
90 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0ebfb8ad6d | |||
| 8c7e550247 | |||
| a40c83835c | |||
| ff887bdee9 | |||
| 39d781d899 | |||
| a3a1fd6ea7 | |||
| 52516755c2 | |||
| 922a75e6fc | |||
| 2169d7fb7e | |||
| 61d2789419 | |||
| fc92cae23f | |||
| 08c2a0c225 | |||
| c73c5ca48a | |||
| 9af0dd57c4 | |||
| 4fb6de94db | |||
| 7b3d05bbd3 | |||
| f458dd97c7 | |||
| d4bf6c45cd | |||
| f8fc81e0ad | |||
| 5e4c453254 | |||
| 52bf5b1595 | |||
| 60eb0fdc56 | |||
| 99bc7fc751 | |||
| 50146c3d65 | |||
| 7fddaec289 | |||
| b6104c92ab | |||
| e54ea95e4f | |||
| 64384a3ee9 | |||
| d2add9ff96 | |||
| b6c145ba49 | |||
| a5953f9b32 | |||
| 6d38b1803c | |||
| 16f244592e | |||
| eb7e98b657 | |||
| c060fa5d6d | |||
| 9ce6a2a400 | |||
| 823f2095d4 | |||
| 49e8ecf6d7 | |||
| 673927b2b1 | |||
| d19be8ce0f | |||
| b8845f1f23 | |||
| 000f4d59ef | |||
| 13c88a6d83 | |||
| 311ae288b9 | |||
| 945cccaac8 | |||
| d8e0548900 | |||
| 3ab54ec4ad | |||
| 51620715fa | |||
| 5b6e7b6b0a | |||
| 85ef9c2443 | |||
| 68fbc3a6f6 | |||
| 2912f20390 | |||
| 63ab1b571d | |||
| 807ea420b0 | |||
| 9cd28b11ea | |||
| 5fb48b994b | |||
| 3cfae42cc1 | |||
| fb922d7836 | |||
| fb7dfdc4b1 | |||
| 9d18f4d11a | |||
| 206a1f41af | |||
| bef4744b09 | |||
| f990cdfa03 | |||
| 34282f79bc | |||
| eda72cb1d3 | |||
| 8ab9c0ee21 | |||
| 8646b07e41 | |||
| 1fe0b6b37e | |||
| 553de6dc2b | |||
| 24fd00e110 | |||
| 6e5ae262d4 | |||
| 74192f5d48 | |||
| d0dc7a7052 | |||
| d465f404c9 | |||
| 64bd95d85c | |||
| 569c7ed910 | |||
| 6fec1a264f | |||
| 7eefe96ee7 | |||
| a54f183ed3 | |||
| f5b73918bb | |||
| 25a59572dd | |||
| a6a847d720 | |||
| 20d005f600 | |||
| 7b2f2c69be | |||
| 1126071fc4 | |||
| 70fbc2d5f8 | |||
| fd844fd7a2 | |||
| a258689880 | |||
| 268b2f76f5 | |||
| ec90f38ad9 |
@@ -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
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$GPOS = Get-GPOZaurr -GPOName 'TEST | Office Configuration'
|
||||
#$GPOS = Get-GPOZaurr -GPOName 'TEST | Office Configuration'
|
||||
#$GPOS | Format-Table -AutoSize *
|
||||
|
||||
$GPOS = Get-GPOZaurr -GPOName 'New Group Policy Object3'
|
||||
$GPOS | Format-Table -AutoSize *
|
||||
@@ -0,0 +1,4 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Issues = Get-GPOZaurrPermissionIssue
|
||||
$Issues | Format-Table
|
||||
@@ -4,14 +4,18 @@
|
||||
# And also can fix at the same time NotAdministrative - this basically looks for users/groups that are not Domain Admins or Enterprise Admins
|
||||
# regardless if current user is still Domain Admin or not
|
||||
|
||||
$GPOs = Get-GPOZaurrOwner -IncludeSysvol #-GPOName
|
||||
$GPOs = Get-GPOZaurrOwner -IncludeSysvol
|
||||
$GPOs | Format-Table DisplayName, Owner, OwnerSID, OwnerType, SysvolOwner, SysvolSID, SysvolType
|
||||
|
||||
#Set-GPOZaurrOwner -Type Unknown -Verbose #-LimitProcessing 2 -WhatIf
|
||||
Set-GPOZaurrOwner -Type NotAdministrative -Verbose -LimitProcessing 2 -WhatIf
|
||||
#Set-GPOZaurrOwner -Type NotMatching -Verbose -LimitProcessing 2 -WhatIf
|
||||
Set-GPOZaurrOwner -Type Unknown -Verbose -WhatIf #-LimitProcessing 2
|
||||
Set-GPOZaurrOwner -Type All -Verbose -LimitProcessing 2 -WhatIf -IncludeDomains 'ad.evotec.pl'
|
||||
Set-GPOZaurrOwner -Type NotMatching -Verbose -LimitProcessing 2 -WhatIf
|
||||
|
||||
#Set-GPOZaurrOwner -GPOName 'COMPUTERS | Enable Sets' -Verbose -Principal 'przemyslaw.klys' -WhatIf #-SkipSysvol
|
||||
#Set-GPOZaurrOwner -GPOName 'New Group Policy Object' -Verbose #-WhatIf #-SkipSysvol
|
||||
#$GPOs = Get-GPOZaurrOwner -IncludeSysvol #-GPOName 'New Group Policy Object'
|
||||
#$GPOs | Format-Table DisplayName, Owner, OwnerSID
|
||||
# This will only set it to przemyslaw klys if the owner is not Domain Admins / Enterprise Admins
|
||||
# it's not working currently for any other object
|
||||
# You can enforce -Force to set it to any other principal
|
||||
Set-GPOZaurrOwner -GPOName 'COMPUTERS | Enable Sets' -Verbose -Principal 'przemyslaw.klys' -WhatIf:$false -Force #-SkipSysvol
|
||||
Set-GPOZaurrOwner -GPOName 'New Group Policy Object' -Verbose -WhatIf #-SkipSysvol
|
||||
|
||||
$GPOs = Get-GPOZaurrOwner -IncludeSysvol #-GPOName 'New Group Policy Object'
|
||||
$GPOs | Format-Table DisplayName, Owner, OwnerSID
|
||||
@@ -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
|
||||
@@ -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'
|
||||
@@ -0,0 +1,10 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
# Change per one GPO
|
||||
Add-GPOZaurrPermission -GPOName 'New Group Policy Object' -Type AuthenticatedUsers -PermissionType GpoRead -Verbose -WhatIf
|
||||
|
||||
# Add to ALL GPOs that need it
|
||||
Add-GPOZaurrPermission -Type AuthenticatedUsers -PermissionType GpoRead -All -WhatIf -Verbose
|
||||
|
||||
# Add Domain Admins/Enterprise Admins to all that need it
|
||||
Add-GPOZaurrPermission -Type Administrative -PermissionType GpoEditDeleteModifySecurity -All -WhatIf -Verbose
|
||||
@@ -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 *
|
||||
@@ -4,7 +4,7 @@
|
||||
Get-GPOZaurrBroken -Verbose -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 #-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
|
||||
@@ -1,7 +1,7 @@
|
||||
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
|
||||
|
||||
$Output = Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOList -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.GPOList
|
||||
$Output.GPOOrphans
|
||||
File diff suppressed because one or more lines are too long
@@ -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."
|
||||
}
|
||||
+5
-5
@@ -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', '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')
|
||||
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', 'Skip-GroupPolicy')
|
||||
GUID = 'f7d4c9e4-0298-4f51-ad77-e8e3febebbde'
|
||||
ModuleVersion = '0.0.78'
|
||||
ModuleVersion = '0.0.94'
|
||||
PowerShellVersion = '5.1'
|
||||
PrivateData = @{
|
||||
PSData = @{
|
||||
@@ -18,15 +18,15 @@
|
||||
}
|
||||
}
|
||||
RequiredModules = @(@{
|
||||
ModuleVersion = '0.0.187'
|
||||
ModuleVersion = '0.0.189'
|
||||
ModuleName = 'PSSharedGoods'
|
||||
Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
|
||||
}, @{
|
||||
ModuleVersion = '0.0.102'
|
||||
ModuleVersion = '0.0.103'
|
||||
ModuleName = 'ADEssentials'
|
||||
Guid = '9fc9fd61-7f11-4f4b-a527-084086f1905f'
|
||||
}, @{
|
||||
ModuleVersion = '0.0.120'
|
||||
ModuleVersion = '0.0.122'
|
||||
ModuleName = 'PSWriteHTML'
|
||||
Guid = 'a7bdf640-f5cb-4acf-9de0-365b322d245c'
|
||||
}, 'CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Security')
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
if ($GPOEntry.SettingBoolean) {
|
||||
$Settings[$($GPOEntry.Name)] = if ($GPOEntry.SettingBoolean -eq 'true') { 'Enabled' } elseif ($GPOEntry.SettingBoolean -eq 'false') { 'Disabled' } else { 'Not set' };
|
||||
} elseif ($GPOEntry.SettingNumber) {
|
||||
$Settings[$($GPOEntry.Name)] = [int] $GPOEntry.SettingNumber
|
||||
$Settings[$($GPOEntry.Name)] = [int64] $GPOEntry.SettingNumber
|
||||
}
|
||||
}
|
||||
[PSCustomObject] $Settings
|
||||
@@ -84,7 +84,7 @@
|
||||
if ($GPOEntry.SettingBoolean) {
|
||||
$CreateGPO[$($GPOEntry.Name)] = if ($GPOEntry.SettingBoolean -eq 'true') { 'Enabled' } elseif ($GPOEntry.SettingBoolean -eq 'false') { 'Disabled' } else { 'Not set' };
|
||||
} elseif ($GPOEntry.SettingNumber) {
|
||||
$CreateGPO[$($GPOEntry.Name)] = [int] $GPOEntry.SettingNumber
|
||||
$CreateGPO[$($GPOEntry.Name)] = [int64] $GPOEntry.SettingNumber
|
||||
}
|
||||
}
|
||||
$CreateGPO['Linked'] = $GPO.Linked
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
function Get-PermissionsAnalysis {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[PSCustomObject] $GPOPermissions,
|
||||
[validateset('WellKnownAdministrative', 'Administrative', 'AuthenticatedUsers', 'Default')][string] $Type = 'Default',
|
||||
[Parameter(Mandatory)][alias('IncludePermissionType')][Microsoft.GroupPolicy.GPPermissionType] $PermissionType,
|
||||
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
[System.Collections.IDictionary] $ADAdministrativeGroups
|
||||
)
|
||||
if (-not $ADAdministrativeGroups) {
|
||||
$ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
}
|
||||
$AdministrativeExists = @{
|
||||
Skip = $false
|
||||
DomainAdmins = $false
|
||||
EnterpriseAdmins = $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
|
||||
$AdministrativeExists['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']) {
|
||||
$AdministrativeExists['Skip'] = $true
|
||||
break
|
||||
}
|
||||
} elseif ($Type -eq 'WellKnownAdministrative') {
|
||||
# this is for SYSTEM account
|
||||
$AdministrativeExists['Skip'] = $true
|
||||
break
|
||||
} elseif ($Type -eq 'AuthenticatedUsers') {
|
||||
# this is for Authenticated Users
|
||||
$AdministrativeExists['Skip'] = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
$AdministrativeExists
|
||||
}
|
||||
@@ -166,7 +166,7 @@
|
||||
#>
|
||||
|
||||
# I don't trust the returned data, some stuff like 'alias' shows up for groups. To unify it with everything else... using my own function
|
||||
$PermissionAccount = Get-WinADObject -Identity $GPOPermission.Trustee.Sid.Value -AddType -Cache
|
||||
$PermissionAccount = Get-WinADObject -Identity $GPOPermission.Trustee.Sid.Value -AddType -Cache -Verbose:$false
|
||||
if ($PermissionAccount) {
|
||||
$UserNameDomain = $PermissionAccount.DomainName
|
||||
$UserName = $PermissionAccount.Name
|
||||
@@ -214,7 +214,7 @@
|
||||
if ($IncludeOwner) {
|
||||
if ($GPO.Owner) {
|
||||
# I don't trust the returned data, some stuff like 'alias' shows up for groups. To unify it with everything else... using my own function
|
||||
$OwnerAccount = Get-WinADObject -Identity $GPO.Owner -AddType -Cache
|
||||
$OwnerAccount = Get-WinADObject -Identity $GPO.Owner -AddType -Cache -Verbose:$false
|
||||
if ($OwnerAccount) {
|
||||
$UserNameDomain = $OwnerAccount.DomainName
|
||||
$UserName = $OwnerAccount.Name
|
||||
|
||||
+53
-22
@@ -7,7 +7,8 @@
|
||||
[switch] $OwnerOnly,
|
||||
[System.Collections.IDictionary] $ADAdministrativeGroups,
|
||||
[string] $Splitter = [System.Environment]::NewLine,
|
||||
[switch] $ReturnObject
|
||||
[switch] $ReturnObject,
|
||||
[System.Collections.IDictionary] $ExcludeGroupPolicies
|
||||
)
|
||||
if ($XMLContent.GPO.LinksTo) {
|
||||
$LinkSplit = ([Array] $XMLContent.GPO.LinksTo).Where( { $_.Enabled -eq $true }, 'Split')
|
||||
@@ -27,30 +28,35 @@
|
||||
$LinksDisabledCount = 0
|
||||
$LinksTotalCount = 0
|
||||
}
|
||||
#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
|
||||
} elseif ($XMLContent.GPO.Computer.Enabled -eq 'True') {
|
||||
$ComputerEnabled = $true
|
||||
} else {
|
||||
Write-Warning "Get-XMLGPO - Computer enabled not set to true or false. Weird."
|
||||
$ComputerEnabled = $null
|
||||
}
|
||||
if ($XMLContent.GPO.User.Enabled -eq 'False') {
|
||||
$UserEnabled = $false
|
||||
} elseif ($XMLContent.GPO.User.Enabled -eq 'True') {
|
||||
$UserEnabled = $true
|
||||
} else {
|
||||
Write-Warning "Get-XMLGPO - User enabled not set to true or false. Weird."
|
||||
$UserEnabled = $null
|
||||
}
|
||||
# Translate Enabled to same as GPO GUI
|
||||
if ($UserEnabled -eq $True -and $ComputerEnabled -eq $true) {
|
||||
$EnabledBool = $true
|
||||
$Enabled = 'Enabled'
|
||||
} elseif ($UserEnabled -eq $false -and $ComputerEnabled -eq $false) {
|
||||
$EnabledBool = $false
|
||||
$Enabled = 'All settings disabled'
|
||||
} elseif ($UserEnabled -eq $true -and $ComputerEnabled -eq $false) {
|
||||
$EnabledBool = $True
|
||||
$Enabled = 'Computer configuration settings disabled'
|
||||
} elseif ($UserEnabled -eq $false -and $ComputerEnabled -eq $true) {
|
||||
$EnabledBool = $True
|
||||
$Enabled = 'User configuration settings disabled'
|
||||
}
|
||||
|
||||
@@ -58,9 +64,9 @@
|
||||
$UserSettingsAvailable = if ($null -eq $XMLContent.GPO.User.ExtensionData) { $false } else { $true }
|
||||
|
||||
if ($ComputerSettingsAvailable -eq $false -and $UserSettingsAvailable -eq $false) {
|
||||
$Empty = $true
|
||||
$NoSettings = $true
|
||||
} else {
|
||||
$Empty = $false
|
||||
$NoSettings = $false
|
||||
}
|
||||
|
||||
# $OutputUser = $XMLContent.GPO.User.ExtensionData.Extension | Where-Object { $_.PSObject.Properties.TypeNameOfValue -in 'System.Xml.XmlElement', 'System.Object[]' }
|
||||
@@ -72,7 +78,7 @@
|
||||
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)"
|
||||
Write-Warning "Get-XMLGPO - things went sideways $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -84,7 +90,7 @@
|
||||
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)"
|
||||
Write-Warning "Get-XMLGPO - things went sideways $($_.Exception.Message)"
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -95,9 +101,9 @@
|
||||
$UserSettingsAvailableReal = if ($OutputUser) { $true } else { $false }
|
||||
|
||||
if (-not $ComputerSettingsAvailableReal -and -not $UserSettingsAvailableReal) {
|
||||
$EmptyMaybe = $true
|
||||
$Empty = $true
|
||||
} else {
|
||||
$EmptyMaybe = $false
|
||||
$Empty = $false
|
||||
}
|
||||
|
||||
$ComputerProblem = $false
|
||||
@@ -126,8 +132,19 @@
|
||||
$UserProblem = $true
|
||||
}
|
||||
|
||||
if ($UserProblem -or $ComputerProblem) {
|
||||
$Problem = $true
|
||||
} else {
|
||||
$Problem = $false
|
||||
}
|
||||
if ($UserOptimized -and $ComputerOptimized) {
|
||||
$Optimized = $true
|
||||
} else {
|
||||
$Optimized = $false
|
||||
}
|
||||
|
||||
if (-not $PermissionsOnly) {
|
||||
if ($XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text') {
|
||||
if ($ADAdministrativeGroups -and $XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text') {
|
||||
$AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text')"]
|
||||
$WellKnown = ConvertFrom-SID -SID $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' -OnlyWellKnown
|
||||
if ($AdministrativeGroup) {
|
||||
@@ -137,8 +154,18 @@
|
||||
} else {
|
||||
$OwnerType = 'NotAdministrative'
|
||||
}
|
||||
} else {
|
||||
} elseif ($ADAdministrativeGroups) {
|
||||
$OwnerType = 'Unknown'
|
||||
} else {
|
||||
$OwnerType = 'Unable to asses (local files?)'
|
||||
}
|
||||
}
|
||||
# Mark GPO as excluded
|
||||
$Exclude = $false
|
||||
if ($ExcludeGroupPolicies) {
|
||||
$PolicyWithDomain = -join ($XMLContent.GPO.Identifier.Domain.'#text', $XMLContent.GPO.Name)
|
||||
if ($ExcludeGroupPolicies[$XMLContent.GPO.Name] -or $ExcludeGroupPolicies[$PolicyWithDomain]) {
|
||||
$Exclude = $true
|
||||
}
|
||||
}
|
||||
if ($PermissionsOnly) {
|
||||
@@ -189,32 +216,36 @@
|
||||
'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text'
|
||||
'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}'
|
||||
'Empty' = $Empty
|
||||
'EmptyMaybe' = $EmptyMaybe
|
||||
'Linked' = $Linked
|
||||
'Enabled' = $EnabledBool
|
||||
'Optimized' = $Optimized
|
||||
'Problem' = $Problem
|
||||
'Exclude' = $Exclude
|
||||
'ComputerPolicies' = $XMLContent.GPO.Computer.ExtensionData.Name -join ", "
|
||||
'UserPolicies' = $XMLContent.GPO.User.ExtensionData.Name -join ", "
|
||||
'LinksCount' = $LinksTotalCount
|
||||
'LinksEnabledCount' = $LinksEnabledCount
|
||||
'LinksDisabledCount' = $LinksDisabledCount
|
||||
'Enabled' = $Enabled
|
||||
'ComputerEnabled' = $ComputerEnabled
|
||||
'ComputerOptimized' = $ComputerOptimized
|
||||
'EnabledDetails' = $Enabled
|
||||
'ComputerProblem' = $ComputerProblem
|
||||
'UserEnabled' = $UserEnabled
|
||||
'UserOptimized' = $UserOptimized
|
||||
'ComputerOptimized' = $ComputerOptimized
|
||||
'UserProblem' = $UserProblem
|
||||
'UserOptimized' = $UserOptimized
|
||||
'ComputerSettingsAvailable' = $ComputerSettingsAvailable
|
||||
'UserSettingsAvailable' = $UserSettingsAvailable
|
||||
'ComputerSettingsAvailableReal' = $ComputerSettingsAvailableReal
|
||||
'UserSettingsAvailableReal' = $UserSettingsAvailableReal
|
||||
'ComputerSettingsTypes' = $OutputComputer.Name
|
||||
'UserSettingsTypes' = $OutputUser.Name
|
||||
'ComputerEnabled' = $ComputerEnabled
|
||||
'UserEnabled' = $UserEnabled
|
||||
'ComputerSettingsStatus' = if ($XMLContent.GPO.Computer.VersionDirectory -eq 0 -and $XMLContent.GPO.Computer.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" }
|
||||
'ComputerSetttingsVersionIdentical' = if ($XMLContent.GPO.Computer.VersionDirectory -eq $XMLContent.GPO.Computer.VersionSysvol) { $true } else { $false }
|
||||
'ComputerSettings' = $XMLContent.GPO.Computer.ExtensionData.Extension
|
||||
'UserSettingsStatus' = if ($XMLContent.GPO.User.VersionDirectory -eq 0 -and $XMLContent.GPO.User.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" }
|
||||
'UserSettingsVersionIdentical' = if ($XMLContent.GPO.User.VersionDirectory -eq $XMLContent.GPO.User.VersionSysvol) { $true } else { $false }
|
||||
'UserSettings' = $XMLContent.GPO.User.ExtensionData.Extension
|
||||
'ComputerPolicies' = $XMLContent.GPO.Computer.ExtensionData.Name -join ", "
|
||||
'UserPolicies' = $XMLContent.GPO.User.ExtensionData.Name -join ", "
|
||||
'NoSettings' = $NoSettings
|
||||
'CreationTime' = [DateTime] $XMLContent.GPO.CreatedTime
|
||||
'ModificationTime' = [DateTime] $XMLContent.GPO.ModifiedTime
|
||||
'ReadTime' = [DateTime] $XMLContent.GPO.ReadTime
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Invoke-GPOZaurrContent
|
||||
Invoke-GPOZaurrContent -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrInheritance -IncludeBlockedObjects -OnlyBlockedInheritance
|
||||
Get-GPOZaurrInheritance -IncludeBlockedObjects -OnlyBlockedInheritance -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
Enabled = $true
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Execute = { Get-GPOZaurrPermissionConsistency -Type All -VerifyInheritance }
|
||||
Execute = {
|
||||
Get-GPOZaurrPermissionConsistency -Type All -VerifyInheritance -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
foreach ($GPO in $Script:Reporting['GPOConsistency']['Data']) {
|
||||
if ($GPO.ACLConsistent -eq $true) {
|
||||
@@ -17,7 +19,7 @@
|
||||
$Script:Reporting['GPOConsistency']['Variables']['InconsistentInside']++
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOConsistency']['Variables']['Inconsistent'].Count -gt 0 -or $Script:Reporting['GPOConsistency']['Variables']['InconsistentInside'].Count -gt 0 ) {
|
||||
if ($Script:Reporting['GPOConsistency']['Variables']['Inconsistent'] -gt 0 -or $Script:Reporting['GPOConsistency']['Variables']['InconsistentInside'] -gt 0 ) {
|
||||
$Script:Reporting['GPOConsistency']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOConsistency']['ActionRequired'] = $false
|
||||
@@ -90,6 +92,74 @@
|
||||
New-HTMLTableCondition -Name 'ACLConsistentInside' -Value 'Not available' -BackgroundColor Crimson -ComparisonType string
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix - Permissions Consistency' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLText -Text 'Following steps will guide you how to fix permissions consistency'
|
||||
New-HTMLWizard {
|
||||
New-HTMLWizardStep -Name 'Prepare environment' {
|
||||
New-HTMLText -Text "To be able to execute actions in automated way please install required modules. Those modules will be installed straight from Microsoft PowerShell Gallery."
|
||||
New-HTMLCodeBlock -Code {
|
||||
Install-Module GPOZaurr -Force
|
||||
Import-Module GPOZaurr -Force
|
||||
} -Style powershell
|
||||
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding fixing permissions inconsistencies. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrPermissionsInconsistentBefore.html -Verbose -Type GPOConsistency
|
||||
}
|
||||
New-HTMLText -Text {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurrPermissionConsistency
|
||||
$GPOOutput | Format-Table # do your actions as desired
|
||||
}
|
||||
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Fix inconsistent permissions' {
|
||||
New-HTMLText -Text "Following command when executed fixes inconsistent permissions."
|
||||
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-HTMLText -Text "Make sure to fill in TargetDomain to match your Domain Admin permission account"
|
||||
|
||||
New-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrPermissionConsistency -IncludeDomains "TargetDomain" -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 deleted matches expected data. Once happy with results please follow with command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrPermissionConsistency -LimitProcessing 2 -IncludeDomains "TargetDomain"
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed repairs only first X inconsistent permissions. Use LimitProcessing parameter to prevent mass fixing 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-HTMLText -Text "If there's nothing else to be fixed, we can skip to next step step"
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Fix inconsistent downlevel permissions' {
|
||||
New-HTMLText -Text "Unfortunetly this step is manual until automation is developed. "
|
||||
New-HTMLText -Text "If there are inconsistent permissions found inside GPO one has to fix them manually by going into SYSVOL and making sure inheritance is enabled, and that permissions are consistent across all files."
|
||||
}
|
||||
New-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\GPOZaurrPermissionsInconsistentAfter.html -Verbose -Type GPOConsistency
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOConsistency']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOConsistency']['WarningsAndErrors'] -Filtering {
|
||||
@@ -98,71 +168,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'Steps to fix - Permissions Consistency' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLText -Text 'Following steps will guide you how to fix permissions consistency'
|
||||
New-HTMLWizard {
|
||||
New-HTMLWizardStep -Name 'Prepare environment' {
|
||||
New-HTMLText -Text "To be able to execute actions in automated way please install required modules. Those modules will be installed straight from Microsoft PowerShell Gallery."
|
||||
New-HTMLCodeBlock -Code {
|
||||
Install-Module GPOZaurr -Force
|
||||
Import-Module GPOZaurr -Force
|
||||
} -Style powershell
|
||||
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding fixing permissions inconsistencies. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrPermissionsInconsistentBefore.html -Verbose -Type GPOConsistency
|
||||
}
|
||||
New-HTMLText -Text {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurrPermissionConsistency
|
||||
$GPOOutput | Format-Table # do your actions as desired
|
||||
}
|
||||
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Fix inconsistent permissions' {
|
||||
New-HTMLText -Text "Following command when executed fixes inconsistent permissions."
|
||||
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-HTMLText -Text "Make sure to fill in TargetDomain to match your Domain Admin permission account"
|
||||
|
||||
New-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrPermissionConsistency -IncludeDomains "TargetDomain" -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 deleted matches expected data. Once happy with results please follow with command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrPermissionConsistency -LimitProcessing 2 -IncludeDomains "TargetDomain"
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed repairs only first X inconsistent permissions. Use LimitProcessing parameter to prevent mass fixing 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-HTMLText -Text "If there's nothing else to be fixed, we can skip to next step step"
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Fix inconsistent downlevel permissions' {
|
||||
New-HTMLText -Text "Unfortunetly this step is manual until automation is developed. "
|
||||
New-HTMLText -Text "If there are inconsistent permissions found inside GPO one has to fix them manually by going into SYSVOL and making sure inheritance is enabled, and that permissions are consistent across all files."
|
||||
}
|
||||
New-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\GPOZaurrPermissionsInconsistentAfter.html -Verbose -Type GPOConsistency
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
Action = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrDuplicateObject
|
||||
Get-GPOZaurrDuplicateObject -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
$Script:Reporting['GPODuplicates']['Variables']['RequireDeletion'] = $Script:Reporting['GPODuplicates']['Data'].Count
|
||||
@@ -40,7 +40,7 @@
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartLegend -Names 'Bad' -Color PaleGreen, Salmon
|
||||
New-ChartLegend -Names 'Bad' -Color Salmon
|
||||
New-ChartBar -Name 'Duplicate (CNF) object' -Value $Script:Reporting['GPODuplicates']['Data'].Count
|
||||
} -Title 'Duplicate (CNF) Objects' -TitleAlignment center
|
||||
}
|
||||
@@ -50,6 +50,67 @@
|
||||
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix - Remove duplicate (CNF) objects' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLWizard {
|
||||
New-HTMLWizardStep -Name 'Prepare environment' {
|
||||
New-HTMLText -Text "To be able to execute actions in automated way please install required modules. Those modules will be installed straight from Microsoft PowerShell Gallery."
|
||||
New-HTMLCodeBlock -Code {
|
||||
Install-Module GPOZaurr -Force
|
||||
Import-Module GPOZaurr -Force
|
||||
} -Style powershell
|
||||
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding fixing duplicate GPO objects. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrDuplicateObjectsBefore.html -Verbose -Type GPODuplicates
|
||||
}
|
||||
New-HTMLText -Text {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment. "
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step. "
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurrDuplicateObject
|
||||
$GPOOutput | Format-Table # do your actions as desired
|
||||
}
|
||||
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove CNF objects' {
|
||||
New-HTMLText -Text "Following command when executed, runs internally command that lists all duplicate objects."
|
||||
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-GPOZaurrDuplicateObject -WhatIf -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be changed matches expected data. Once happy with results please follow with command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrDuplicateObject -Verbose -LimitProcessing 2
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed removes only first X duplicate objects. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur. "
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly. "
|
||||
}
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Verification report' {
|
||||
New-HTMLText -TextBlock {
|
||||
"Once cleanup task was executed properly, we need to verify that report now shows no problems."
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrDuplicateObjectsAfter.html -Verbose -Type GPODuplicates
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPODuplicates']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPODuplicates']['WarningsAndErrors'] -Filtering {
|
||||
@@ -58,65 +119,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'Steps to fix - Remove duplicate (CNF) objects' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLText -Text 'Following steps will guide you how to remove duplicate objects'
|
||||
New-HTMLWizard {
|
||||
New-HTMLWizardStep -Name 'Prepare environment' {
|
||||
New-HTMLText -Text "To be able to execute actions in automated way please install required modules. Those modules will be installed straight from Microsoft PowerShell Gallery."
|
||||
New-HTMLCodeBlock -Code {
|
||||
Install-Module GPOZaurr -Force
|
||||
Import-Module GPOZaurr -Force
|
||||
} -Style powershell
|
||||
New-HTMLText -Text "Using force makes sure newest version is downloaded from PowerShellGallery regardless of what is currently installed. Once installed you're ready for next step."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding fixing duplicate GPO objects. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrDuplicateObjectsBefore.html -Verbose -Type GPODuplicates
|
||||
}
|
||||
New-HTMLText -Text {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurrDuplicateObject
|
||||
$GPOOutput | Format-Table # do your actions as desired
|
||||
}
|
||||
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove CNF objects' {
|
||||
New-HTMLText -Text "Following command when executed, runs internally command that lists all duplicate objects."
|
||||
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-GPOZaurrDuplicateObject -WhatIf -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be changed matches expected data. Once happy with results please follow with command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrDuplicateObject -Verbose -LimitProcessing 2
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed removes only first X duplicate objects. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur."
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly."
|
||||
}
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Verification report' {
|
||||
New-HTMLText -TextBlock {
|
||||
"Once cleanup task was executed properly, we need to verify that report now shows no problems."
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrDuplicateObjectsAfter.html -Verbose -Type GPODuplicates
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrFiles
|
||||
Get-GPOZaurrFiles -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
|
||||
|
||||
+287
-126
@@ -4,10 +4,20 @@
|
||||
Action = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurr
|
||||
if ($Script:Reporting['GPOList']['ExclusionsCode']) {
|
||||
Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExcludeGroupPolicies $Script:Reporting['GPOList']['ExclusionsCode']
|
||||
|
||||
} else {
|
||||
Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
}
|
||||
Processing = {
|
||||
foreach ($GPO in $Script:Reporting['GPOList']['Data']) {
|
||||
if ($GPO.Enabled -eq $false -or $GPO.Empty -eq $true -or $GPO.Linked -eq $false) {
|
||||
$Script:Reporting['GPOList']['Variables']['GPONotValid']++
|
||||
} else {
|
||||
$Script:Reporting['GPOList']['Variables']['GPOValid']++
|
||||
}
|
||||
if ($GPO.Linked -eq $false -and $GPO.Empty -eq $true) {
|
||||
# Not linked, Empty
|
||||
$Script:Reporting['GPOList']['Variables']['GPOEmptyAndUnlinked']++
|
||||
@@ -32,14 +42,17 @@
|
||||
$Script:Reporting['GPOList']['Variables']['GPOLinked']++
|
||||
} else {
|
||||
# Linked, not EMPTY
|
||||
$Script:Reporting['GPOList']['Variables']['GPOValid']++
|
||||
$Script:Reporting['GPOList']['Variables']['GPOLinked']++
|
||||
$Script:Reporting['GPOList']['Variables']['GPONotEmpty']++
|
||||
}
|
||||
if ($GPO.Enabled -eq $true) {
|
||||
$Script:Reporting['GPOList']['Variables']['GPOEnabled']++
|
||||
} else {
|
||||
$Script:Reporting['GPOList']['Variables']['GPODisabled']++
|
||||
}
|
||||
if ($GPO.LinksDisabledCount -eq $GPO.LinksCount -and $GPO.LinksCount -gt 0) {
|
||||
$Script:Reporting['GPOList']['Variables']['GPOLinkedButLinkDisabled']++
|
||||
}
|
||||
|
||||
if ($GPO.ComputerOptimized -eq $true) {
|
||||
$Script:Reporting['GPOList']['Variables']['ComputerOptimizedYes']++
|
||||
} else {
|
||||
@@ -63,9 +76,19 @@
|
||||
if ($GPO.UserProblem -or $GPO.ComputerProblem) {
|
||||
$Script:Reporting['GPOList']['Variables']['GPOWithProblems']++
|
||||
}
|
||||
if ($GPO.Problem -eq $true) {
|
||||
$Script:Reporting['GPOList']['Variables']['GPOProblem']++
|
||||
} else {
|
||||
$Script:Reporting['GPOList']['Variables']['GPONoProblem']++
|
||||
}
|
||||
if ($GPO.Optimized -eq $true) {
|
||||
$Script:Reporting['GPOList']['Variables']['GPOOptimized']++
|
||||
} else {
|
||||
$Script:Reporting['GPOList']['Variables']['GPONotOptimized']++
|
||||
}
|
||||
}
|
||||
$Script:Reporting['GPOList']['Variables']['GPOTotal'] = $Script:Reporting['GPOList']['Data'].Count
|
||||
if ($Script:Reporting['GPOList']['Variables']['GPOEmptyOrUnlinked'].Count -gt 0) {
|
||||
if ($Script:Reporting['GPOList']['Variables']['GPONotValid'] -gt 0) {
|
||||
$Script:Reporting['GPOList']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOList']['ActionRequired'] = $false
|
||||
@@ -81,6 +104,10 @@
|
||||
UserOptimizedNo = 0
|
||||
UserProblemYes = 0
|
||||
UserProblemNo = 0
|
||||
GPOOptimized = 0
|
||||
GPONotOptimized = 0
|
||||
GPOProblem = 0
|
||||
GPONoProblem = 0
|
||||
GPONotLinked = 0
|
||||
GPOLinked = 0
|
||||
GPOEmpty = 0
|
||||
@@ -88,36 +115,15 @@
|
||||
GPOEmptyAndUnlinked = 0
|
||||
GPOEmptyOrUnlinked = 0
|
||||
GPOLinkedButEmpty = 0
|
||||
GPOEnabled = 0
|
||||
GPODisabled = 0
|
||||
GPOValid = 0
|
||||
GPONotValid = 0
|
||||
GPOLinkedButLinkDisabled = 0
|
||||
GPOTotal = 0
|
||||
}
|
||||
Overview = {
|
||||
New-HTMLPanel {
|
||||
New-HTMLText -Text 'Following chart presents ', 'Linked / Empty and Unlinked Group Policies' -FontSize 10pt -FontWeight normal, bold
|
||||
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']['GPOEmptyOrUnlinked'] -FontWeight normal, bold {
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies that are unlinked (are not doing anything currently): ', $Script:Reporting['GPOList']['Variables']['GPONotLinked'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are empty (have no settings): ", $Script:Reporting['GPOList']['Variables']['GPOEmpty'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are linked, but empty: ", $Script:Reporting['GPOList']['Variables']['GPOLinkedButEmpty'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are linked, but link disabled: ", $Script:Reporting['GPOList']['Variables']['GPOLinkedButLinkDisabled'] -FontWeight normal, bold
|
||||
}
|
||||
}
|
||||
}
|
||||
New-HTMLText -FontSize 10pt -Text 'Usually empty or unlinked Group Policies are safe to delete.'
|
||||
New-HTMLChart -Title 'Group Policies Summary' {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
#New-ChartLegend -Names 'Unlinked', 'Linked', 'Empty', 'Total' -Color Salmon, PaleGreen, PaleVioletRed, PaleTurquoise
|
||||
New-ChartLegend -Names 'Good', 'Bad' -Color PaleGreen, Salmon
|
||||
#New-ChartBar -Name 'Group Policies' -Value $Script:Reporting['GPOList']['Variables']['GPONotLinked'], $Script:Reporting['GPOList']['Variables']['GPOLinked'], $Script:Reporting['GPOList']['Variables']['GPOEmpty'], $Script:Reporting['GPOList']['Variables']['GPOTotal']
|
||||
New-ChartBar -Name 'Linked' -Value $Script:Reporting['GPOList']['Variables']['GPOLinked'], $Script:Reporting['GPOList']['Variables']['GPONotLinked']
|
||||
New-ChartBar -Name 'Empty' -Value $Script:Reporting['GPOList']['Variables']['GPONotEmpty'], $Script:Reporting['GPOList']['Variables']['GPOEmpty']
|
||||
New-ChartBar -Name 'Valid' -Value $Script:Reporting['GPOList']['Variables']['GPOValid'], $Script:Reporting['GPOList']['Variables']['GPOEmptyOrUnlinked']
|
||||
} -TitleAlignment center
|
||||
}
|
||||
|
||||
}
|
||||
Summary = {
|
||||
New-HTMLText -TextBlock {
|
||||
@@ -129,16 +135,32 @@
|
||||
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']['GPOEmptyOrUnlinked'] -FontWeight normal, bold {
|
||||
New-HTMLListItem -Text "Group Policies to delete: ", $Script:Reporting['GPOList']['Variables']['GPONotValid'] -FontWeight normal, bold {
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies that are unlinked (are not doing anything currently): ', $Script:Reporting['GPOList']['Variables']['GPONotLinked'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are empty (have no settings): ", $Script:Reporting['GPOList']['Variables']['GPOEmpty'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are linked, but empty: ", $Script:Reporting['GPOList']['Variables']['GPOLinkedButEmpty'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are linked, but link disabled: ", $Script:Reporting['GPOList']['Variables']['GPOLinkedButLinkDisabled'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies that are disabled (both user/computer sections): ", $Script:Reporting['GPOList']['Variables']['GPODisabled'] -FontWeight normal, bold
|
||||
}
|
||||
}
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text "Additionally, we're reviewing Group Policies that have their section disabled, but contain data. Please review them and make sure this configuration is as expected!" -FontSize 10pt
|
||||
New-HTMLText -Text "Keep in mind that each GPO can match multiple conditions such as being empty and unlinked and disabled at the same time. We're only deleting GPO once." -FontSize 10pt
|
||||
New-HTMLText -Text @(
|
||||
'All ',
|
||||
'empty',
|
||||
' or ',
|
||||
'unlinked',
|
||||
' or ',
|
||||
'disabled',
|
||||
' Group Policies can be automatically deleted. Please review output in the table and follow steps below table to cleanup Group Policies. ',
|
||||
'GPOs that have content, but are disabled require manual intervention. ',
|
||||
"If performance is an issue you should consider disabling user or computer sections of GPO when those are not used. "
|
||||
) -FontSize 10pt -FontWeight normal, bold, normal, bold, normal, bold, normal, normal, normal, normal
|
||||
|
||||
New-HTMLText -LineBreak
|
||||
|
||||
New-HTMLText -Text "Additionally, we're reviewing Group Policies that have their section disabled, but contain data." -FontSize 10pt
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies with problems: ', $Script:Reporting['GPOList']['Variables']['GPOWithProblems'] -FontWeight normal, bold {
|
||||
New-HTMLList -Type Unordered {
|
||||
@@ -147,7 +169,15 @@
|
||||
}
|
||||
}
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text "For best performance it's recommended that if there are no settings of certain kind (Computer or User settings) it's best to disable them. " -FontSize 10pt
|
||||
New-HTMLText -Text @(
|
||||
"Such policies require manual review from whoever owns them. "
|
||||
"It could be a mistake tha section was disabled while containing data or that content is no longer needed in which case it should be deleted. "
|
||||
"This can't be auto-handled and is INFORMATIONAL only. "
|
||||
) -FontSize 10pt
|
||||
|
||||
New-HTMLText -LineBreak
|
||||
|
||||
New-HTMLText -Text "Moreover, for best performance it's recommended that if there are no settings of certain kind (Computer or User settings) it's best to disable whole section. " -FontSize 10pt
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies with optimization: ' -FontWeight normal, bold {
|
||||
New-HTMLList -Type Unordered {
|
||||
@@ -162,11 +192,11 @@
|
||||
}
|
||||
}
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -TextBlock {
|
||||
'All empty or unlinked Group Policies can be automatically deleted. Please review output in the table and follow steps below table to cleanup Group Policies. '
|
||||
'GPOs that have content, but are disabled require manual intervention. '
|
||||
"If performance is an issue you should consider disabling user or computer sections of GPO when those are not used. "
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text @(
|
||||
"This means "
|
||||
$Script:Reporting['GPOList']['Variables']['GPONotOptimized']
|
||||
" could be optimized for performance reasons. "
|
||||
) -FontSize 10pt -FontWeight normal, bold, normal
|
||||
}
|
||||
Solution = {
|
||||
New-HTMLSection -Invisible {
|
||||
@@ -178,108 +208,239 @@
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Names 'Yes', 'No' -Color SpringGreen, Salmon
|
||||
New-ChartBar -Name 'Linked' -Value $Script:Reporting['GPOList']['Variables']['GPOLinked'], $Script:Reporting['GPOList']['Variables']['GPONotLinked']
|
||||
New-ChartBar -Name 'Empty' -Value $Script:Reporting['GPOList']['Variables']['GPONotEmpty'], $Script:Reporting['GPOList']['Variables']['GPOEmpty']
|
||||
New-ChartBar -Name 'Valid' -Value $Script:Reporting['GPOList']['Variables']['GPOValid'], $Script:Reporting['GPOList']['Variables']['GPOEmptyOrUnlinked']
|
||||
New-ChartBar -Name 'With problem (computers)' -Value $Script:Reporting['GPOList']['Variables']['ComputerProblemNo'], $Script:Reporting['GPOList']['Variables']['ComputerProblemYes']
|
||||
New-ChartBar -Name 'With problem (users)' -Value $Script:Reporting['GPOList']['Variables']['UserProblemNo'], $Script:Reporting['GPOList']['Variables']['UserProblemYes']
|
||||
New-ChartBar -Name 'Not Empty' -Value $Script:Reporting['GPOList']['Variables']['GPONotEmpty'], $Script:Reporting['GPOList']['Variables']['GPOEmpty']
|
||||
New-ChartBar -Name 'Enabled' -Value $Script:Reporting['GPOList']['Variables']['GPOEnabled'], $Script:Reporting['GPOList']['Variables']['GPODisabled']
|
||||
New-ChartBar -Name 'Valid' -Value $Script:Reporting['GPOList']['Variables']['GPOValid'], $Script:Reporting['GPOList']['Variables']['GPONotValid']
|
||||
New-ChartBar -Name 'Optimized (for speed)' -Value $Script:Reporting['GPOList']['Variables']['GPOOptimized'], $Script:Reporting['GPOList']['Variables']['GPONotOptimized']
|
||||
New-ChartBar -Name 'No problem' -Value $Script:Reporting['GPOList']['Variables']['GPONoProblem'], $Script:Reporting['GPOList']['Variables']['GPOProblem']
|
||||
New-ChartBar -Name 'No problem (computers)' -Value $Script:Reporting['GPOList']['Variables']['ComputerProblemNo'], $Script:Reporting['GPOList']['Variables']['ComputerProblemYes']
|
||||
New-ChartBar -Name 'No problem (users)' -Value $Script:Reporting['GPOList']['Variables']['UserProblemNo'], $Script:Reporting['GPOList']['Variables']['UserProblemYes']
|
||||
New-ChartBar -Name 'Optimized Computers' -Value $Script:Reporting['GPOList']['Variables']['ComputerOptimizedYes'], $Script:Reporting['GPOList']['Variables']['ComputerOptimizedNo']
|
||||
New-ChartBar -Name 'Optimized Users' -Value $Script:Reporting['GPOList']['Variables']['UserOptimizedYes'], $Script:Reporting['GPOList']['Variables']['UserOptimizedNo']
|
||||
} -TitleAlignment center
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policies List' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOList']['Data'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Empty' -Value $true -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Linked' -Value $false -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerProblem' -Value $true -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'UserProblem' -Value $true -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerOptimized' -Value $false -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'UserOptimized' -Value $false -BackgroundColor Salmon -TextTransform capitalize -ComparisonType string
|
||||
# reverse
|
||||
New-HTMLTableCondition -Name 'Empty' -Value $false -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Linked' -Value $true -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerProblem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'UserProblem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerOptimized' -Value $true -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'UserOptimized' -Value $true -BackgroundColor SpringGreen -TextTransform capitalize -ComparisonType string
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
New-HTMLContainer {
|
||||
New-HTMLText -Text 'Explanation to table columns:' -FontSize 10pt
|
||||
New-HTMLList {
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "Empty", " - means GPO has currently no content. It could be there was content, but it was removed, or that it never had content. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "Linked", " - means GPO is linked or unlinked. We need at least one link that is enabled to mark it as linked. If GPO is linked, but all links are disabled, it's not linked. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "Enabled", " - means GPO has at least one section enabled. If enabled is set to false that means both sections are disabled, and therefore GPO is not active. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "Optimized", " - means GPO section that is not in use is disabled. If section (user or computer) is enabled and there is no content, it's not optimized. "
|
||||
New-HTMLListItem -FontWeight bold, normal -Text "Problem", " - means GPO has one or more section (user or computer) that is disabled, yet there is content in it. "
|
||||
} -FontSize 10pt
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOList']['Data'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Exclude' -Value $true -BackgroundColor DeepSkyBlue -ComparisonType string -Row
|
||||
|
||||
New-HTMLTableCondition -Name 'Empty' -Value $true -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Linked' -Value $false -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Enabled' -Value $false -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Optimized' -Value $false -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Problem' -Value $true -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerProblem' -Value $true -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'UserProblem' -Value $true -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerOptimized' -Value $false -BackgroundColor Salmon -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'UserOptimized' -Value $false -BackgroundColor Salmon -TextTransform capitalize -ComparisonType string
|
||||
# reverse
|
||||
New-HTMLTableCondition -Name 'Empty' -Value $false -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Linked' -Value $true -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Enabled' -Value $true -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Optimized' -Value $true -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'Problem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerProblem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'UserProblem' -Value $false -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'ComputerOptimized' -Value $true -BackgroundColor SpringGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'UserOptimized' -Value $true -BackgroundColor SpringGreen -TextTransform capitalize -ComparisonType string
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix - Empty & Unlinked & Disabled Group Policies' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLText -Text 'Following steps will guide you how to remove empty or unlinked group policies'
|
||||
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 removal. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrEmptyUnlinked.html -Verbose -Type GPOList
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurr
|
||||
$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 'Make a backup' {
|
||||
New-HTMLText -TextBlock {
|
||||
"The process of deleting Group Policies is final. Once GPO is removed - it's gone. "
|
||||
"To make sure you can recover deleted GPO please make sure to back them up. "
|
||||
}
|
||||
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. "
|
||||
"Keep in mind that Remove-GPOZaurr command also has a backup feature built-in. "
|
||||
"It's possible to skip this backup and use the backup provided as part of Remove-GPOZaurr command. "
|
||||
}
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Excluding Group Policies' {
|
||||
New-HTMLText -Text @(
|
||||
"Remove-GPOZaurr",
|
||||
" cmdlet that you will use in next steps is pretty advanced in what it can do. It can remove one or multiple types of problems at the same time. "
|
||||
"That means you can pick just EMPTY, just UNLINKED or just DISABLED but also a mix of them if you want. "
|
||||
"It also provides a way to exclude some GPOs from being removed even though they match condition. "
|
||||
"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' {
|
||||
Skip-GroupPolicy -Name 'TEST | Drive Mapping'
|
||||
Skip-GroupPolicy -Name 'Default Domain Policy'
|
||||
Skip-GroupPolicy -Name 'Default Domain Controllers Policy' -DomaiName 'JustOneDomain'
|
||||
}
|
||||
}
|
||||
New-HTMLText -Text @(
|
||||
"Code above when executed will scan YourDomainYouHavePermissionsFor, find all empty, unlinked, disabled group policies, backup any GPO just before it's to be deleted to `$Env:UserProfile\Desktop\GPO. "
|
||||
"If it's not able to make a backup it will terminate. Additionally it will skip all 3 group policies that have been shown above. "
|
||||
"You can one or multiple group policies to be skipped. "
|
||||
"Now go ahead and find what's there"
|
||||
)
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove GPOs that are EMPTY or UNLINKED' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command when executed removes every ",
|
||||
"EMPTY"
|
||||
" or "
|
||||
"NOT LINKED"
|
||||
" Group Policy. Make sure when running it for the first time to run it with ",
|
||||
"WhatIf",
|
||||
" parameter as shown below to prevent accidental removal.",
|
||||
"Make sure to use BackupPath which will make sure that for each GPO that is about to be deleted a backup is made to folder on a desktop."
|
||||
"You can skip parameters related to backup if you did backup all GPOs prior to running remove command. "
|
||||
) -FontWeight normal, bold, normal, bold, normal, bold, normal, normal -Color Black, Red, Black, Red, Black
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"After execution please make sure there are no errors, make sure to review provided output, and confirm that what is about to be deleted matches expected data. "
|
||||
} -LineBreak
|
||||
New-HTMLText -Text "Once happy with results please follow with command (this will start fixing process): " -LineBreak -FontWeight bold
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed deletes only first X empty or unlinked GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur."
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly."
|
||||
"Please make sure to check if backup is made as well before going all in."
|
||||
}
|
||||
New-HTMLText -Text "If there's nothing else to be deleted on SYSVOL side, we can skip to next step step"
|
||||
}
|
||||
New-HTMLWizardStep -Name 'Remove GPOs that are DISABLED' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command when executed removes every ",
|
||||
"DISABLED"
|
||||
" Group Policy. Make sure when running it for the first time to run it with ",
|
||||
"WhatIf",
|
||||
" parameter as shown below to prevent accidental removal.",
|
||||
"Make sure to use BackupPath which will make sure that for each GPO that is about to be deleted a backup is made to folder on a desktop."
|
||||
"You can skip parameters related to backup if you did backup all GPOs prior to running remove command. "
|
||||
) -FontWeight normal, bold, normal, bold, normal, bold, normal, normal -Color Black, Red, Black, Red, Black
|
||||
New-HTMLText -TextBlock {
|
||||
""
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -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'
|
||||
}
|
||||
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
|
||||
}
|
||||
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'
|
||||
}
|
||||
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. "
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly. "
|
||||
"Please make sure to check if backup is made as well before going all in."
|
||||
}
|
||||
New-HTMLText -Text "If there's nothing else to be deleted, we can skip to next step step."
|
||||
}
|
||||
New-HTMLWizardStep -Name '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\GPOZaurrEmptyUnlinkedAfter.html -Verbose -Type GPOList
|
||||
}
|
||||
New-HTMLText -Text "If there are no more empty or unlinked GPOs in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOList']['Exclusions']) {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLSection -Name 'Group Policies Exclusions' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOList']['Exclusions'] -Filtering {
|
||||
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policies Exclusions Code' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLText -Text 'Please make sure to use following exclusions when executing removal' -FontSize 10pt
|
||||
New-HTMLCodeBlock -Code $Script:Reporting['GPOList']['ExclusionsCode']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOList']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLSection -Name 'Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOList']['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 - Empty & Unlinked Group Policies' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLText -Text 'Following steps will guide you how to remove empty or unlinked group policies'
|
||||
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 removal. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrEmptyUnlinked.html -Verbose -Type GPOList
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurr
|
||||
$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 'Remove GPOs that are EMPTY or UNLINKED' {
|
||||
New-HTMLText -Text @(
|
||||
"Following command when executed removes every ",
|
||||
"EMPTY"
|
||||
" or "
|
||||
"NOT LINKED"
|
||||
" Group Policy. Make sure when running it for the first time to run it with ",
|
||||
"WhatIf",
|
||||
" parameter as shown below to prevent accidental removal.",
|
||||
"Make sure to use BackupPath which will make sure that for each GPO that is about to be deleted a backup is made to folder on a desktop."
|
||||
) -FontWeight normal, bold, normal, bold, normal, bold, normal, normal -Color Black, Red, Black, Red, Black
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -Verbose -WhatIf
|
||||
}
|
||||
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: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -LimitProcessing 2 -Verbose
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed deletes only first empty or unlinked GPOs. Use LimitProcessing parameter to prevent mass delete and increase the counter when no errors occur."
|
||||
"Repeat step above as much as needed increasing LimitProcessing count till there's nothing left. In case of any issues please review and action accordingly."
|
||||
"Please make sure to check if backup is made as well before going all in."
|
||||
}
|
||||
New-HTMLText -Text "If there's nothing else to be deleted on SYSVOL side, we can skip to next step step"
|
||||
}
|
||||
New-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\GPOZaurrEmptyUnlinkedAfter.html -Verbose -Type GPOList
|
||||
}
|
||||
New-HTMLText -Text "If there are no more empty or unlinked GPOs in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
$GPOZaurrNetLogonOwners = [ordered] @{
|
||||
Name = 'NetLogon Owners'
|
||||
Enabled = $true
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrNetLogon -OwnerOnly -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
foreach ($File in $Script:Reporting['NetLogonOwners']['Data']) {
|
||||
# if ($File.FileSystemRights -eq 'Owner') {
|
||||
# Process Owner part of the report
|
||||
$Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwners']++
|
||||
if ($File.OwnerType -eq 'WellKnownAdministrative') {
|
||||
$Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersAdministrative']++
|
||||
} elseif ($File.OwnerType -eq 'Administrative') {
|
||||
$Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersAdministrative']++
|
||||
} else {
|
||||
$Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersNotAdministrative']++
|
||||
}
|
||||
if ($File.OwnerSid -eq 'S-1-5-32-544') {
|
||||
$Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersAdministrators']++
|
||||
} elseif ($File.OwnerType -in 'WellKnownAdministrative', 'Administrative') {
|
||||
$Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersAdministrativeNotAdministrators']++
|
||||
$Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersToFix']++
|
||||
} else {
|
||||
$Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersToFix']++
|
||||
}
|
||||
#$Script:Reporting['NetLogonPermissions']['Variables']['Owner'].Add($File)
|
||||
#} else {
|
||||
# Process all other part of the report
|
||||
# $Script:Reporting['NetLogonPermissions']['Variables']['NonOwner'].Add($File)
|
||||
|
||||
# if ($File.Status -eq 'Review permission required') {
|
||||
# $Script:Reporting['NetLogonPermissions']['Variables']['PermissionReviewRequired']++
|
||||
# } elseif ($File.Status -eq 'Removal permission required') {
|
||||
# $Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequired']++
|
||||
# } elseif ($File.Status -eq 'Not assesed') {
|
||||
# $Script:Reporting['NetLogonPermissions']['Variables']['PermissionNotAssesed']++
|
||||
# } else {
|
||||
# $Script:Reporting['NetLogonPermissions']['Variables']['PermissionOK']++
|
||||
# }
|
||||
# }
|
||||
}
|
||||
if ($Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersToFix'] -gt 0) {
|
||||
$Script:Reporting['NetLogonOwners']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['NetLogonOwners']['ActionRequired'] = $false
|
||||
}
|
||||
# if (-not $Script:Reporting['NetLogonPermissions']['ActionRequired']) {
|
||||
# # if owners require fixing, we don't need to check those as we get this anyways
|
||||
# # if owners don't require fixing we check permissions anyways
|
||||
# if ($Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequired'] -gt 0 -or $Script:Reporting['NetLogonPermissions']['Variables']['PermissionReviewRequired'] -gt 0) {
|
||||
# $Script:Reporting['NetLogonPermissions']['ActionRequired'] = $true
|
||||
# } else {
|
||||
# $Script:Reporting['NetLogonPermissions']['ActionRequired'] = $false
|
||||
# }
|
||||
# }
|
||||
}
|
||||
Variables = @{
|
||||
NetLogonOwners = 0
|
||||
NetLogonOwnersAdministrators = 0
|
||||
NetLogonOwnersNotAdministrative = 0
|
||||
NetLogonOwnersAdministrative = 0
|
||||
NetLogonOwnersAdministrativeNotAdministrators = 0
|
||||
NetLogonOwnersToFix = 0
|
||||
#Owner = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
#NonOwner = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
|
||||
# PermissionReviewRequired = 0
|
||||
# PermissionRemovalRequired = 0
|
||||
# PermissionOK = 0
|
||||
# PermissionNotAssesed = 0
|
||||
}
|
||||
Overview = {
|
||||
# New-HTMLPanel {
|
||||
# New-HTMLText -Text 'Following chart presents ', 'NetLogon Summary' -FontSize 10pt -FontWeight normal, bold
|
||||
# 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 -FontSize 10pt -Text 'Those problems must be resolved before doing other clenaup activities.'
|
||||
# New-HTMLChart {
|
||||
# New-ChartPie -Name 'Correct Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrators'] -Color LightGreen
|
||||
# New-ChartPie -Name 'Incorrect Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersToFix'] -Color Crimson
|
||||
# } -Title 'NetLogon Owners' -TitleAlignment center
|
||||
# }
|
||||
# New-HTMLPanel {
|
||||
|
||||
# }
|
||||
}
|
||||
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['NetLogonOwners']['Variables']['NetLogonOwners'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'NetLogon BUILTIN\Administrators as Owner: ', $Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersAdministrators'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "NetLogon Owners requiring change: ", $Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersToFix'] -FontWeight normal, bold {
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Not Administrative: ', $Script:Reporting['NetLogonOwners']['Variables']['NetLogonOwnersNotAdministrative'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Administrative, but not BUILTIN\Administrators: ', $Script:Reporting['NetLogonOwners']['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 {
|
||||
& $Script:GPOConfiguration['NetLogonOwners']['Summary']
|
||||
}
|
||||
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
|
||||
} -Title 'NetLogon Owners' -TitleAlignment center
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'NetLogon File Owners' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['NetLogonOwners']['Data'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'OwnerSid' -Value "S-1-5-32-544" -BackgroundColor LightGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'OwnerSid' -Value "S-1-5-32-544" -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
New-HTMLTableCondition -Name 'OwnerType' -Value "WellKnownAdministrative" -BackgroundColor LightGreen -ComparisonType string -Operator eq
|
||||
New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor LightGreen -ComparisonType string -Operator eq
|
||||
New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix NetLogon Owners ' {
|
||||
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 removal. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrNetLogonBefore.html -Verbose -Type NetLogonOwners
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$NetLogonOutput = Get-GPOZaurrNetLogon -OwnerOnly -Verbose
|
||||
$NetLogonOutput | 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 'Set non-compliant file owners to BUILTIN\Administrators' {
|
||||
New-HTMLText -Text "Following command when executed runs internally command that lists all file owners and if it doesn't match changes it BUILTIN\Administrators. It doesn't change compliant owners."
|
||||
New-HTMLText -Text "Make sure when running it for the first time to run it with ", "WhatIf", " parameter as shown below to prevent accidental removal." -FontWeight normal, bold, normal -Color Black, Red, Black
|
||||
|
||||
New-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrNetLogonOwner -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 {
|
||||
Repair-GPOZaurrNetLogonOwner -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 replacement of owners process): " -LineBreak -FontWeight bold
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed sets new owner only on first X non-compliant NetLogon files. 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-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrNetLogonOwner -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 {
|
||||
Repair-GPOZaurrNetLogonOwner -Verbose -LimitProcessing 2 -IncludeDomains 'YourDomainYouHavePermissionsFor'
|
||||
}
|
||||
}
|
||||
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\GPOZaurrNetLogonAfter.html -Verbose -Type NetLogonOwners
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['NetLogonOwners']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['NetLogonOwners']['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-HTMLTab -Name 'NetLogon Permissions' {
|
||||
# New-HTMLSection -Invisible {
|
||||
# New-HTMLPanel {
|
||||
# #& $Script:GPOConfiguration['NetLogonPermissions']['Summary']
|
||||
# }
|
||||
# New-HTMLPanel {
|
||||
# #New-HTMLChart {
|
||||
# # New-ChartPie -Name 'Correct Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrators'] -Color LightGreen
|
||||
# # New-ChartPie -Name 'Incorrect Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersToFix'] -Color Crimson
|
||||
# #} -Title 'NetLogon Owners' -TitleAlignment center
|
||||
# }
|
||||
# }
|
||||
# # New-HTMLSection -Name 'NetLogon Files List' {
|
||||
# # New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['Variables']['Owner'] -Filtering {
|
||||
# # New-HTMLTableCondition -Name 'PrincipalSid' -Value "S-1-5-32-544" -BackgroundColor LightGreen -ComparisonType string
|
||||
# # New-HTMLTableCondition -Name 'PrincipalSid' -Value "S-1-5-32-544" -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
# # New-HTMLTableCondition -Name 'PrincipalType' -Value "WellKnownAdministrative" -BackgroundColor LightGreen -ComparisonType string -Operator eq
|
||||
# # }
|
||||
# # }
|
||||
# New-HTMLSection -Name 'NetLogon Files List' {
|
||||
# New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['Variables']['NonOwner'] -Filtering {
|
||||
# New-HTMLTableCondition -Name 'PrincipalType' -Value "Unknown" -BackgroundColor Salmon -ComparisonType string -Operator eq -Row
|
||||
# New-HTMLTableCondition -Name 'PrincipalType' -Value "WellKnownAdministrative" -BackgroundColor LightGreen -ComparisonType string -Operator eq -Row
|
||||
# New-HTMLTableCondition -Name 'Status' -Value "Review permission required" -BackgroundColor PaleGoldenrod -ComparisonType string -Operator eq -Row
|
||||
# New-HTMLTableCondition -Name 'Status' -Value "Removal permission required" -BackgroundColor Salmon -ComparisonType string -Operator eq -Row
|
||||
# New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor LightGreen -ComparisonType string -Operator eq
|
||||
# }
|
||||
# }
|
||||
# if ($Script:Reporting['NetLogonPermissions']['WarningsAndErrors']) {
|
||||
# New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
# New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['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,123 +4,245 @@
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrNetLogon
|
||||
Get-GPOZaurrNetLogon -SkipOwner -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionWriteReviewPerDomain'] = @{}
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionFullControlReviewPerDomain'] = @{}
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionModifyReviewPerDomain'] = @{}
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequiredPerDomain'] = @{}
|
||||
|
||||
foreach ($File in $Script:Reporting['NetLogonPermissions']['Data']) {
|
||||
if ($File.FileSystemRights -eq 'Owner') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwners']++
|
||||
if ($File.PrincipalType -eq 'WellKnownAdministrative') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrative']++
|
||||
} elseif ($File.PrincipalType -eq 'Administrative') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrative']++
|
||||
if (-not $Script:Reporting['NetLogonPermissions']['Variables']['PermissionWriteReviewPerDomain'][$File.DomainName]) {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionWriteReviewPerDomain'][$File.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['NetLogonPermissions']['Variables']['PermissionFullControlReviewPerDomain'][$File.DomainName]) {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionFullControlReviewPerDomain'][$File.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['NetLogonPermissions']['Variables']['PermissionModifyReviewPerDomain'][$File.DomainName]) {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionModifyReviewPerDomain'][$File.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequiredPerDomain'][$File.DomainName]) {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequiredPerDomain'][$File.DomainName] = 0
|
||||
}
|
||||
|
||||
if ($File.Status -eq 'Review permission required') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionReviewRequired']++
|
||||
if ($File.FileSystemRights -like '*Modify*') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionModifyReview']++
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionModifyReviewPerDomain'][$File.DomainName]++
|
||||
} elseif ($File.FileSystemRights -like '*Write*') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionWriteReview']++
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionWriteReviewPerDomain'][$File.DomainName]++
|
||||
} elseif ($File.FileSystemRights -like '*FullControl*') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionFullControlReview']++
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionFullControlReviewPerDomain'][$File.DomainName]++
|
||||
} else {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersNotAdministrative']++
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionOtherReview']++
|
||||
}
|
||||
if ($File.PrincipalSid -eq 'S-1-5-32-544') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrators']++
|
||||
} elseif ($File.PrincipalType -in 'WellKnownAdministrative', 'Administrative') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrativeNotAdministrators']++
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersToFix']++
|
||||
} elseif ($File.Status -eq 'Removal permission required') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequired']++
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequiredPerDomain'][$File.DomainName]++
|
||||
if ($File.PrincipalObjectClass -in 'user', 'computer') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequiredBecauseObject']++
|
||||
} else {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersToFix']++
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequiredBecauseUnknown']++
|
||||
}
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['Owner'].Add($File)
|
||||
} elseif ($File.Status -eq 'Not assesed') {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionNotAssesed']++
|
||||
} else {
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['NonOwner'].Add($File)
|
||||
$Script:Reporting['NetLogonPermissions']['Variables']['PermissionOK']++
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersToFix'].Count -gt 0) {
|
||||
if ($Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequired'] -gt 0 -or $Script:Reporting['NetLogonPermissions']['Variables']['PermissionReviewRequired'] -gt 0) {
|
||||
$Script:Reporting['NetLogonPermissions']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['NetLogonPermissions']['ActionRequired'] = $false
|
||||
}
|
||||
}
|
||||
Variables = @{
|
||||
NetLogonOwners = 0
|
||||
NetLogonOwnersAdministrators = 0
|
||||
NetLogonOwnersNotAdministrative = 0
|
||||
NetLogonOwnersAdministrative = 0
|
||||
NetLogonOwnersAdministrativeNotAdministrators = 0
|
||||
NetLogonOwnersToFix = 0
|
||||
Owner = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
NonOwner = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
PermissionReviewRequired = 0
|
||||
PermissionRemovalRequired = 0
|
||||
PermissionOK = 0
|
||||
PermissionNotAssesed = 0
|
||||
|
||||
PermissionWriteReview = 0
|
||||
PermissionFullControlReview = 0
|
||||
PermissionModifyReview = 0
|
||||
PermissionOtherReview = 0
|
||||
PermissionRemovalRequiredBecauseObject = 0
|
||||
PermissionRemovalRequiredBecauseUnknown = 0
|
||||
|
||||
|
||||
PermissionWriteReviewPerDomain = $null
|
||||
PermissionFullControlReviewPerDomain = $null
|
||||
PermissionModifyReviewPerDomain = $null
|
||||
PermissionRemovalRequiredPerDomain = $null
|
||||
}
|
||||
Overview = {
|
||||
New-HTMLPanel {
|
||||
New-HTMLText -Text 'Following chart presents ', 'NetLogon Summary' -FontSize 10pt -FontWeight normal, bold
|
||||
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 -FontSize 10pt -Text 'Those problems must be resolved before doing other clenaup activities.'
|
||||
New-HTMLChart {
|
||||
New-ChartPie -Name 'Correct Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrators'] -Color LightGreen
|
||||
New-ChartPie -Name 'Incorrect Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersToFix'] -Color Crimson
|
||||
} -Title 'NetLogon Owners' -TitleAlignment center
|
||||
}
|
||||
New-HTMLPanel {
|
||||
|
||||
}
|
||||
}
|
||||
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. "
|
||||
"Each file stored on NETLOGON has it's own permissions. "
|
||||
"It's important that crucial permissions such as FullControl, Modify or Write permissions are only applied to proper, trusted groups of users. "
|
||||
"Additionally permissions for FullControl, Modify or Write should not be granted to direct users or computers. Only groups are allowed! "
|
||||
""
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text 'Assesment overall: ' -FontSize 10pt -FontWeight bold
|
||||
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-HTMLListItem -Text 'Permissions that look ok: ' {
|
||||
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
|
||||
New-HTMLListItem -Text 'Assesed and as expected ', $Script:Reporting['NetLogonPermissions']['Variables']['PermissionOK'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Not assesed, but not critical (read/execute only) ', $Script:Reporting['NetLogonPermissions']['Variables']['PermissionNotAssesed'] -FontWeight normal, bold
|
||||
}
|
||||
}
|
||||
New-HTMLListItem -Text 'Permissions requiring review:' {
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Full control permissions ', $Script:Reporting['NetLogonPermissions']['Variables']['PermissionFullControlReview'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Modify permissions ', $Script:Reporting['NetLogonPermissions']['Variables']['PermissionModifyReview'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Write permissions ', $Script:Reporting['NetLogonPermissions']['Variables']['PermissionWriteReview'] -FontWeight normal, bold
|
||||
}
|
||||
}
|
||||
New-HTMLListItem -Text 'Permissions requiring removal: ', $Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequired'] -FontWeight normal, bold {
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Because of object type (user/computer) ', $Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequiredBecauseObject'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text 'Because of unknown permissions ', $Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequiredBecauseUnknown'] -FontWeight normal, bold
|
||||
}
|
||||
}
|
||||
} -FontSize 10pt -LineBreak
|
||||
New-HTMLText -Text 'Assesment split per domain (will require permissions to fix): ' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
foreach ($Domain in $Script:Reporting['NetLogonPermissions']['Variables']['PermissionWriteReviewPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain requires review of ", $Script:Reporting['NetLogonPermissions']['Variables']['PermissionFullControlReviewPerDomain'][$Domain], " full control" -FontWeight normal, bold, normal
|
||||
New-HTMLListItem -Text "$Domain requires review of ", $Script:Reporting['NetLogonPermissions']['Variables']['PermissionModifyReviewPerDomain'][$Domain], " modify permission" -FontWeight normal, bold, normal
|
||||
New-HTMLListItem -Text "$Domain requires review of ", $Script:Reporting['NetLogonPermissions']['Variables']['PermissionWriteReviewPerDomain'][$Domain], " write permission" -FontWeight normal, bold, normal
|
||||
New-HTMLListItem -Text "$Domain requires removal of ", $Script:Reporting['NetLogonPermissions']['Variables']['PermissionRemovalRequiredPerDomain'][$Domain], " permissions" -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text "Follow the steps below table to get NetLogon Owners into compliant state." -FontSize 10pt
|
||||
New-HTMLText -Text "Please review output in table and follow the steps below table to get NetLogon permissions in order." -FontSize 10pt
|
||||
}
|
||||
Solution = {
|
||||
New-HTMLTab -Name 'NetLogon Owners' {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLPanel {
|
||||
& $Script:GPOConfiguration['NetLogonPermissions']['Summary']
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartPie -Name 'Correct Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrators'] -Color LightGreen
|
||||
New-ChartPie -Name 'Incorrect Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersToFix'] -Color Crimson
|
||||
} -Title 'NetLogon Owners' -TitleAlignment center
|
||||
}
|
||||
# New-HTMLTab -Name 'NetLogon Owners' {
|
||||
# New-HTMLSection -Invisible {
|
||||
# New-HTMLPanel {
|
||||
# & $Script:GPOConfiguration['NetLogonPermissions']['Summary']
|
||||
# }
|
||||
# New-HTMLPanel {
|
||||
# New-HTMLChart {
|
||||
# New-ChartPie -Name 'Correct Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersAdministrators'] -Color LightGreen
|
||||
# New-ChartPie -Name 'Incorrect Owners' -Value $Script:Reporting['NetLogonPermissions']['Variables']['NetLogonOwnersToFix'] -Color Crimson
|
||||
# } -Title 'NetLogon Owners' -TitleAlignment center
|
||||
# }
|
||||
# }
|
||||
# New-HTMLSection -Name 'NetLogon File Owners' {
|
||||
# New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['Variables']['Owner'] -Filtering {
|
||||
# New-HTMLTableCondition -Name 'PrincipalSid' -Value "S-1-5-32-544" -BackgroundColor LightGreen -ComparisonType string
|
||||
# New-HTMLTableCondition -Name 'PrincipalSid' -Value "S-1-5-32-544" -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
# New-HTMLTableCondition -Name 'PrincipalType' -Value "WellKnownAdministrative" -BackgroundColor LightGreen -ComparisonType string -Operator eq
|
||||
# New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor LightGreen -ComparisonType string -Operator eq
|
||||
# New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
# }
|
||||
# }
|
||||
# New-HTMLSection -Name 'Steps to fix NetLogon Owners ' {
|
||||
# New-HTMLContainer {
|
||||
# New-HTMLSpanStyle -FontSize 10pt {
|
||||
# New-HTMLText -Text 'Following steps will guide you how to fix NetLogon Owners and make them compliant.'
|
||||
# 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 removal. To generate new report please use:"
|
||||
# New-HTMLCodeBlock -Code {
|
||||
# Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrNetLogonBefore.html -Verbose -Type NetLogon
|
||||
# }
|
||||
# New-HTMLText -TextBlock {
|
||||
# "When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
# "Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
# }
|
||||
# New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
# New-HTMLCodeBlock -Code {
|
||||
# $NetLogonOutput = Get-GPOZaurrNetLogon -OwnerOnly -Verbose
|
||||
# $NetLogonOutput | 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 'Set non-compliant file owners to BUILTIN\Administrators' {
|
||||
# New-HTMLText -Text "Following command when executed runs internally command that lists all file owners and if it doesn't match changes it BUILTIN\Administrators. It doesn't change compliant owners."
|
||||
# New-HTMLText -Text "Make sure when running it for the first time to run it with ", "WhatIf", " parameter as shown below to prevent accidental removal." -FontWeight normal, bold, normal -Color Black, Red, Black
|
||||
|
||||
# New-HTMLCodeBlock -Code {
|
||||
# Repair-GPOZaurrNetLogonOwner -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: "
|
||||
# }
|
||||
# New-HTMLCodeBlock -Code {
|
||||
# Repair-GPOZaurrNetLogonOwner -Verbose -LimitProcessing 2
|
||||
# }
|
||||
# New-HTMLText -TextBlock {
|
||||
# "This command when executed sets new owner only on first X non-compliant NetLogon files. 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\GPOZaurrNetLogonAfter.html -Verbose -Type NetLogon
|
||||
# }
|
||||
# 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
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# if ($Script:Reporting['NetLogonPermissions']['WarningsAndErrors']) {
|
||||
# New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
# New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['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-HTMLTab -Name 'NetLogon Permissions' {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLPanel {
|
||||
& $Script:GPOConfiguration['NetLogonPermissions']['Summary']
|
||||
}
|
||||
New-HTMLSection -Name 'NetLogon Files List' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['Variables']['Owner'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'PrincipalSid' -Value "S-1-5-32-544" -BackgroundColor LightGreen -ComparisonType string
|
||||
New-HTMLTableCondition -Name 'PrincipalSid' -Value "S-1-5-32-544" -BackgroundColor Salmon -ComparisonType string -Operator ne
|
||||
New-HTMLTableCondition -Name 'PrincipalType' -Value "WellKnownAdministrative" -BackgroundColor LightGreen -ComparisonType string -Operator eq
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartPie -Name 'Full Control requiring review' -Value $Script:Reporting['NetLogonPermissions']['Variables']['PermissionFullControlReview'] -Color Crimson
|
||||
New-ChartPie -Name 'Modify requiring review' -Value $Script:Reporting['NetLogonPermissions']['Variables']['PermissionModifyReview'] -Color Plum
|
||||
New-ChartPie -Name 'Write requiring review' -Value $Script:Reporting['NetLogonPermissions']['Variables']['PermissionWriteReview'] -Color LightCoral
|
||||
New-ChartPie -Name 'Permissions OK' -Value $Script:Reporting['NetLogonPermissions']['Variables']['PermissionOK'] -Color LightGreen
|
||||
New-ChartPie -Name 'Permissions ReadOnly/Execute' -Value $Script:Reporting['NetLogonPermissions']['Variables']['PermissionNotAssesed'] -Color Aqua
|
||||
} -Title 'NetLogon Permissions' -TitleAlignment center
|
||||
}
|
||||
if ($Script:Reporting['NetLogonPermissions']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['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 'NetLogon Files List' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['Data'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'PrincipalType' -Value "Unknown" -BackgroundColor Salmon -ComparisonType string -Operator eq -Row
|
||||
New-HTMLTableCondition -Name 'PrincipalType' -Value "WellKnownAdministrative" -BackgroundColor LightGreen -ComparisonType string -Operator eq -Row
|
||||
New-HTMLTableCondition -Name 'Status' -Value "Review permission required" -BackgroundColor PaleGoldenrod -ComparisonType string -Operator eq
|
||||
New-HTMLTableCondition -Name 'Status' -Value "Removal permission required" -BackgroundColor Salmon -ComparisonType string -Operator eq -Row
|
||||
New-HTMLTableCondition -Name 'Status' -Value "OK" -BackgroundColor LightGreen -ComparisonType string -Operator eq
|
||||
}
|
||||
New-HTMLSection -Name 'Steps to fix NetLogon Owners ' {
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix NetLogon Permissions ' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLText -Text 'Following steps will guide you how to fix NetLogon Owners and make them compliant.'
|
||||
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."
|
||||
@@ -133,43 +255,31 @@
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding with removal. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrNetLogonBefore.html -Verbose -Type NetLogon
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrNetLogonBefore.html -Verbose -Type NetLogonPermissions
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment. "
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step. "
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$NetLogonOutput = Get-GPOZaurrNetLogon -Verbose
|
||||
$NetLogonOutput = Get-GPOZaurrNetLogon -SkipOwner -Verbose
|
||||
$NetLogonOutput | 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 'Set non-compliant file owners to BUILTIN\Administrators' {
|
||||
New-HTMLText -Text "Following command when executed runs internally command that lists all file owners and if it doesn't match changes it BUILTIN\Administrators. It doesn't change compliant owners."
|
||||
New-HTMLText -Text "Make sure when running it for the first time to run it with ", "WhatIf", " parameter as shown below to prevent accidental removal." -FontWeight normal, bold, normal -Color Black, Red, Black
|
||||
|
||||
New-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrNetLogonOwner -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: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Repair-GPOZaurrNetLogonOwner -Verbose -LimitProcessing 2
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"This command when executed sets new owner only on first X non-compliant NetLogon files. 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 permissions manually for non-compliant users/groups' {
|
||||
New-HTMLText -Text @(
|
||||
"In case of NETLOGON permissions it's impossible to tell what in a given moment for given domain should be automatically removed except for the very obvious ",
|
||||
"unknown ", 'permissions. Domain Admins have to make their assesment on and remove permissions from users or groups that '
|
||||
) -FontWeight normal, bold, normal
|
||||
}
|
||||
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\GPOZaurrNetLogonAfter.html -Verbose -Type NetLogon
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrNetLogonAfter.html -Verbose -Type NetLogonPermissions
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
@@ -178,9 +288,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
New-HTMLTab -Name 'NetLogon Permissions' {
|
||||
New-HTMLSection -Name 'NetLogon Files List' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['Variables']['NonOwner'] -Filtering
|
||||
if ($Script:Reporting['NetLogonPermissions']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['NetLogonPermissions']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+132
-114
@@ -4,7 +4,7 @@
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrBroken
|
||||
Get-GPOZaurrBroken -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
$Script:Reporting['GPOOrphans']['Variables']['ToBeDeletedPerDomain'] = @{}
|
||||
@@ -29,7 +29,7 @@
|
||||
$Script:Reporting['GPOOrphans']['Variables']['NotAvailablePermissionIssuePerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOOrphans']['Variables']['ToBeDeleted'].Count -gt 0) {
|
||||
if ($Script:Reporting['GPOOrphans']['Variables']['ToBeDeleted'] -gt 0) {
|
||||
$Script:Reporting['GPOOrphans']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOOrphans']['ActionRequired'] = $false
|
||||
@@ -117,125 +117,143 @@
|
||||
New-HTMLTableCondition -Name 'Status' -Value "Permissions issue" -BackgroundColor MediumVioletRed -ComparisonType string -Color White
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
New-HTMLSection -Name 'Steps to fix - Not available on SYSVOL / Active Directory' {
|
||||
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 removal. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoBefore.html -Verbose -Type GPOOrphans
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix - Not available on SYSVOL / Active Directory' {
|
||||
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-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
New-HTMLWizardStep -Name 'Prepare report' {
|
||||
New-HTMLText -Text "Depending when this report was run you may want to prepare new report before proceeding with removal. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoBefore.html -Verbose -Type GPOOrphans
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-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-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$GPOOutput = Get-GPOZaurrBroken -Verbose
|
||||
$GPOOutput | Format-Table
|
||||
New-HTMLWizardStep -Name 'Make a backup (optional)' {
|
||||
New-HTMLText -TextBlock {
|
||||
"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 {
|
||||
$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-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 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-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 SYSVOL -LimitProcessing 2 -BackupPath $Env:UserProfile\Desktop\GPOSYSVOLBackup -Verbose
|
||||
New-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrBroken -Type SYSVOL -LimitProcessing 2 -BackupPath $Env:UserProfile\Desktop\GPOSYSVOLBackup -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 -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. "
|
||||
"If there's nothing else to be deleted on SYSVOL side, we can skip to next step step. "
|
||||
}
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"Alternatively for multi-domain scenario, if you have limited Domain Admin credentials to a single domain please use following command: "
|
||||
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-HTMLCodeBlock -Code {
|
||||
Remove-GPOZaurrBroken -Type SYSVOL -LimitProcessing 2 -BackupPath $Env:UserProfile\Desktop\GPOSYSVOLBackup -IncludeDomains 'YourDomainYouHavePermissionsFor' -Verbose
|
||||
New-HTMLWizardStep -Name 'Verification report' {
|
||||
New-HTMLText -TextBlock {
|
||||
"Once cleanup task was executed properly, we need to verify that report now shows no problems."
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoAfter.html -Verbose -Type GPOOrphans
|
||||
}
|
||||
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
|
||||
}
|
||||
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 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-HTMLWizardStep -Name 'Verification report' {
|
||||
New-HTMLText -TextBlock {
|
||||
"Once cleanup task was executed properly, we need to verify that report now shows no problems."
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrBrokenGpoAfter.html -Verbose -Type GPOOrphans
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,22 @@
|
||||
Enabled = $true
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Execute = { Get-GPOZaurrOwner -IncludeSysvol }
|
||||
Execute = {
|
||||
Get-GPOZaurrOwner -IncludeSysvol -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
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,28 +31,33 @@
|
||||
}
|
||||
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']++
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOOwners']['Variables']['WillFix'].Count -gt 0) {
|
||||
if ($Script:Reporting['GPOOwners']['Variables']['WillFix'] -gt 0) {
|
||||
$Script:Reporting['GPOOwners']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOOwners']['ActionRequired'] = $false
|
||||
}
|
||||
}
|
||||
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 +74,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 +96,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 {
|
||||
@@ -104,72 +135,99 @@
|
||||
New-HTMLTableCondition -Name 'IsOwnerAdministrative' -Value $false -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix Group Policy Owners' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
#New-HTMLText -Text 'Following steps will guide you how to fix group policy owners'
|
||||
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 Owners. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOOwnersBefore.html -Verbose -Type GPOOwners
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$OwnersGPO = Get-GPOZaurrOwner -IncludeSysvol -Verbose
|
||||
$OwnersGPO | 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 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 {
|
||||
"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. "
|
||||
}
|
||||
}
|
||||
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\GPOZaurrGPOOwnersAfter.html -Verbose -Type GPOOwners
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOOwners']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOOwners']['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 Group Policy Owners' {
|
||||
New-HTMLContainer {
|
||||
New-HTMLSpanStyle -FontSize 10pt {
|
||||
New-HTMLText -Text 'Following steps will guide you how to fix group policy owners'
|
||||
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 Owners. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOOwnersBefore.html -Verbose -Type GPOOwners
|
||||
}
|
||||
New-HTMLText -TextBlock {
|
||||
"When executed it will take a while to generate all data and provide you with new report depending on size of environment."
|
||||
"Once confirmed that data is still showing issues and requires fixing please proceed with next step."
|
||||
}
|
||||
New-HTMLText -Text "Alternatively if you prefer working with console you can run: "
|
||||
New-HTMLCodeBlock -Code {
|
||||
$OwnersGPO = Get-GPOZaurrOwner -IncludeSysvol -Verbose
|
||||
$OwnersGPO | 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 '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: "
|
||||
}
|
||||
New-HTMLCodeBlock -Code {
|
||||
Set-GPOZaurrOwner -Type All -Verbose -LimitProcessing 2
|
||||
}
|
||||
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."
|
||||
}
|
||||
}
|
||||
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\GPOZaurrGPOOwnersAfter.html -Verbose -Type GPOOwners
|
||||
}
|
||||
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
|
||||
}
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Action = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrPassword
|
||||
Get-GPOZaurrPassword -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Action = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrPermission -Type All -IncludePermissionType GpoEditDeleteModifySecurity, GpoEdit, GpoCustom #-IncludeOwner
|
||||
Get-GPOZaurrPermission -Type All -IncludePermissionType GpoEditDeleteModifySecurity, GpoEdit, GpoCustom -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
$GPOZaurrPermissionsAdministrative = [ordered] @{
|
||||
Name = 'Group Policy Administrative Permissions'
|
||||
Enabled = $true
|
||||
Action = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
$Object = [ordered] @{
|
||||
Permissions = Get-GPOZaurrPermission -Type Administrative -IncludePermissionType GpoEditDeleteModifySecurity -ReturnSecurityWhenNoData -IncludeGPOObject -ReturnSingleObject -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
$Object['PermissionsPerRow'] = $Object['Permissions'] | ForEach-Object { $_ }
|
||||
$Object
|
||||
}
|
||||
Processing = {
|
||||
# Create Per Domain Variables
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFixPerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillNotTouchPerDomain'] = @{}
|
||||
|
||||
foreach ($GPO in $Script:Reporting['GPOPermissionsAdministrative']['Data'].Permissions) {
|
||||
# Create Per Domain Variables
|
||||
if (-not $Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFixPerDomain'][$GPO[0].DomainName]) {
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFixPerDomain'][$GPO[0].DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillNotTouchPerDomain'][$GPO[0].DomainName]) {
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillNotTouchPerDomain'][$GPO[0].DomainName] = 0
|
||||
}
|
||||
# Checks
|
||||
|
||||
$Analysis = Get-PermissionsAnalysis -GPOPermissions $GPO -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -Type Administrative -PermissionType GpoEditDeleteModifySecurity
|
||||
if ($Analysis.Skip) {
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillNotTouch']++
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillNotTouchPerDomain'][$GPO[0].DomainName]++
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFix']++
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFixPerDomain'][$GPO[0].DomainName]++
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFix'] -gt 0) {
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissionsAdministrative']['ActionRequired'] = $false
|
||||
}
|
||||
}
|
||||
Variables = @{
|
||||
WillFix = 0
|
||||
WillNotTouch = 0
|
||||
WillFixPerDomain = $null
|
||||
WillNotTouchPerDomain = $null
|
||||
}
|
||||
Overview = {
|
||||
|
||||
}
|
||||
Summary = {
|
||||
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. "
|
||||
} -LineBreak
|
||||
New-HTMLText -FontSize 10pt -Text "Assesment results: " -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies requiring adding Domain Admins or Enterprise Admins: ', $Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFix'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which don't require changes: ", $Script:Reporting['GPOPermissionsAdministrative']['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['GPOPermissionsAdministrative']['Variables']['WillFixPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOPermissionsAdministrative']['Variables']['WillFixPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text @(
|
||||
"That means we need to fix permissions on: "
|
||||
$($Script:Reporting['GPOPermissionsAdministrative']['Variables'].WillFix)
|
||||
" out of "
|
||||
$($Script:Reporting['GPOPermissionsAdministrative']['Data'].Permissions).Count
|
||||
" Group Policies. "
|
||||
) -FontSize 10pt -FontWeight bold, bold, normal, bold, normal -Color Black, FreeSpeechRed, Black, Black -LineBreak -TextDecoration none, underline, underline, underline, none
|
||||
}
|
||||
Solution = {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLPanel {
|
||||
& $Script:GPOConfiguration['GPOPermissionsAdministrative']['Summary']
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Name 'Yes', 'No' -Color LightGreen, 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-HTMLTable -DataTable $Script:Reporting['GPOPermissionsAdministrative']['Data'].PermissionsPerRow -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 {
|
||||
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\GPOZaurrGPOPermissionsAdministrativeBefore.html -Verbose -Type GPOPermissionsAdministrative
|
||||
}
|
||||
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 {
|
||||
$AdministrativeUsers = Get-GPOZaurrPermission -Type Administrative -IncludePermissionType GpoEditDeleteModifySecurity -ReturnSecurityWhenNoData
|
||||
$AdministrativeUsers | 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 Administrative Groups proper permissions GPO' {
|
||||
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 '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\GPOZaurrGPOPermissionsAdministrativeAfter.html -Verbose -Type GPOPermissionsAdministrative
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOPermissionsAdministrative']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsAdministrative']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
$GPOZaurrPermissionsRead = [ordered] @{
|
||||
Name = 'Group Policy Authenticated Users Permissions'
|
||||
Enabled = $true
|
||||
Action = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
[ordered] @{
|
||||
Permissions = Get-GPOZaurrPermission -Type AuthenticatedUsers -ReturnSecurityWhenNoData -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
Issues = Get-GPOZaurrPermissionIssue
|
||||
}
|
||||
}
|
||||
Processing = {
|
||||
# This is a workaround - we need to use it since we have 0 permissions
|
||||
|
||||
# Create Per Domain Variables
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['WillFixPerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['WillNotTouchPerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['ReadPerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotReadPerDomain'] = @{}
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['TotalPerDomain'] = @{}
|
||||
|
||||
foreach ($GPO in $Script:Reporting['GPOPermissionsRead']['Data'].Issues) {
|
||||
# Create Per Domain Variables
|
||||
if (-not $Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotReadPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotReadPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissionsRead']['Variables']['ReadPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['ReadPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissionsRead']['Variables']['TotalPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['TotalPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if ($GPO.PermissionIssue) {
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotRead']++
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotReadPerDomain'][$GPO.DomainName]++
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['Read']++
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['ReadPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['TotalPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
foreach ($GPO in $Script:Reporting['GPOPermissionsRead']['Data'].Permissions) {
|
||||
# Create Per Domain Variables
|
||||
if (-not $Script:Reporting['GPOPermissionsRead']['Variables']['WillFixPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['WillFixPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
if (-not $Script:Reporting['GPOPermissionsRead']['Variables']['WillNotTouchPerDomain'][$GPO.DomainName]) {
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['WillNotTouchPerDomain'][$GPO.DomainName] = 0
|
||||
}
|
||||
# Checks
|
||||
if ($GPO.Permission -in 'GpoApply', 'GpoRead') {
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['WillNotTouch']++
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['WillNotTouchPerDomain'][$GPO.DomainName]++
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['WillFix']++
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['WillFixPerDomain'][$GPO.DomainName]++
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOPermissionsRead']['Variables']['WillFix'] -gt 0 -or $Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotRead'] -gt 0) {
|
||||
$Script:Reporting['GPOPermissionsRead']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissionsRead']['ActionRequired'] = $false
|
||||
}
|
||||
# Summary from 2 reports
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['TotalToFix'] = $Script:Reporting['GPOPermissionsRead']['Variables']['WillFix'] + $Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotRead']
|
||||
}
|
||||
Variables = @{
|
||||
WillFix = 0
|
||||
WillNotTouch = 0
|
||||
WillFixPerDomain = $null
|
||||
WillNotTouchPerDomain = $null
|
||||
CouldNotRead = 0
|
||||
CouldNotReadPerDomain = $null
|
||||
Read = 0
|
||||
ReadPerDomain = $null
|
||||
TotalToFix = 0
|
||||
TotalPerDomain = $null
|
||||
}
|
||||
Overview = {
|
||||
|
||||
}
|
||||
Summary = {
|
||||
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. "
|
||||
} -LineBreak
|
||||
New-HTMLText -Text "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: " -FontSize 10pt
|
||||
New-HTMLText -TextBlock {
|
||||
"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. "
|
||||
"Before MS16-072 is installed, user group policies were retrieved by using the user’s security context. "
|
||||
"After MS16-072 is installed, user group policies are retrieved by using the computer's security context."
|
||||
} -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()),
|
||||
" 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. "
|
||||
) -FontWeight normal, bold, normal
|
||||
New-HTMLText -FontSize 10pt -Text "First assesment results: " -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies requiring Authenticated Users with GpoRead permission: ', $Script:Reporting['GPOPermissionsRead']['Variables']['WillFix'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies which don't require changes: ", $Script:Reporting['GPOPermissionsRead']['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['GPOPermissionsRead']['Variables']['WillFixPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOPermissionsRead']['Variables']['WillFixPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -FontSize 10pt -Text "Secondary assesment results: " -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text "Group Policies couldn't read at all: ", $Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotRead'] -FontWeight normal, bold
|
||||
New-HTMLListItem -Text "Group Policies with permissions allowing read: ", $Script:Reporting['GPOPermissionsRead']['Variables']['Read'] -FontWeight normal, bold
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text 'With split per domain (permissions required):' -FontSize 10pt -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
foreach ($Domain in $Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotReadPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text @(
|
||||
"$Domain requires ",
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['CouldNotReadPerDomain'][$Domain],
|
||||
" changes out of ",
|
||||
$Script:Reporting['GPOPermissionsRead']['Variables']['TotalPerDomain'][$Domain],
|
||||
"."
|
||||
) -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text @(
|
||||
"That means we need to fix permissions on: "
|
||||
$($Script:Reporting['GPOPermissionsRead']['Variables']['TotalToFix'])
|
||||
" out of "
|
||||
$($Script:Reporting['GPOPermissionsRead']['Data'].Issues).Count
|
||||
" Group Policies. "
|
||||
) -FontSize 10pt -FontWeight bold, bold, normal, bold, normal -Color Black, FreeSpeechRed, Black, Black -LineBreak -TextDecoration none, underline, underline, underline, none
|
||||
}
|
||||
Solution = {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLPanel {
|
||||
& $Script:GPOConfiguration['GPOPermissionsRead']['Summary']
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Name 'Yes', 'No' -Color LightGreen, 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
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policy Authenticated Users Analysis' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsRead']['Data'].Permissions -Filtering {
|
||||
New-HTMLTableCondition -Name 'Permission' -Value '' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 7, 15, 30, 45, 60
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policy Issues Assesment' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsRead']['Data'].Issues -Filtering {
|
||||
New-HTMLTableCondition -Name 'PermissionIssue' -Value $true -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 7, 15, 30, 45, 60 -DefaultSortColumn PermissionIssue -DefaultSortOrder Descending
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix Group Policy Authenticated 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\GPOZaurrGPOPermissionsReadBefore.html -Verbose -Type GPOPermissionsRead
|
||||
}
|
||||
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 {
|
||||
$AuthenticatedUsers = Get-GPOZaurrPermission -Type AuthenticatedUsers -ReturnSecurityWhenNoData
|
||||
$AuthenticatedUsers | 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 ability to read all GPO' {
|
||||
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 '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\GPOZaurrGPOPermissionsReadAfter.html -Verbose -Type GPOPermissionsRead
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOPermissionsRead']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsRead']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
Action = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrPermissionRoot -SkipNames
|
||||
Get-GPOZaurrPermissionRoot -SkipNames -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
$GPOZaurrPermissionsUnknown = [ordered] @{
|
||||
Name = 'Group Policy Unknown Permissions'
|
||||
Enabled = $true
|
||||
Action = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrPermission -Type Unknown -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
# Create Per Domain Variables
|
||||
$Script:Reporting['GPOPermissionsUnknown']['Variables']['WillFixPerDomain'] = @{}
|
||||
foreach ($GPO in $Script:Reporting['GPOPermissionsUnknown']['Data']) {
|
||||
# Create Per Domain Variables
|
||||
if (-not $Script:Reporting['GPOPermissionsUnknown']['Variables']['WillFixPerDomain'][$GPO[0].DomainName]) {
|
||||
$Script:Reporting['GPOPermissionsUnknown']['Variables']['WillFixPerDomain'][$GPO[0].DomainName] = 0
|
||||
}
|
||||
# Checks
|
||||
$Script:Reporting['GPOPermissionsUnknown']['Variables']['WillFix']++
|
||||
$Script:Reporting['GPOPermissionsUnknown']['Variables']['WillFixPerDomain'][$GPO[0].DomainName]++
|
||||
}
|
||||
if ($Script:Reporting['GPOPermissionsUnknown']['Variables']['WillFix'] -gt 0) {
|
||||
$Script:Reporting['GPOPermissionsUnknown']['ActionRequired'] = $true
|
||||
} else {
|
||||
$Script:Reporting['GPOPermissionsUnknown']['ActionRequired'] = $false
|
||||
}
|
||||
}
|
||||
Variables = @{
|
||||
WillFix = 0
|
||||
WillFixPerDomain = $null
|
||||
}
|
||||
Overview = {
|
||||
|
||||
}
|
||||
Summary = {
|
||||
New-HTMLText -FontSize 10pt -TextBlock {
|
||||
"Group Policies contain multiple permissions for different level of access. "
|
||||
"Be it adminstrative permissions, read permissions or apply permissions. "
|
||||
"Over time some users or groups get deleted for different reasons and such permission in Group Policies leave a trace in form of Unknown SID. "
|
||||
"Unknown SIDs can also be remains of Active Directory Trusts, that have been deleted or are otherwise unavailable. "
|
||||
"Following assesment detects all unknown permissions and provides them for review & deletion. "
|
||||
} -LineBreak
|
||||
New-HTMLText -FontSize 10pt -Text "Assesment results: " -FontWeight bold
|
||||
New-HTMLList -Type Unordered {
|
||||
New-HTMLListItem -Text 'Group Policies requiring removal of unknown SIDs: ', $Script:Reporting['GPOPermissionsUnknown']['Variables']['WillFix'] -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['GPOPermissionsUnknown']['Variables']['WillFixPerDomain'].Keys) {
|
||||
New-HTMLListItem -Text "$Domain requires ", $Script:Reporting['GPOPermissionsUnknown']['Variables']['WillFixPerDomain'][$Domain], " changes." -FontWeight normal, bold, normal
|
||||
}
|
||||
} -FontSize 10pt
|
||||
New-HTMLText -Text @(
|
||||
"That means we need to remove "
|
||||
$($Script:Reporting['GPOPermissionsUnknown']['Variables'].WillFix)
|
||||
" unknown permissions from Group Policies. "
|
||||
) -FontSize 10pt -FontWeight normal, bold, normal -Color Black, FreeSpeechRed, Black -LineBreak -TextDecoration none, underline, none
|
||||
}
|
||||
Solution = {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLPanel {
|
||||
& $Script:GPOConfiguration['GPOPermissionsUnknown']['Summary']
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart {
|
||||
New-ChartBarOptions -Type barStacked
|
||||
New-ChartLegend -Name 'Yes' -Color Salmon
|
||||
New-ChartBar -Name 'Unknown Permissions Present' -Value $Script:Reporting['GPOPermissionsUnknown']['Variables']['WillFix']
|
||||
} -Title 'Group Policy Permissions' -TitleAlignment center
|
||||
}
|
||||
}
|
||||
New-HTMLSection -Name 'Group Policy Unknown Permissions Analysis' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsUnknown']['Data'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Permission' -Value '' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 7, 15, 30, 45, 60
|
||||
}
|
||||
if ($Script:Reporting['Settings']['HideSteps'] -eq $false) {
|
||||
New-HTMLSection -Name 'Steps to fix Group Policy Unknown Permissions' {
|
||||
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 removing unknown permissions. To generate new report please use:"
|
||||
New-HTMLCodeBlock -Code {
|
||||
Invoke-GPOZaurr -FilePath $Env:UserProfile\Desktop\GPOZaurrGPOPermissionsUnknownBefore.html -Verbose -Type GPOPermissionsUnknown
|
||||
}
|
||||
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. "
|
||||
"The table only shows GPO and their unknown permissions. "
|
||||
"It doesn't show permissions that are not subject of this investigation. "
|
||||
"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 {
|
||||
$UnknownPermissions = Get-GPOZaurrPermission -Type Unknown
|
||||
$UnknownPermissions | 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 removes 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 '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\GPOZaurrGPOPermissionsUnknownAfter.html -Verbose -Type GPOPermissionsUnknown
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Script:Reporting['GPOPermissionsUnknown']['WarningsAndErrors']) {
|
||||
New-HTMLSection -Name 'Warnings & Errors to Review' {
|
||||
New-HTMLTable -DataTable $Script:Reporting['GPOPermissionsUnknown']['WarningsAndErrors'] -Filtering {
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
|
||||
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
|
||||
} -PagingOptions 10, 20, 30, 40, 50
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
Action = $null
|
||||
Data = $null
|
||||
Execute = {
|
||||
Get-GPOZaurrLegacyFiles
|
||||
Get-GPOZaurrLegacyFiles -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
|
||||
}
|
||||
Processing = {
|
||||
|
||||
|
||||
@@ -6,6 +6,11 @@ function New-GPOZaurrReportHTML {
|
||||
[switch] $Offline,
|
||||
[switch] $Open
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$PSDefaultParameterValues = @{
|
||||
"New-HTMLTable:WarningAction" = 'SilentlyContinue'
|
||||
}
|
||||
@@ -17,14 +22,47 @@ function New-GPOZaurrReportHTML {
|
||||
#$LoggingMode = $($Support.ResultantSetPolicy.LoggingMode)
|
||||
New-HTML -TitleText "Group Policy Report - $ComputerName" {
|
||||
#New-HTMLTabOptions -SlimTabs -Transition -LinearGradient -SelectorColor Akaroa
|
||||
New-HTMLTableOption -DataStore JavaScript -BoolAsString
|
||||
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
|
||||
New-HTMLTable -DataTable $Support.ResultantSetPolicy -HideFooter -Transpose
|
||||
|
||||
New-HTMLSection {
|
||||
New-HTMLSection {
|
||||
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-HTMLContainer {
|
||||
New-HTMLSection {
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.CPU -Filtering
|
||||
}
|
||||
New-HTMLSection {
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.RAM -Filtering
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
New-HTMLSection {
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.OperatingSystem -Filtering
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.System -Filtering
|
||||
}
|
||||
New-HTMLSection {
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.Disk -Filtering
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.DiskLogical -Filtering
|
||||
}
|
||||
New-HTMLSection {
|
||||
New-HTMLTable -DataTable $Support.ComputerInformation.Services -Filtering
|
||||
}
|
||||
New-HTMLSection {
|
||||
|
||||
}
|
||||
}
|
||||
foreach ($Key in $Support.Keys) {
|
||||
if ($Key -eq 'ResultantSetPolicy') {
|
||||
if ($Key -in 'ResultantSetPolicy', 'ComputerInformation') {
|
||||
continue
|
||||
}
|
||||
New-HTMLTab -Name $Key {
|
||||
@@ -32,7 +70,7 @@ function New-GPOZaurrReportHTML {
|
||||
New-HTMLSection -Invisible {
|
||||
New-HTMLSection -HeaderText 'Summary' {
|
||||
New-HTMLTable -DataTable $Support.$Key.Summary -Filtering -PagingOptions @(7, 14 )
|
||||
New-HTMLTable -DataTable $Support.$Key.SummaryDetails -Filtering -PagingOptions @(7, 14)
|
||||
New-HTMLTable -DataTable $Support.$Key.SummaryDetails -Filtering -PagingOptions @(7, 14) -Transpose
|
||||
}
|
||||
New-HTMLSection -HeaderText 'Part of Security Groups' {
|
||||
New-HTMLTable -DataTable $Support.$Key.SecurityGroups -Filtering -PagingOptions @(7, 14)
|
||||
@@ -55,11 +93,34 @@ function New-GPOZaurrReportHTML {
|
||||
}
|
||||
#>
|
||||
New-HTMLSection -HeaderText 'ExtensionStatus' {
|
||||
New-HTMLTable -DataTable $Support.$Key.ExtensionStatus -Filtering
|
||||
New-HTMLPanel {
|
||||
New-HTMLTable -DataTable $Support.$Key.ExtensionStatus -Filtering
|
||||
}
|
||||
New-HTMLPanel {
|
||||
New-HTMLChart -Title 'Extension TimeLine' -TitleAlignment center {
|
||||
foreach ($Extension in $Support.$Key.ExtensionStatus) {
|
||||
New-ChartTimeLine -DateFrom ([DateTime] $Extension.BeginTime) -DateTo ([DateTime] $Extension.EndTime) -Name $Extension.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
New-HTMLSection -HeaderText 'Group Policies' {
|
||||
New-HTMLTable -DataTable $Support.$Key.GroupPolicies -Filtering
|
||||
New-HTMLTable -DataTable $Support.$Key.GroupPolicies -Filtering {
|
||||
# Global color applied
|
||||
New-TableCondition -Name 'Status' -Value 'Applied' -BackgroundColor BrightGreen -Row
|
||||
New-TableCondition -Name 'Status' -Value 'Denied' -BackgroundColor Salmon -Row
|
||||
|
||||
# One by one colors
|
||||
New-TableCondition -Name 'IsValid' -Value $true -BackgroundColor BrightGreen
|
||||
New-TableCondition -Name 'IsValid' -Value $false -BackgroundColor Salmon
|
||||
|
||||
New-TableCondition -Name 'FilterAllowed' -Value $true -BackgroundColor BrightGreen
|
||||
New-TableCondition -Name 'FilterAllowed' -Value $false -BackgroundColor Salmon
|
||||
|
||||
New-TableCondition -Name 'AccessAllowed' -Value $true -BackgroundColor BrightGreen
|
||||
New-TableCondition -Name 'AccessAllowed' -Value $false -BackgroundColor Salmon
|
||||
}
|
||||
}
|
||||
New-HTMLSection -HeaderText 'Group Policies Links' {
|
||||
New-HTMLTable -DataTable $Support.$Key.GroupPoliciesLinks -Filtering
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
$Script:GPOConfiguration = [ordered] @{
|
||||
GPOOrphans = $GPOZaurrOrphans
|
||||
GPOOwners = $GPOZaurrOwners
|
||||
GPOConsistency = $GPOZaurrConsistency
|
||||
GPODuplicates = $GPOZaurrDuplicates
|
||||
GPOList = $GPOZaurrList
|
||||
GPOPassword = $GPOZaurrPassword
|
||||
GPOPermissions = $GPOZaurrPermissions
|
||||
GPOPermissionsRoot = $GPOZaurrPermissionsRoot
|
||||
GPOFiles = $GPOZaurrFiles
|
||||
GPOBlockedInheritance = $GPOZaurrBlockedInheritance
|
||||
GPOAnalysis = $GPOZaurrAnalysis
|
||||
NetLogonPermissions = $GPOZaurrNetLogonPermissions
|
||||
SysVolLegacyFiles = $GPOZaurrSysVolLegacyFiles
|
||||
GPOOrphans = $GPOZaurrOrphans
|
||||
GPOOwners = $GPOZaurrOwners
|
||||
GPOConsistency = $GPOZaurrConsistency
|
||||
GPODuplicates = $GPOZaurrDuplicates
|
||||
GPOList = $GPOZaurrList
|
||||
GPOPassword = $GPOZaurrPassword
|
||||
GPOPermissions = $GPOZaurrPermissions
|
||||
GPOPermissionsAdministrative = $GPOZaurrPermissionsAdministrative
|
||||
GPOPermissionsRead = $GPOZaurrPermissionsRead
|
||||
GPOPermissionsRoot = $GPOZaurrPermissionsRoot
|
||||
GPOPermissionsUnknown = $GPOZaurrPermissionsUnknown
|
||||
GPOFiles = $GPOZaurrFiles
|
||||
GPOBlockedInheritance = $GPOZaurrBlockedInheritance
|
||||
GPOAnalysis = $GPOZaurrAnalysis
|
||||
NetLogonOwners = $GPOZaurrNetLogonOwners
|
||||
NetLogonPermissions = $GPOZaurrNetLogonPermissions
|
||||
SysVolLegacyFiles = $GPOZaurrSysVolLegacyFiles
|
||||
}
|
||||
@@ -96,7 +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"
|
||||
Write-Verbose "Get-GPOZaurrBroken - Processing SYSVOL differences"
|
||||
foreach ($_ in $Differences.Keys) {
|
||||
if ($Differences[$_] -in 'Not available in AD', 'Permissions issue') {
|
||||
$FullPath = $SysvolHash[$_].FullName
|
||||
|
||||
+176
-151
@@ -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,
|
||||
@@ -25,7 +23,7 @@
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation,
|
||||
[System.Collections.IDictionary] $ADAdministrativeGroups,
|
||||
[int] $LimitProcessing
|
||||
[int] $LimitProcessing = [int32]::MaxValue
|
||||
)
|
||||
$ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -Extended
|
||||
if (-not $ADAdministrativeGroups) {
|
||||
@@ -55,159 +53,186 @@
|
||||
}
|
||||
$Splat['ExcludeDomains'] = $ExcludeDomains
|
||||
$Splat['ExtendedForestInformation'] = $ExtendedForestInformation
|
||||
#$Splat['ExcludePermissionType'] = $ExcludePermissionType
|
||||
$Splat['IncludePermissionType'] = $PermissionType
|
||||
$Splat['SkipWellKnown'] = $SkipWellKnown.IsPresent
|
||||
$Splat['SkipAdministrative'] = $SkipAdministrative.IsPresent
|
||||
|
||||
$AdministrativeExists = @{
|
||||
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 {
|
||||
$GPOPermissions = $_
|
||||
$PermissionsAnalysis = Get-PermissionsAnalysis -GPOPermissions $GPOPermissions -ADAdministrativeGroups $ADAdministrativeGroups -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -Type $Type -PermissionType $PermissionType
|
||||
<#
|
||||
# Prepare data to clean
|
||||
$Skip = $false
|
||||
$AdministrativeExists = @{
|
||||
DomainAdmins = $false
|
||||
EnterpriseAdmins = $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 $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!"
|
||||
} 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 ($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++
|
||||
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 ($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++
|
||||
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)
|
||||
}
|
||||
+22
-4
@@ -1,6 +1,7 @@
|
||||
function Get-GPOZaurr {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[scriptblock] $ExcludeGroupPolicies,
|
||||
[string] $GPOName,
|
||||
[alias('GUID', 'GPOID')][string] $GPOGuid,
|
||||
|
||||
@@ -24,6 +25,23 @@
|
||||
if (-not $GPOPath) {
|
||||
$ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
||||
}
|
||||
$ExcludeGPO = [ordered] @{}
|
||||
if ($ExcludeGroupPolicies) {
|
||||
$ExExecution = Invoke-Command -ScriptBlock $ExcludeGroupPolicies
|
||||
foreach ($GroupPolicy in $ExExecution) {
|
||||
if ($GroupPolicy -is [string]) {
|
||||
$ExcludeGPO[$GroupPolicy] = $true
|
||||
} elseif ($GroupPolicy.Name -and $GroupPolicy.DomainName) {
|
||||
$PolicyName = -join ($GroupPolicy.DomainName, $GroupPolicy.Name)
|
||||
$ExcludeGPO[$PolicyName] = $true
|
||||
} elseif ($GroupPolicy.Name) {
|
||||
$ExcludeGPO[$GroupPolicy.Name] = $true
|
||||
} else {
|
||||
Write-Warning "Get-GPOZaurr - Exclusion takes only Group Policy Name as string, or as hashtable with domain name @{ Name = 'Group Policy Name'; DomainName = 'Domain' }."
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Process {
|
||||
if (-not $GPOPath) {
|
||||
@@ -43,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 -ReturnObject:$ReturnObject.IsPresent
|
||||
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups -ReturnObject:$ReturnObject.IsPresent -ExcludeGroupPolicies $ExcludeGPO
|
||||
} else {
|
||||
$_
|
||||
}
|
||||
@@ -61,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 -ReturnObject:$ReturnObject.IsPresent
|
||||
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups -ReturnObject:$ReturnObject.IsPresent -ExcludeGroupPolicies $ExcludeGPO
|
||||
} else {
|
||||
$_
|
||||
}
|
||||
@@ -79,7 +97,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 -ReturnObject:$ReturnObject.IsPresent
|
||||
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups -ReturnObject:$ReturnObject.IsPresent -ExcludeGroupPolicies $ExcludeGPO
|
||||
} else {
|
||||
$_
|
||||
}
|
||||
@@ -92,7 +110,7 @@
|
||||
Get-ChildItem -LiteralPath $Path -Recurse -Filter *.xml | ForEach-Object {
|
||||
$XMLContent = [XML]::new()
|
||||
$XMLContent.Load($_.FullName)
|
||||
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -PermissionsOnly:$PermissionsOnly.IsPresent
|
||||
Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -PermissionsOnly:$PermissionsOnly.IsPresent -ExcludeGroupPolicies $ExcludeGPO
|
||||
}
|
||||
Write-Verbose "Get-GPOZaurr - Finished GPO content from XML files"
|
||||
}
|
||||
|
||||
@@ -129,6 +129,9 @@
|
||||
} elseif ($_.Extension -eq '.adm') {
|
||||
$SuggestedAction = 'Consider deleting'
|
||||
$SuggestedActionComment = 'Most likely legacy ADM files'
|
||||
} elseif ($_.Name -eq 'Thumbs.db') {
|
||||
$SuggestedAction = 'Consider deleting'
|
||||
$SuggestedActionComment = 'Most likely database files to store image thumbnails on Windows systems.'
|
||||
}
|
||||
if (-not $SuggestedAction) {
|
||||
$FullPathAdmFiles = [System.IO.Path]::Combine($GPO.Path, 'Adm\admfiles.ini')
|
||||
@@ -217,6 +220,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-not $SuggestedAction) {
|
||||
if ($_.Name -eq 'Thumbs.db') {
|
||||
$SuggestedAction = 'Consider deleting'
|
||||
$SuggestedActionComment = 'Most likely database files to store image thumbnails on Windows systems.'
|
||||
}
|
||||
}
|
||||
if (-not $SuggestedAction) {
|
||||
foreach ($FullName in @('*backup*', '*Delete*', '*Obsoleet*', '*Obsolete*', '*Archive*')) {
|
||||
if ($_.FullName -like $FullName) {
|
||||
|
||||
@@ -13,62 +13,113 @@
|
||||
$FilesAll = foreach ($Domain in $ForestInformation.Domains) {
|
||||
$Path = -join ("\\", $Domain, '\Netlogon')
|
||||
$PathOnSysvol = -join ("\\", $Domain, "\SYSVOL\", $Domain, "\Scripts")
|
||||
$Files = Get-ChildItem -LiteralPath $Path -Recurse -Force -ErrorVariable Err -ErrorAction SilentlyContinue
|
||||
[Array] $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))"
|
||||
}
|
||||
$Count = 0
|
||||
foreach ($File in $Files) {
|
||||
$Count++
|
||||
Write-Verbose "GPOZaurrNetLogon - Processing [$($Domain)]($Count/$($Files.Count)) $($File.FullName)"
|
||||
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 {
|
||||
$IdentityOwner = [PSCustomObject] @{ SID = ''; Type = 'Uknown' }
|
||||
}
|
||||
#if ($ACL.Owner) {
|
||||
$IdentityOwner = Convert-Identity -Identity $ACL.Owner -Verbose:$false
|
||||
$IdentityOwnerAdvanced = Get-WinADObject -Identity $ACL.Owner -Cache -Verbose:$false
|
||||
#} else {
|
||||
# $IdentityOwner = [PSCustomObject] @{ SID = ''; Type = 'Unknown' }
|
||||
# $IdentityOwnerAdvanced = [PSCustomObject] @{ ObjectClass = '' }
|
||||
#}
|
||||
if (-not $OwnerOnly) {
|
||||
if (-not $SkipOwner) {
|
||||
if ($IdentityOwner.SID -eq "S-1-5-32-544") {
|
||||
$Status = 'OK'
|
||||
} else {
|
||||
$Status = 'Replace owner required'
|
||||
}
|
||||
[PSCustomObject] @{
|
||||
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 = $File.FullName.Replace($Path, $PathOnSysvol)
|
||||
#Owner = $ACL.Owner
|
||||
FullName = $File.FullName
|
||||
Status = $Status
|
||||
DomainName = $Domain
|
||||
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
|
||||
PrincipalObjectClass = $IdentityOwnerAdvanced.ObjectClass
|
||||
FileSystemRights = 'Owner' # : FullControl
|
||||
IsInherited = $false
|
||||
FullNameOnSysVol = $File.FullName.Replace($Path, $PathOnSysvol)
|
||||
}
|
||||
}
|
||||
$FilePermission = Get-FilePermissions -Path $_.FullName -ACLS $ACL -Verbose:$false
|
||||
$FilePermission = Get-FilePermissions -Path $File.FullName -ACLS $ACL -Verbose:$false
|
||||
foreach ($Perm in $FilePermission) {
|
||||
$Identity = Convert-Identity -Identity $Perm.Principal -Verbose:$false
|
||||
[PSCustomObject] @{
|
||||
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 = $File.FullName.Replace($Path, $PathOnSysvol)
|
||||
$AdvancedIdentity = Get-WinADObject -Identity $Perm.Principal -Cache -Verbose:$false
|
||||
$Status = 'Not assesed'
|
||||
if ($Perm.FileSystemRights -eq [System.Security.AccessControl.FileSystemRights]::FullControl) {
|
||||
if ($Identity.Type -eq 'WellKnownAdministrative') {
|
||||
$Status = 'OK'
|
||||
} else {
|
||||
if ($AdvancedIdentity.ObjectClass -in 'user', 'computer') {
|
||||
$Status = 'Removal permission required'
|
||||
} else {
|
||||
$Status = 'Review permission required'
|
||||
}
|
||||
}
|
||||
} elseif ($Perm.FileSystemRights -like "*Modify*") {
|
||||
if ($AdvancedIdentity.ObjectClass -in 'user', 'computer') {
|
||||
$Status = 'Removal permission required'
|
||||
} else {
|
||||
$Status = 'Review permission required'
|
||||
}
|
||||
} elseif ($Perm.FileSystemRights -like "*Write*") {
|
||||
if ($AdvancedIdentity.ObjectClass -in 'user', 'computer') {
|
||||
$Status = 'Removal permission required'
|
||||
} else {
|
||||
$Status = 'Review permission required'
|
||||
}
|
||||
}
|
||||
if ($Identity.Type -eq 'Unknown') {
|
||||
$Status = 'Removal permission required'
|
||||
}
|
||||
[PSCustomObject] @{
|
||||
FullName = $File.FullName
|
||||
Status = $Status
|
||||
DomainName = $Domain
|
||||
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
|
||||
PrincipalObjectClass = $AdvancedIdentity.ObjectClass
|
||||
FileSystemRights = $Perm.FileSystemRights # : FullControl
|
||||
IsInherited = $Perm.IsInherited # : True
|
||||
FullNameOnSysVol = $File.FullName.Replace($Path, $PathOnSysvol)
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if ($IdentityOwner.SID -eq "S-1-5-32-544") {
|
||||
$Status = 'OK'
|
||||
} else {
|
||||
$Status = 'Replace owner required'
|
||||
}
|
||||
[PSCustomObject] @{
|
||||
FullName = $File.FullName
|
||||
Status = $Status
|
||||
DomainName = $Domain
|
||||
Extension = $File.Extension
|
||||
CreationTime = $File.CreationTime
|
||||
LastAccessTime = $File.LastAccessTime
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
Doesn't display GPOs that have no SYSVOL content (orphaned GPOs)
|
||||
|
||||
.PARAMETER Forest
|
||||
Target different Forest
|
||||
Target different Forest, by default current forest is used
|
||||
|
||||
.PARAMETER ExcludeDomains
|
||||
Exclude domain from search, by default whole forest is scanned
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
Tries to find CPassword in Group Policies or given path and translate it to readable value
|
||||
|
||||
.PARAMETER Forest
|
||||
Specify forest name. By default current forest is used
|
||||
Target different Forest, by default current forest is used
|
||||
|
||||
.PARAMETER ExcludeDomains
|
||||
Exclude Domain or Domains
|
||||
Exclude domain from search, by default whole forest is scanned
|
||||
|
||||
.PARAMETER IncludeDomains
|
||||
Include only certain Domain or Domains
|
||||
Include only specific domains, by default whole forest is scanned
|
||||
|
||||
.PARAMETER ExtendedForestInformation
|
||||
Ability to provide extended forest information in advanced scenarios
|
||||
Ability to provide Forest Information from another command to speed up processing
|
||||
|
||||
.PARAMETER GPOPath
|
||||
Path where Group Policy content is located or where backup is located
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
function Get-GPOZaurrPermissionIssue {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Detects Group Policy missing Authenticated Users permission while not having higher permissions.
|
||||
|
||||
.DESCRIPTION
|
||||
Detects Group Policy missing Authenticated Users permission while not having higher permissions.
|
||||
|
||||
.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
|
||||
$Issues = Get-GPOZaurrPermissionIssue
|
||||
$Issues | Format-Table
|
||||
|
||||
.NOTES
|
||||
General notes
|
||||
#>
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
)
|
||||
$ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExcludeDomainControllers $ExcludeDomainControllers -IncludeDomainControllers $IncludeDomainControllers -SkipRODC:$SkipRODC -ExtendedForestInformation $ExtendedForestInformation -Extended
|
||||
foreach ($Domain in $ForestInformation.Domains) {
|
||||
$TimeLog = Start-TimeLog
|
||||
Write-Verbose "Get-GPOZaurrPermissionIssue - Starting process for $Domain"
|
||||
$QueryServer = $ForestInformation['QueryServers']["$Domain"].HostName[0]
|
||||
$SystemsContainer = $ForestInformation['DomainsExtended'][$Domain].SystemsContainer
|
||||
if ($SystemsContainer) {
|
||||
$PoliciesSearchBase = -join ("CN=Policies,", $SystemsContainer)
|
||||
$Properties = 'DisplayName', 'Name', 'DistinguishedName', 'ObjectClass', 'WhenCreated', 'WhenChanged'
|
||||
$PoliciesInAD = Get-ADObject -SearchBase $PoliciesSearchBase -SearchScope OneLevel -Filter * -Server $QueryServer -Properties $Properties
|
||||
foreach ($Policy in $PoliciesInAD) {
|
||||
$GUIDFromDN = ConvertFrom-DistinguishedName -DistinguishedName $Policy.DistinguishedName
|
||||
$GUIDFromDN = $GUIDFromDN -replace '{' -replace '}'
|
||||
$GUID = $Policy.Name -replace '{' -replace '}'
|
||||
[PSCustomObject] @{
|
||||
DisplayName = $Policy.DisplayName
|
||||
DomainName = $Domain
|
||||
PermissionIssue = -not ($GUID -and $GUIDFromDN)
|
||||
ObjectClass = $Policy.ObjectClass
|
||||
Name = $Policy.Name
|
||||
DistinguishedName = $Policy.DistinguishedName
|
||||
GUID = $GUIDFromDN
|
||||
WhenCreated = $Policy.WhenCreated
|
||||
WhenChanged = $Policy.WhenChanged
|
||||
}
|
||||
}
|
||||
}
|
||||
$TimeEnd = Stop-TimeLog -Time $TimeLog -Option OneLiner
|
||||
Write-Verbose "Get-GPOZaurrPermissionIssue - Finishing process for $Domain (Time to process: $TimeEnd)"
|
||||
}
|
||||
}
|
||||
+80
-18
@@ -2,15 +2,27 @@
|
||||
[alias('Show-GPOZaurr', 'Show-GPO')]
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[Parameter(Position = 1)][scriptblock] $ExcludeGroupPolicies,
|
||||
[string] $FilePath,
|
||||
[string[]] $Type,
|
||||
[Parameter(Position = 0)][string[]] $Type,
|
||||
[switch] $PassThru,
|
||||
[switch] $HideHTML
|
||||
[switch] $HideHTML,
|
||||
[switch] $HideSteps,
|
||||
[switch] $HideErrors,
|
||||
[switch] $HideWarnings,
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains
|
||||
)
|
||||
Reset-GPOZaurrStatus # This makes sure types are at it's proper status
|
||||
|
||||
$Script:Reporting = [ordered] @{}
|
||||
$Script:Reporting['Version'] = Get-GitHubVersion -Cmdlet 'Invoke-GPOZaurr' -RepositoryOwner 'evotecit' -RepositoryName 'GPOZaurr'
|
||||
$Script:Reporting['Settings'] = @{
|
||||
HideErrors = $HideErrors.IsPresent
|
||||
HideWarnings = $HideWarnings.IsPresent
|
||||
HideSteps = $HideSteps.IsPresent
|
||||
}
|
||||
Write-Color '[i]', "[GPOZaurr] ", 'Version', ' [Informative] ', $Script:Reporting['Version'] -Color Yellow, DarkGray, Yellow, DarkGray, Magenta
|
||||
|
||||
# Verify requested types are supported
|
||||
@@ -30,6 +42,33 @@
|
||||
Write-Color '[i]', "[GPOZaurr] ", 'Not supported types', ' [Informative] ', "Please use one/multiple from the list: ", ($Script:GPOConfiguration.Keys -join ', ') -Color Yellow, DarkGray, Yellow, DarkGray, Yellow, Magenta
|
||||
return
|
||||
}
|
||||
$DisplayForest = if ($Forest) { $Forest } else { 'Not defined. Using current one' }
|
||||
$DisplayIncludedDomains = if ($IncludeDomains) { $IncludeDomains -join "," } else { 'Not defined. Using all domains of forest' }
|
||||
$DisplayExcludedDomains = if ($ExcludeDomains) { $ExcludeDomains -join ',' } else { 'No exclusions provided' }
|
||||
Write-Color '[i]', "[GPOZaurr] ", 'Domain Information', ' [Informative] ', "Forest: ", $DisplayForest -Color Yellow, DarkGray, Yellow, DarkGray, Yellow, Magenta
|
||||
Write-Color '[i]', "[GPOZaurr] ", 'Domain Information', ' [Informative] ', "Included Domains: ", $DisplayIncludedDomains -Color Yellow, DarkGray, Yellow, DarkGray, Yellow, Magenta
|
||||
Write-Color '[i]', "[GPOZaurr] ", 'Domain Information', ' [Informative] ', "Excluded Domains: ", $DisplayExcludedDomains -Color Yellow, DarkGray, Yellow, DarkGray, Yellow, Magenta
|
||||
|
||||
# Exclusions support, converts ScriptBlock into list of GPOs
|
||||
<#
|
||||
$Exclusions = [ordered]@{}
|
||||
if ($Extension) {
|
||||
$Exclusions['All'] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
[Array] $ExecuteExtension = & $Extension
|
||||
foreach ($Ext in $ExecuteExtension) {
|
||||
if ($Ext.Type -eq 'Exclusion') {
|
||||
if ($Ext.Type) {
|
||||
if (-not $Exclusions[$Ext.Type]) {
|
||||
$Exclusions[$Ext.Type] = [System.Collections.Generic.List[PSCustomObject]]::new()
|
||||
}
|
||||
$Exclusions[$Ext.Type].Add($Ext)
|
||||
} else {
|
||||
$Exclusions['All'].Add($Ext)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#>
|
||||
|
||||
# Lets make sure we only enable those types which are requestd by user
|
||||
if ($Type) {
|
||||
@@ -49,36 +88,53 @@
|
||||
Name = $Script:GPOConfiguration[$T].Name
|
||||
ActionRequired = $null
|
||||
Data = $null
|
||||
Exclusions = $null
|
||||
WarningsAndErrors = $null
|
||||
Time = $null
|
||||
Summary = $null
|
||||
Variables = Copy-Dictionary -Dictionary $Script:GPOConfiguration[$T]['Variables']
|
||||
}
|
||||
if ($Exclusions) {
|
||||
$Script:Reporting[$T]['ExclusionsCode'] = $ExcludeGroupPolicies
|
||||
$Script:Reporting[$T]['Exclusions'] = & $ExcludeGroupPolicies
|
||||
}
|
||||
|
||||
$TimeLogGPOList = Start-TimeLog
|
||||
Write-Color -Text '[i]', '[Start] ', $($Script:GPOConfiguration[$T]['Name']) -Color Yellow, DarkGray, Yellow
|
||||
$Script:Reporting[$T]['Data'] = Invoke-Command -ScriptBlock $Script:GPOConfiguration[$T]['Execute'] -WarningVariable CommandWarnings -ErrorVariable CommandErrors
|
||||
$OutputCommand = Invoke-Command -ScriptBlock $Script:GPOConfiguration[$T]['Execute'] -WarningVariable CommandWarnings -ErrorVariable CommandErrors -ArgumentList $Forest, $ExcludeDomains, $IncludeDomains
|
||||
if ($OutputCommand -is [System.Collections.IDictionary]) {
|
||||
# in some cases the return will be wrapped in Hashtable/orderedDictionary and we need to handle this without an array
|
||||
$Script:Reporting[$T]['Data'] = $OutputCommand
|
||||
} else {
|
||||
# since sometimes it can be 0 or 1 objects being returned we force it being an array
|
||||
$Script:Reporting[$T]['Data'] = [Array] $OutputCommand
|
||||
}
|
||||
Invoke-Command -ScriptBlock $Script:GPOConfiguration[$T]['Processing']
|
||||
$Script:Reporting[$T]['WarningsAndErrors'] = @(
|
||||
foreach ($War in $CommandWarnings) {
|
||||
[PSCustomObject] @{
|
||||
Type = 'Warning'
|
||||
Comment = $War
|
||||
Reason = ''
|
||||
TargetName = ''
|
||||
if (-not $HideWarnings) {
|
||||
foreach ($War in $CommandWarnings) {
|
||||
[PSCustomObject] @{
|
||||
Type = 'Warning'
|
||||
Comment = $War
|
||||
Reason = ''
|
||||
TargetName = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($Err in $CommandErrors) {
|
||||
[PSCustomObject] @{
|
||||
Type = 'Error'
|
||||
Comment = $Err
|
||||
Reason = $Err.CategoryInfo.Reason
|
||||
TargetName = $Err.CategoryInfo.TargetName
|
||||
if (-not $HideErrors) {
|
||||
foreach ($Err in $CommandErrors) {
|
||||
[PSCustomObject] @{
|
||||
Type = 'Error'
|
||||
Comment = $Err
|
||||
Reason = $Err.CategoryInfo.Reason
|
||||
TargetName = $Err.CategoryInfo.TargetName
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
if ($Script:GPOConfiguration[$T]['Summary']) {
|
||||
$Script:Reporting[$T]['Summary'] = Invoke-Command -ScriptBlock $Script:GPOConfiguration[$T]['Summary']
|
||||
}
|
||||
#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
|
||||
@@ -108,12 +164,18 @@
|
||||
if ($Type.Count -eq 1) {
|
||||
foreach ($T in $Script:GPOConfiguration.Keys) {
|
||||
if ($Script:GPOConfiguration[$T].Enabled -eq $true) {
|
||||
if ($Script:GPOConfiguration[$T]['Summary']) {
|
||||
$Script:Reporting[$T]['Summary'] = Invoke-Command -ScriptBlock $Script:GPOConfiguration[$T]['Summary']
|
||||
}
|
||||
& $Script:GPOConfiguration[$T]['Solution']
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($T in $Script:GPOConfiguration.Keys) {
|
||||
if ($Script:GPOConfiguration[$T].Enabled -eq $true) {
|
||||
if ($Script:GPOConfiguration[$T]['Summary']) {
|
||||
$Script:Reporting[$T]['Summary'] = Invoke-Command -ScriptBlock $Script:GPOConfiguration[$T]['Summary']
|
||||
}
|
||||
New-HTMLTab -Name $Script:GPOConfiguration[$T]['Name'] {
|
||||
& $Script:GPOConfiguration[$T]['Solution']
|
||||
}
|
||||
|
||||
@@ -117,7 +117,8 @@
|
||||
$PolicyContent.Rsop
|
||||
} else {
|
||||
$Output = [ordered] @{
|
||||
ResultantSetPolicy = $ResultantSetPolicy
|
||||
ComputerInformation = Get-Computer -ComputerName $ComputerName
|
||||
ResultantSetPolicy = $ResultantSetPolicy
|
||||
}
|
||||
if ($PolicyContent.Rsop.ComputerResults) {
|
||||
$Output.ComputerResults = ConvertFrom-XMLRSOP -Content $PolicyContent.Rsop -ResultantSetPolicy $ResultantSetPolicy -ResultsType 'ComputerResults' -Splitter $Splitter
|
||||
|
||||
+38
-47
@@ -1,7 +1,8 @@
|
||||
function Remove-GPOZaurr {
|
||||
[cmdletBinding(SupportsShouldProcess)]
|
||||
param(
|
||||
[parameter(Mandatory)][validateset('Empty', 'Unlinked')][string[]] $Type,
|
||||
[Parameter(Position = 1)][scriptblock] $ExcludeGroupPolicies,
|
||||
[parameter(Position = 0, Mandatory)][validateset('Empty', 'Unlinked', 'Disabled')][string[]] $Type,
|
||||
[int] $LimitProcessing,
|
||||
[alias('ForestName')][string] $Forest,
|
||||
[string[]] $ExcludeDomains,
|
||||
@@ -27,60 +28,50 @@
|
||||
$Count = 0
|
||||
}
|
||||
Process {
|
||||
Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -GPOPath $GPOPath | ForEach-Object {
|
||||
Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -GPOPath $GPOPath -ExcludeGroupPolicies $ExcludeGroupPolicies | ForEach-Object {
|
||||
$DeleteRequired = $false
|
||||
|
||||
if ($Type -contains 'Empty') {
|
||||
if ($_.ComputerSettingsAvailable -eq $false -and $_.UserSettingsAvailable -eq $false) {
|
||||
if ($BackupRequired) {
|
||||
try {
|
||||
Write-Verbose "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)"
|
||||
$BackupInfo = Backup-GPO -Guid $_.Guid -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer
|
||||
$BackupInfo
|
||||
$BackupOK = $true
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)"
|
||||
$BackupOK = $false
|
||||
}
|
||||
}
|
||||
if (($BackupRequired -and $BackupOK) -or (-not $BackupRequired)) {
|
||||
try {
|
||||
Write-Verbose "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName)"
|
||||
Remove-GPO -Domain $_.DomainName -Guid $_.Guid -ErrorAction Stop #-Server $QueryServer
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
$Count++
|
||||
if ($LimitProcessing -eq $Count) {
|
||||
break
|
||||
}
|
||||
if ($_.Empty -eq $true) {
|
||||
$DeleteRequired = $true
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'Unlinked') {
|
||||
if ($_.Linked -eq $false) {
|
||||
if ($BackupRequired) {
|
||||
try {
|
||||
Write-Verbose "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)"
|
||||
$BackupInfo = Backup-GPO -Guid $_.Guid -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer
|
||||
$BackupInfo
|
||||
$BackupOK = $true
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)"
|
||||
$BackupOK = $false
|
||||
}
|
||||
$DeleteRequired = $true
|
||||
}
|
||||
}
|
||||
if ($Type -contains 'Disabled') {
|
||||
if ($_.Enabled -eq $false) {
|
||||
$DeleteRequired = $true
|
||||
}
|
||||
}
|
||||
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
|
||||
$BackupOK = $true
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)"
|
||||
$BackupOK = $false
|
||||
}
|
||||
if (($BackupRequired -and $BackupOK) -or (-not $BackupRequired)) {
|
||||
try {
|
||||
Write-Verbose "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName)"
|
||||
Remove-GPO -Domain $_.DomainName -Guid $_.Guid -ErrorAction Stop #-Server $QueryServer
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
$Count++
|
||||
if ($LimitProcessing -eq $Count) {
|
||||
break
|
||||
}
|
||||
if (($BackupRequired -and $BackupOK) -or (-not $BackupRequired)) {
|
||||
try {
|
||||
Write-Verbose "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName)"
|
||||
Remove-GPO -Domain $_.DomainName -Guid $_.Guid -ErrorAction Stop #-Server $QueryServer
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
$Count++
|
||||
if ($LimitProcessing -eq $Count) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,42 +33,44 @@
|
||||
}
|
||||
}
|
||||
} | Select-Object | Select-Object -First $LimitProcessing | ForEach-Object {
|
||||
if ($_.Status -eq 'Not available in AD') {
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Processing $($_.Path)"
|
||||
$GPO = $_
|
||||
if ($GPO.Status -eq 'Not available in AD') {
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Processing [AD] $($GPO.Path)"
|
||||
if ($BackupFinalPath) {
|
||||
Try {
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Backing up $($_.Path)"
|
||||
Copy-Item -LiteralPath $_.Path -Recurse -Destination $BackupFinalPath -ErrorAction Stop
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Backing up $($GPO.Path)"
|
||||
Copy-Item -LiteralPath $GPO.Path -Recurse -Destination $BackupFinalPath -ErrorAction Stop
|
||||
$BackupWorked = $true
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrBroken - Error backing up error: $($_.Exception.Message)"
|
||||
Write-Warning "Remove-GPOZaurrBroken - Error backing up $($GPO.Path) error: $($_.Exception.Message)"
|
||||
$BackupWorked = $false
|
||||
}
|
||||
}
|
||||
if ($BackupWorked -or $BackupFinalPath -eq '') {
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Deleting $($_.Path)"
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Deleting $($GPO.Path)"
|
||||
try {
|
||||
Remove-Item -Recurse -Force -LiteralPath $_.Path
|
||||
Remove-Item -Recurse -Force -LiteralPath $GPO.Path -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrBroken - Failed to remove file $($_.Path): $($_.Exception.Message)."
|
||||
Write-Warning "Remove-GPOZaurrBroken - Failed to remove file $($GPO.Path): $($_.Exception.Message)."
|
||||
}
|
||||
}
|
||||
} elseif ($_.Status -eq 'Not available on SYSVOL') {
|
||||
} elseif ($GPO.Status -eq 'Not available on SYSVOL') {
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Processing [SYSVOL] $($GPO.DistinguishedName)"
|
||||
try {
|
||||
$ExistingObject = Get-ADObject -Identity $_.DistinguishedName -Server $_.DomainName -ErrorAction Stop
|
||||
$ExistingObject = Get-ADObject -Identity $GPO.DistinguishedName -Server $GPO.DomainName -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrBroken - Error getting $($_.DistinguishedName) from AD error: $($_.Exception.Message)"
|
||||
Write-Warning "Remove-GPOZaurrBroken - Error getting $($GPO.DistinguishedName) from AD error: $($_.Exception.Message)"
|
||||
$ExistingObject = $null
|
||||
}
|
||||
if ($ExistingObject -and $ExistingObject.ObjectClass -eq 'groupPolicyContainer') {
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Removing DN: $($_.DistinguishedName) / ObjectClass: $($ExistingObject.ObjectClass)"
|
||||
Write-Verbose "Remove-GPOZaurrBroken - Removing DN: $($GPO.DistinguishedName) / ObjectClass: $($ExistingObject.ObjectClass)"
|
||||
try {
|
||||
Remove-ADObject -Server $_.DomainName -Identity $_.DistinguishedName -Recursive -Confirm:$false
|
||||
Remove-ADObject -Server $GPO.DomainName -Identity $GPO.DistinguishedName -Recursive -Confirm:$false -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrBroken - Failed to remove $($_.DistinguishedName) from AD error: $($_.Exception.Message)"
|
||||
Write-Warning "Remove-GPOZaurrBroken - Failed to remove $($GPO.DistinguishedName) from AD error: $($_.Exception.Message)"
|
||||
}
|
||||
} else {
|
||||
Write-Warning "Remove-GPOZaurrBroken - DistinguishedName $($_.DistinguishedName) not found or ObjectClass is not groupPolicyContainer ($($ExistingObject.ObjectClass))"
|
||||
Write-Warning "Remove-GPOZaurrBroken - DistinguishedName $($GPO.DistinguishedName) not found or ObjectClass is not groupPolicyContainer ($($ExistingObject.ObjectClass))"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
||||
[System.Collections.IDictionary] $ExtendedForestInformation
|
||||
)
|
||||
|
||||
$getGPOZaurrDuplicateObjectSplat = @{
|
||||
Forest = $Forest
|
||||
IncludeDomains = $IncludeDomains
|
||||
@@ -18,7 +17,7 @@
|
||||
$DuplicateGpoObjects = Get-GPOZaurrDuplicateObject @getGPOZaurrDuplicateObjectSplat
|
||||
foreach ($Duplicate in $DuplicateGpoObjects | Select-Object -First $LimitProcessing) {
|
||||
try {
|
||||
Remove-ADObject -Identity $Duplicate.ObjectGUID -Recursive -ErrorAction Stop -Server $Duplicate.DomainName
|
||||
Remove-ADObject -Identity $Duplicate.ObjectGUID -Recursive -ErrorAction Stop -Server $Duplicate.DomainName -Confirm:$false
|
||||
} catch {
|
||||
Write-Warning "Remove-GPOZaurrDuplicateObject - Deleting $($Duplicate.ConflictDN) / $($Duplicate.DomainName) via GUID: $($Duplicate.ObjectGUID) failed with error: $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -17,18 +17,18 @@
|
||||
$Principal = $Identity.Name
|
||||
|
||||
$getGPOZaurrNetLogonSplat = @{
|
||||
OwnerOnly = $true
|
||||
Forest = $Forest
|
||||
IncludeDomains = $IncludeDomains
|
||||
ExcludeDomains = $ExcludeDomains
|
||||
OwnerOnly = $true
|
||||
Forest = $Forest
|
||||
IncludeDomains = $IncludeDomains
|
||||
ExcludeDomains = $ExcludeDomains
|
||||
ExtendedForestInformation = $ExtendedForestInformation
|
||||
}
|
||||
|
||||
Get-GPOZaurrNetLogon @getGPOZaurrNetLogonSplat | Select-Object -First $LimitProcessing | Where-Object {
|
||||
Get-GPOZaurrNetLogon @getGPOZaurrNetLogonSplat -Verbose | Where-Object {
|
||||
if ($_.OwnerSid -ne 'S-1-5-32-544') {
|
||||
$_
|
||||
}
|
||||
} | ForEach-Object {
|
||||
} | Select-Object -First $LimitProcessing | ForEach-Object {
|
||||
if ($PSCmdlet.ShouldProcess($_.FullName, "Setting NetLogon Owner to $($Principal)")) {
|
||||
Set-FileOwner -JustPath -Path $_.FullName -Owner $Principal -Verbose:$true -WhatIf:$WhatIfPreference
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
GUID of GPO. By default all GPOs are targetted
|
||||
|
||||
.PARAMETER Forest
|
||||
Target different Forest
|
||||
Target different Forest, by default current forest is used
|
||||
|
||||
.PARAMETER ExcludeDomains
|
||||
Exclude domain from search, by default whole forest is scanned
|
||||
@@ -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 {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
function Skip-GroupPolicy {
|
||||
[cmdletBinding()]
|
||||
param(
|
||||
[ValidateSet('GPOList')][string] $Type,
|
||||
[string] $Name,
|
||||
[string] $DomaiName
|
||||
)
|
||||
if ($Type) {
|
||||
[PSCustomObject] @{
|
||||
Type = $Type
|
||||
Name = $Name
|
||||
DomainName = $DomaiName
|
||||
}
|
||||
} else {
|
||||
[PSCustomObject] @{
|
||||
Name = $Name
|
||||
DomainName = $DomaiName
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,84 @@ That's it. Whenever there's a new version, you run the command, and you can enjo
|
||||
|
||||
## Changelog
|
||||
|
||||
- 0.0.94
|
||||
- [x] Fix for too big int - [#4](https://github.com/EvotecIT/GPOZaurr/issues/4) - tnx neztach
|
||||
- [x] Improved `Invoke-GPOZaurr`
|
||||
- [x] Type `GPOList` - added ability for Exclusions
|
||||
- [x] All other types, small improvements
|
||||
- [x] Added HideSteps, HideErrors, HideWarnings
|
||||
- [x] Improved `Remove-GPOZaurr` - added Exclusions
|
||||
- 0.0.93 - 03.12.2020
|
||||
- [x] Improved `Invoke-GPOZaurr`
|
||||
- [x] Type `GPOList` reverted charts colors for entries to match colors
|
||||
- [ ] Added `Skip-GroupPolicy` to use within `Invoke-GPOZaurr`
|
||||
- [x] Improved `Invoke-GPOZaurr` with basic support for Exclusions
|
||||
- [x] Improved `Get-GPOZaurr` with basic support for Exclusions
|
||||
- [x] Improved `Remove-GPOZaurrPermission` error handling
|
||||
- 0.0.92 - 01.12.2020
|
||||
- [x] Improved `Invoke-GPOZaurrSupport`
|
||||
- [x] Improved `Invoke-GPOZaurr`
|
||||
- [x] Type `GPOList` improved with more data, more problems and clearer information
|
||||
- [x] Improved `Remove-GPOZaurr`
|
||||
- [x] Added ability do remove disabed GPO
|
||||
- [x] Improved `Get-GPOZaurr` detecting more issues, delivering more data
|
||||
- 0.0.91 - 24.11.2020
|
||||
- [x] Improves `Invoke-GPOZaurr` (WIP)
|
||||
- [x] Improve Type `GPOPermissionsUnknown`
|
||||
- 0.0.90 - 23.11.2020
|
||||
- [x] Improves `Invoke-GPOZaurr` (WIP)
|
||||
- [x] Improves Type `GPODuplicates`
|
||||
- [x] Fix for chart color to be RED
|
||||
- [x] Add Type `GPOPermissionsUnknown`
|
||||
- [x] Improves logic for Data with 0/1 element
|
||||
- [x] Improves `Remove-GPOZaurrDuplicateObject` - removed `Confirm` requirement
|
||||
- [x] Improves `Get-GPOZaurrNetLogon` with more verbose
|
||||
- [x] Improves `Repair-GPOZaurrNetLogonOwner` with more verbose and fix for `LimitProcessing`
|
||||
- 0.0.89 - 22.11.2020
|
||||
- [x] Small update `Add-GPOZaurrPermission`
|
||||
- [x] Improves `Invoke-GPOZaurr` (WIP)
|
||||
- [x] Added Type `GPOPermissionsAdministrative`
|
||||
- 0.0.88 - 18.11.2020
|
||||
- [x] Fix for `Add-GPOZaurrPermission`
|
||||
- 0.0.87 - 18.11.2020
|
||||
- [x] Improve error handling `Remove-GPOZaurrBroken`
|
||||
- 0.0.86 - 18.11.2020
|
||||
- [x] Improve error handling `Remove-GPOZaurrBroken`
|
||||
- 0.0.85 - 17.11.2020
|
||||
- [x] Improves `Invoke-GPOZaurr` (WIP)
|
||||
- [x] Split `NetLogonPermissions` into `NetLogonPermissions` and `NetLogonOwners`
|
||||
- [x] Improved type `NetLogonPermissions`
|
||||
- [x] Improved type `NetLogonOwners`
|
||||
- [x] Improves `Get-GPOZaurrFiles`
|
||||
- [x] Improves `Get-GPOZaurrNetLogon`
|
||||
- [x] Fix for `Get-GPOZaurrNetLogon`
|
||||
- 0.0.84 - 16.11.2020
|
||||
- [x] Improves `Invoke-GPOZaurr` (WIP)
|
||||
- [x] Type `NetLogonPermissions`
|
||||
- [x] Fix for `Get-GPOZaurrNetLogon`
|
||||
- 0.0.83 - 14.11.2020
|
||||
- [x] Improves `Invoke-GPOZaurr` (WIP)
|
||||
- [x] Fix for wrong ActionRequired count
|
||||
- 0.0.82 - 14.11.2020
|
||||
- [x] Added `Get-GPOZaurrPermissionIssue` to detect permission issue with no rights
|
||||
- [x] Improves `Invoke-GPOZaurr` (WIP)
|
||||
- [x] Type `GPOPermissionsRead` improved detection of problems with low permissions
|
||||
- 0.0.81 - 12.11.2020
|
||||
- [x] Fix for `Set-GPOZaurrOwner` in case of missing permissions to not throw errors
|
||||
- [x] Improves `Invoke-GPOZaurr` (WIP)
|
||||
- [x] Type `GPOPermissionsRead` added
|
||||
- 0.0.80 - 12.11.2020
|
||||
- [x] Improves `Invoke-GPOZaurr` (WIP)
|
||||
- [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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user