Compare commits

...

55 Commits

Author SHA1 Message Date
Przemyslaw Klys bd103a513b Bump version 2024-06-11 17:22:51 +02:00
Przemyslaw Klys 8268002ac0 Update changelog 2024-06-11 17:22:26 +02:00
Przemyslaw Klys 038e4036b9 Add null 2024-06-11 17:22:02 +02:00
Przemyslaw Klys 632f2b0c26 Fix for excluded domains #55 2024-06-11 17:21:34 +02:00
Przemyslaw Klys 84805cf134 Should fix partially #55 2024-06-11 14:49:49 +02:00
Przemyslaw Klys d7ebc89d54 Update changelog 2024-04-16 18:36:40 +02:00
Przemyslaw Klys 4288829415 Bump version #53 2024-04-16 18:35:53 +02:00
Przemyslaw Klys f3d426ba93 Fixes typos in report #53 2024-04-16 18:35:24 +02:00
Przemyslaw Klys fef37130bb Update version build 2024-04-16 18:28:01 +02:00
Przemyslaw Klys d62b8e47f7 Update changelog 2024-04-16 18:27:43 +02:00
Przemyslaw Klys 63f1ccd232 Bump versions 2024-04-16 18:26:35 +02:00
Przemyslaw Klys e61ef74920 Fixes forest issue #54 2024-04-16 18:26:28 +02:00
Przemyslaw Klys b63e333fd0 Update changelog 2024-02-07 14:15:43 +01:00
Przemyslaw Klys 9b0ab0c1c2 Bump version 2024-02-07 14:14:33 +01:00
Przemyslaw Klys ee3b25ee88 Force specific DC for search 2024-02-07 14:14:27 +01:00
Przemyslaw Klys 25c13b54aa Fix filters 2024-02-04 13:31:48 +01:00
Przemyslaw Klys 2b9faa4e61 Update changelog 2024-02-04 13:31:38 +01:00
Przemyslaw Klys 42f3053896 Enhance GPO Script to Consider GPF Files
Improved the PowerShell script to account for special '.gpf' files when evaluating whether a Group Policy Object (GPO) is empty. Previously, GPOs containing only these files were incorrectly marked as empty since they weren't visible in the XML output. This update ensures that GPOs with '.gpf' files are recognized as non-empty. Additionally, the script now includes the SYSVOL path and the count of files within each GPO in its summary output, aiding in thorough GPO analysis.

This enhancement resolves issues with incomplete policy reporting and assists administrators in scenarios where Citrix or other applications rely on .gpf files for storing their settings.

Refs: #49
2024-02-04 13:27:51 +01:00
Przemyslaw Klys edcba71e7f examples added 2024-02-04 11:34:29 +01:00
Przemyslaw Klys c8ee2cca56 Update changelog 2024-02-04 11:34:00 +01:00
Przemyslaw Klys 3b4617af83 Small fix typo 2024-02-04 11:33:22 +01:00
Przemyslaw Klys 6830b1e219 Bump dependencies 2024-02-04 11:11:36 +01:00
Przemyslaw Klys 28c55deaa7 Adds new report #42 2024-02-04 11:11:28 +01:00
Przemyslaw Klys c757c8281b Add ability to limit GPO analysis by GPOName/GPOGUID 2024-02-04 09:09:36 +01:00
Przemyslaw Klys e3e5582696 Updatre module builder configuration 2023-09-17 10:10:36 +02:00
Przemyslaw Klys 8e2f4f1552 Bump versions 2023-09-17 10:10:26 +02:00
Przemyslaw Klys 863c9fabc9 Update changelog 2023-09-17 07:32:08 +02:00
Przemyslaw Klys 972b51b472 Update changelog 2023-09-17 07:31:12 +02:00
Przemyslaw Klys 060fb95064 Update example 2023-09-17 07:30:17 +02:00
Przemyslaw Klys fdfc700c6f Update example 2023-09-17 07:30:03 +02:00
Przemyslaw Klys 81eaac3fd1 Small improvements to the report #48 2023-09-16 09:42:09 +02:00
Przemyslaw Klys cf9164766e Add example for new report #48 2023-09-16 09:41:56 +02:00
Przemyslaw Klys 4de2e2a57e Submit gitignore 2023-09-16 09:38:54 +02:00
Przemyslaw Klys 663e6058e6 Rewrite configuration 2023-09-16 09:38:30 +02:00
Przemyslaw Klys f681a5586e Update changelog 2023-09-16 09:38:22 +02:00
Przemyslaw Klys 4c022bfc16 Add redirected report #48 2023-09-16 09:38:15 +02:00
Przemyslaw Klys c03f158b77 Changed pipeline into standard foreach 2023-09-16 09:37:44 +02:00
Przemyslaw Klys 4824633787 Changed pipeline foreach into foreach for better/safer results 2023-09-16 09:34:20 +02:00
Przemyslaw Klys 8dc7e5b26d Bump versions 2023-09-16 09:34:00 +02:00
Przemyslaw Klys 68ed20f3e8 Update changelog 2023-09-16 08:48:32 +02:00
Przemyslaw Klys df2bacdba7 Remove bad char 2023-09-16 08:48:26 +02:00
Przemyslaw Klys f67ade6341 Use hashtable to create PSCustomObject for GPO details
- Simplify code by using a hashtable to create PSCustomObject for GPO details in "Get-GPOZaurrAD.ps1" script.
2023-09-16 08:42:31 +02:00
Przemyslaw Klys 5855ca2a7c Detect paths #48 2023-09-15 12:05:34 +02:00
Przemyslaw Klys b5d69c8a1f Bump versions 2023-05-26 13:25:46 +02:00
Przemyslaw Klys 32dc6ac661 add cert thumbprint 2023-05-26 13:25:39 +02:00
Przemyslaw Klys 300d6f63c5 Update changelog 2023-05-26 13:09:01 +02:00
Przemyslaw Klys 1f43816804 Improve Remove-GPOZaurr LimitProcessing 2023-05-26 13:08:51 +02:00
Przemyslaw Klys 5d50536f5a Update changelog 2023-04-27 22:16:32 +02:00
Przemyslaw Klys 4da232a1be Merge branch 'master' of https://github.com/EvotecIT/GPOZaurr 2023-04-27 21:54:54 +02:00
Przemyslaw Klys fb5fa00dce Fixes space #44 2023-04-27 21:54:33 +02:00
Przemysław Kłys 970080bfad Merge pull request #43 from Absoblogginlutely/patch-1
Typo fixed
2023-04-27 15:13:12 +02:00
Andy Helsby 845c2124bd Typo fixed
Oddly enough this message was displayed on an en-us windows 2022 server so fixed the typos
2023-04-21 11:37:39 -04:00
Przemyslaw Klys 14d33aa2a6 Bump versions and dependencies 2023-03-07 18:12:19 +01:00
Przemyslaw Klys d596fd31fc Update changelog 2023-03-07 18:12:08 +01:00
Przemyslaw Klys a5cf96398c Update module builder 2023-03-07 18:12:03 +01:00
26 changed files with 813 additions and 331 deletions
+8
View File
@@ -0,0 +1,8 @@
Ignore/*
.vs/*
.vscode/*
Releases/*
ReleasesUnpacked/*
*.log
*.html
Artefacts/*
+212 -273
View File
@@ -1,287 +1,226 @@
Clear-Host
$Configuration = @{
Information = @{
ModuleName = 'GPOZaurr'
DirectoryProjects = 'C:\Support\GitHub'
Import-Module "PSPublishModule" -Force
FunctionsToExport = 'Public'
AliasesToExport = 'Public'
Invoke-ModuleBuild -ModuleName 'GPOZaurr' {
# Usual defaults as per standard module
$Manifest = @{
# Version number of this module.
ModuleVersion = '1.1.X'
# Supported PSEditions
CompatiblePSEditions = @('Desktop')
# ID used to uniquely identify this module
GUID = 'f7d4c9e4-0298-4f51-ad77-e8e3febebbde'
# Author of this module
Author = 'Przemyslaw Klys'
# Company or vendor of this module
CompanyName = 'Evotec'
# Copyright statement for this module
Copyright = "(c) 2011 - $((Get-Date).Year) Przemyslaw Klys @ Evotec. All rights reserved."
# Description of the functionality provided by this module
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.'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '5.1'
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
Tags = @('Windows', 'ActiveDirectory', 'GPO', 'GroupPolicy')
#IconUri = 'https://evotec.xyz/wp-content/uploads/2019/02/PSPublishModule.png'
Manifest = @{
# Version number of this module.
ModuleVersion = '0.0.X'
# Supported PSEditions
CompatiblePSEditions = @('Desktop')
# ID used to uniquely identify this module
GUID = 'f7d4c9e4-0298-4f51-ad77-e8e3febebbde'
# Author of this module
Author = 'Przemyslaw Klys'
# Company or vendor of this module
CompanyName = 'Evotec'
# Copyright statement for this module
Copyright = "(c) 2011 - $((Get-Date).Year) Przemyslaw Klys @ Evotec. All rights reserved."
# Description of the functionality provided by this module
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.'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '5.1'
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
Tags = @('Windows', 'ActiveDirectory', 'GPO', 'GroupPolicy')
#IconUri = 'https://evotec.xyz/wp-content/uploads/2019/02/PSPublishModule.png'
ProjectUri = 'https://github.com/EvotecIT/GPOZaurr'
RequiredModules = @(
@{ ModuleName = 'PSSharedGoods'; ModuleVersion = 'Latest'; Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe' }
@{ ModuleName = 'ADEssentials'; ModuleVersion = '0.0.148'; Guid = '9fc9fd61-7f11-4f4b-a527-084086f1905f' }
@{ ModuleName = 'PSWriteHTML'; ModuleVersion = "Latest"; Guid = 'a7bdf640-f5cb-4acf-9de0-365b322d245c' }
)
ExternalModuleDependencies = @(
#"ActiveDirectory"
#"GroupPolicy"
"CimCmdlets"
'Microsoft.PowerShell.Management'
'Microsoft.PowerShell.Utility'
'Microsoft.PowerShell.Security'
)
CommandModuleDependencies = @{
ActiveDirectory = @(
'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'
'Find-GPO'
'Get-GPOZaurrFilesPolicyDefinitions'
'Get-GPOZaurrSysvol'
'Remove-GPOZaurrOrphaned'
'Show-GPO'
'Show-GPOZaurr'
)
GroupPolicy = @(
'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'
'Find-GPO'
'Get-GPOZaurrFilesPolicyDefinitions'
'Get-GPOZaurrSysvol'
'Remove-GPOZaurrOrphaned'
'Show-GPO'
'Show-GPOZaurr'
)
}
}
ProjectUri = 'https://github.com/EvotecIT/GPOZaurr'
}
Options = @{
Merge = @{
Sort = 'None'
FormatCodePSM1 = @{
Enabled = $true
RemoveComments = $false
FormatterSettings = @{
IncludeRules = @(
'PSPlaceOpenBrace',
'PSPlaceCloseBrace',
'PSUseConsistentWhitespace',
'PSUseConsistentIndentation',
'PSAlignAssignmentStatement',
'PSUseCorrectCasing'
)
New-ConfigurationManifest @Manifest
Rules = @{
PSPlaceOpenBrace = @{
Enable = $true
OnSameLine = $true
NewLineAfter = $true
IgnoreOneLineBlock = $true
}
New-ConfigurationModule -Type RequiredModule -Name 'PSWriteColor', 'PSSharedGoods', 'ADEssentials', 'PSWriteHTML' -Guid Auto -Version Latest
#New-ConfigurationModule -Type ExternalModule -Name 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Management','Microsoft.PowerShell.Security'
New-ConfigurationModule -Type ApprovedModule -Name 'PSSharedGoods', 'PSWriteColor', 'Connectimo', 'PSUnifi', 'PSWebToolbox', 'PSMyPassword', 'ADEssentials'
PSPlaceCloseBrace = @{
Enable = $true
NewLineAfter = $false
IgnoreOneLineBlock = $true
NoEmptyLineBefore = $false
}
New-ConfigurationModule -Type ExternalModule -Name @(
"CimCmdlets"
'Microsoft.PowerShell.Management'
'Microsoft.PowerShell.Utility'
'Microsoft.PowerShell.Security'
)
PSUseConsistentIndentation = @{
Enable = $true
Kind = 'space'
PipelineIndentation = 'IncreaseIndentationAfterEveryPipeline'
IndentationSize = 4
}
New-ConfigurationModuleSkip -IgnoreModuleName @(
# this are builtin into PowerShell, so not critical
'powershellget'
'GroupPolicy'
'ScheduledTasks'
'ActiveDirectory'
'Microsoft.WSMan.Management'
'NetConnection'
'NetSecurity'
'NetTCPIP'
) -IgnoreFunctionName @(
'Select-Unique'
)
PSUseConsistentWhitespace = @{
Enable = $true
CheckInnerBrace = $true
CheckOpenBrace = $true
CheckOpenParen = $true
CheckOperator = $true
CheckPipe = $true
CheckSeparator = $true
}
New-ConfigurationCommand -ModuleName 'ActiveDirectory' -CommandName @(
'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'
'Find-GPO'
'Get-GPOZaurrFilesPolicyDefinitions'
'Get-GPOZaurrSysvol'
'Remove-GPOZaurrOrphaned'
'Show-GPO'
'Show-GPOZaurr'
)
New-ConfigurationCommand -ModuleName 'GroupPolicy' -CommandName @(
'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'
'Find-GPO'
'Get-GPOZaurrFilesPolicyDefinitions'
'Get-GPOZaurrSysvol'
'Remove-GPOZaurrOrphaned'
'Show-GPO'
'Show-GPOZaurr'
)
PSAlignAssignmentStatement = @{
Enable = $true
CheckHashtable = $true
}
PSUseCorrectCasing = @{
Enable = $true
}
}
}
}
FormatCodePSD1 = @{
Enabled = $true
RemoveComments = $false
}
Integrate = @{
ApprovedModules = 'PSSharedGoods', 'PSWriteColor', 'Connectimo', 'PSUnifi', 'PSWebToolbox', 'PSMyPassword', 'ADEssentials'
}
}
Standard = @{
FormatCodePSM1 = @{
$ConfigurationFormat = [ordered] @{
RemoveComments = $true
RemoveEmptyLines = $true
}
FormatCodePSD1 = @{
Enabled = $true
#RemoveComments = $true
}
}
PowerShellGallery = @{
ApiKey = 'C:\Support\Important\PowerShellGalleryAPI.txt'
FromFile = $true
}
GitHub = @{
ApiKey = 'C:\Support\Important\GithubAPI.txt'
FromFile = $true
UserName = 'EvotecIT'
#RepositoryName = 'PSPublishModule' # not required, uses project name
}
Documentation = @{
Path = 'Docs'
PathReadme = 'Docs\Readme.md'
}
Style = @{
PSD1 = 'Minimal' # Native
}
PlaceOpenBraceEnable = $true
PlaceOpenBraceOnSameLine = $true
PlaceOpenBraceNewLineAfter = $true
PlaceOpenBraceIgnoreOneLineBlock = $false
PlaceCloseBraceEnable = $true
PlaceCloseBraceNewLineAfter = $true
PlaceCloseBraceIgnoreOneLineBlock = $false
PlaceCloseBraceNoEmptyLineBefore = $true
UseConsistentIndentationEnable = $true
UseConsistentIndentationKind = 'space'
UseConsistentIndentationPipelineIndentation = 'IncreaseIndentationAfterEveryPipeline'
UseConsistentIndentationIndentationSize = 4
UseConsistentWhitespaceEnable = $true
UseConsistentWhitespaceCheckInnerBrace = $true
UseConsistentWhitespaceCheckOpenBrace = $true
UseConsistentWhitespaceCheckOpenParen = $true
UseConsistentWhitespaceCheckOperator = $true
UseConsistentWhitespaceCheckPipe = $true
UseConsistentWhitespaceCheckSeparator = $true
AlignAssignmentStatementEnable = $true
AlignAssignmentStatementCheckHashtable = $true
UseCorrectCasingEnable = $true
}
Steps = @{
BuildModule = @{ # requires Enable to be on to process all of that
Enable = $true
DeleteBefore = $false
Merge = $true
MergeMissing = $true
SignMerged = $true
Releases = $true
ReleasesUnpacked = $false
RefreshPSD1Only = $false
}
BuildDocumentation = @{
Enable = $true # enables documentation processing
StartClean = $true # always starts clean
UpdateWhenNew = $true # always updates right after new
}
ImportModules = @{
Self = $true
RequiredModules = $false
Verbose = $false
}
PublishModule = @{ # requires Enable to be on to process all of that
Enabled = $true
Prerelease = ''
RequireForce = $false
GitHub = $true
}
}
}
# format PSD1 and PSM1 files when merging into a single file
# enable formatting is not required as Configuration is provided
New-ConfigurationFormat -ApplyTo 'OnMergePSM1', 'OnMergePSD1' -Sort None @ConfigurationFormat
# format PSD1 and PSM1 files within the module
# enable formatting is required to make sure that formatting is applied (with default settings)
New-ConfigurationFormat -ApplyTo 'DefaultPSD1', 'DefaultPSM1' -EnableFormatting -Sort None
# when creating PSD1 use special style without comments and with only required parameters
New-ConfigurationFormat -ApplyTo 'DefaultPSD1', 'OnMergePSD1' -PSD1Style 'Minimal'
# configuration for documentation, at the same time it enables documentation processing
New-ConfigurationDocumentation -Enable:$false -StartClean -UpdateWhenNew -PathReadme 'Docs\Readme.md' -Path 'Docs'
New-PrepareModule -Configuration $Configuration
New-ConfigurationImportModule -ImportSelf
New-ConfigurationBuild -Enable:$true -SignModule -MergeModuleOnBuild -MergeFunctionsFromApprovedModules -CertificateThumbprint '483292C9E317AA13B07BB7A96AE9D1A5ED9E7703'
# New-ConfigurationTest -TestsPath "$PSScriptRoot\..\Tests" -Enable
New-ConfigurationArtefact -Type Unpacked -Enable -Path "$PSScriptRoot\..\Artefacts\Unpacked" -AddRequiredModules
New-ConfigurationArtefact -Type Packed -Enable -Path "$PSScriptRoot\..\Artefacts\Packed" -ArtefactName '<ModuleName>.v<ModuleVersion>.zip' -AddRequiredModules
# options for publishing to github/psgallery
#New-ConfigurationPublish -Type PowerShellGallery -FilePath 'C:\Support\Important\PowerShellGalleryAPI.txt' -Enabled:$true
#New-ConfigurationPublish -Type GitHub -FilePath 'C:\Support\Important\GitHubAPI.txt' -UserName 'EvotecIT' -Enabled:$true
} -ExitCode
+40
View File
@@ -1,5 +1,45 @@
# GPOZaurr Release History
## 1.1.4 - 2024.06.11
- Small improvements & fixes
## 1.1.3 - 2024.04.16
- Fixes report showing unessecary `WhatIf` [#53](https://github.com/EvotecIT/GPOZaurr/issues/53)
## 1.1.2 - 2024.04.16
- Fixes `Forest` parameter for GPOAnalysis [#54](https://github.com/EvotecIT/GPOZaurr/issues/54)
## 1.1.1 - 2024.02.07
- Force specific DC for `Invoke-GPOZaurrContent`
- Update to Duplicate Object detection for error handling [#52](https://github.com/EvotecIT/GPOZaurr/issues/52)
## 1.1.0 - 2024.04.02
- Improve `Invoke-GPOZaurr` - by adding `GPOName` and `GPOGUID` parameters, providing ability to analyse single/multiple GPOs
- Those parameters are only applicable to `GPOAnalysis`,`GPOBrokenPartially` for now (need to be expanded further)
- Improve `Invoke-GPOZaurrContent` by allowing `GPOName` and `GPOGUID` parameters, providing ability to analyse single/multiple GPOs
- Small verbose message improvement for `Export-GPOZaurrContent`
- Added `Get-GPOZaurrMissingFiles` to detect missing files for GPOs
- Added `Invoke-GPOZaurr` - type `GPOBrokenPartially` to detect missing files for GPOs
- Improve detection of empty GPOs by including check for GPF files
- Added `FilesCount` to `Get-GPOZaurr` to detect number of files in GPO
## 1.0.0 - 2023.09.17
- `Get-GPOZaurrUpdates` fix small typo
- `Get-GPOZaurrAD` improve performance a bit
- `Get-GPOZaurrAD` changed pipeline into standard foreach to improve performance and potential problems for large domains
- Added `Get-GPOZaurrRedirect` to detect if GPO path was redirected (security issue)
- Added `GPORedirect` report type to `Invoke-GPOZaurr` to detect if GPO path was redirected (security issue)
## 0.0.160 - 2023.05.26
- Fixes `Remove-GPOZaurr` limit processing feature which would not stop in some cases
## 0.0.159
- Fixes [#44 Extra spaces in property name 'Id' in Get-GPOZaurrPermissionConsistency?](https://github.com/EvotecIT/GPOZaurr/issues/44)
- Fixes typos [#43](https://github.com/EvotecIT/GPOZaurr/pull/43)
## 0.0.158 - 2023.03.07
- Improve detection of empty OUs by including AD printers.
## 0.0.157 - 2022.12.16
- Resolves *Group Policy Content - GPO Subfolders for Google Chrome* [#38](https://github.com/EvotecIT/GPOZaurr/issues/38)
- Resolves *Filename processing issue* [#37](https://github.com/EvotecIT/GPOZaurr/issues/37)
@@ -1,7 +1,11 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
# Remove GPOS
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -BackupDated -LimitProcessing 2 -Verbose -WhatIf
# Remove GPOS, but don't touch 2 defined exclusions
$ExcludeGroupPolicies = {
'TEST | Drive Mapping 1',
'TEST | Drive Mapping 2'
}
Remove-GPOZaurr -Type Empty -BackupPath "$Env:UserProfile\Desktop\GPO" -BackupDated -LimitProcessing 3 -Verbose -WhatIf -ExcludeGroupPolicies $ExcludeGroupPolicies
# Remove GPOS, but don't touch 2 defined exclusions
Remove-GPOZaurr -Type Empty, Unlinked -BackupPath "$Env:UserProfile\Desktop\GPO" -BackupDated -LimitProcessing 2 -Verbose -WhatIf {
@@ -1,3 +1,3 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
#Clear-Host
Remove-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 1 #-WhatIf
Remove-GPOZaurrPermission -Verbose -Type Unknown -LimitProcessing 5 -GPOName 'CA TEST'
+4
View File
@@ -0,0 +1,4 @@
Import-Module .\GPoZaurr.psd1 -Force
$Data = Invoke-GPOZaurr -Online -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPORedirect -PassThru
$Data.GPORedirect
+14
View File
@@ -0,0 +1,14 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
$Output = Invoke-GPOZaurrContent -Verbose -GPOName 'Default Domain Policy'
$Output | Format-Table
<#
# You need PSWriteOffice for that
foreach ($Key in $Output.Keys) {
$Output[$Key] | Export-OfficeExcel -FilePath $Env:USERPROFILE\Desktop\GPOAnalysis.xlsx -WorkSheetName $Key
}
Invoke-GPOZaurr -Type GPOAnalysis -GPOName 'ALL | Allow use of biometrics', 'ALL | Enable RDP' -GPOGUID '{31B2F340-016D-11D2-945F-00C04FB984F9}' -IncludeDomains 'ad.evotec.xyz' -Verbose
#>
@@ -0,0 +1,10 @@
Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force
# search by guid or name for specific GPOs
#Get-GPOZaurrMissingFiles -GPOGUID '{2F326111-C21B-4892-B7BC-9BDCB201FFCC}' | Format-Table
# search for all GPOs with missing files
#Get-GPOZaurrMissingFiles -BrokenOnly | Format-Table
# search for all GPOs with missing files for everythin
Invoke-GPOZaurr -Type GPOBrokenPartially #, GPOBroken, GPOBrokenLink
+15 -11
View File
@@ -4,31 +4,35 @@
CmdletsToExport = @()
CompanyName = 'Evotec'
CompatiblePSEditions = @('Desktop')
Copyright = '(c) 2011 - 2022 Przemyslaw Klys @ Evotec. All rights reserved.'
Copyright = '(c) 2011 - 2024 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', 'Export-GPOZaurrContent', 'Find-CSExtension', 'Get-GPOZaurr', 'Get-GPOZaurrAD', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrBroken', 'Get-GPOZaurrBrokenLink', 'Get-GPOZaurrDictionary', 'Get-GPOZaurrDuplicateObject', 'Get-GPOZaurrFiles', 'Get-GPOZaurrFilesPolicyDefinition', 'Get-GPOZaurrFolders', 'Get-GPOZaurrInheritance', 'Get-GPOZaurrLegacyFiles', 'Get-GPOZaurrLink', 'Get-GPOZaurrLinkSummary', 'Get-GPOZaurrNetLogon', 'Get-GPOZaurrOrganizationalUnit', 'Get-GPOZaurrOwner', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrPermissionAnalysis', 'Get-GPOZaurrPermissionConsistency', 'Get-GPOZaurrPermissionIssue', 'Get-GPOZaurrPermissionRoot', 'Get-GPOZaurrPermissionSummary', 'Get-GPOZaurrSysvolDFSR', 'Get-GPOZaurrUpdates', '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-GPOZaurrLinkEmptyOU', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Repair-GPOZaurrBrokenLink', 'Repair-GPOZaurrNetLogonOwner', 'Repair-GPOZaurrPermission', 'Repair-GPOZaurrPermissionConsistency', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOOwner', 'Set-GPOZaurrOwner', 'Set-GPOZaurrStatus', 'Skip-GroupPolicy')
FunctionsToExport = @('Add-GPOPermission', 'Add-GPOZaurrPermission', 'Backup-GPOZaurr', 'Clear-GPOZaurrSysvolDFSR', 'ConvertFrom-CSExtension', 'Export-GPOZaurrContent', 'Find-CSExtension', 'Get-GPOZaurr', 'Get-GPOZaurrAD', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrBroken', 'Get-GPOZaurrBrokenLink', 'Get-GPOZaurrDictionary', 'Get-GPOZaurrDuplicateObject', 'Get-GPOZaurrFiles', 'Get-GPOZaurrFilesPolicyDefinition', 'Get-GPOZaurrFolders', 'Get-GPOZaurrInheritance', 'Get-GPOZaurrLegacyFiles', 'Get-GPOZaurrLink', 'Get-GPOZaurrLinkSummary', 'Get-GPOZaurrMissingFiles', 'Get-GPOZaurrNetLogon', 'Get-GPOZaurrOrganizationalUnit', 'Get-GPOZaurrOwner', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrPermissionAnalysis', 'Get-GPOZaurrPermissionConsistency', 'Get-GPOZaurrPermissionIssue', 'Get-GPOZaurrPermissionRoot', 'Get-GPOZaurrPermissionSummary', 'Get-GPOZaurrRedirect', 'Get-GPOZaurrSysvolDFSR', 'Get-GPOZaurrUpdates', '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-GPOZaurrLinkEmptyOU', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Repair-GPOZaurrBrokenLink', 'Repair-GPOZaurrNetLogonOwner', 'Repair-GPOZaurrPermission', 'Repair-GPOZaurrPermissionConsistency', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOOwner', 'Set-GPOZaurrOwner', 'Set-GPOZaurrStatus', 'Skip-GroupPolicy')
GUID = 'f7d4c9e4-0298-4f51-ad77-e8e3febebbde'
ModuleVersion = '0.0.157'
ModuleVersion = '1.1.4'
PowerShellVersion = '5.1'
PrivateData = @{
PSData = @{
Tags = @('Windows', 'ActiveDirectory', 'GPO', 'GroupPolicy')
ProjectUri = 'https://github.com/EvotecIT/GPOZaurr'
ExternalModuleDependencies = @('CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Security')
ProjectUri = 'https://github.com/EvotecIT/GPOZaurr'
Tags = @('Windows', 'ActiveDirectory', 'GPO', 'GroupPolicy')
}
}
RequiredModules = @(@{
ModuleVersion = '0.0.253'
ModuleName = 'PSSharedGoods'
Guid = '0b0ba5c5-ec85-4c2b-a718-874e55a8bc3f'
ModuleName = 'PSWriteColor'
ModuleVersion = '1.0.1'
}, @{
Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
ModuleName = 'PSSharedGoods'
ModuleVersion = '0.0.291'
}, @{
ModuleVersion = '0.0.148'
ModuleName = 'ADEssentials'
Guid = '9fc9fd61-7f11-4f4b-a527-084086f1905f'
ModuleName = 'ADEssentials'
ModuleVersion = '0.0.213'
}, @{
ModuleVersion = '0.0.180'
ModuleName = 'PSWriteHTML'
Guid = 'a7bdf640-f5cb-4acf-9de0-365b322d245c'
ModuleName = 'PSWriteHTML'
ModuleVersion = '1.19.0'
}, 'CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Security')
RootModule = 'GPOZaurr.psm1'
}
+23 -4
View File
@@ -12,6 +12,8 @@
[System.Collections.IDictionary] $LinksSummaryCache
)
$SysvolGpoPath = "\\$($GPO.DomainName)\SYSVOL\$($GPO.DomainName)\Policies\{$($GPO.ID)}"
$DisplayName = $XMLContent.GPO.Name
$DomainName = $XMLContent.GPO.Identifier.Domain.'#text'
@@ -133,7 +135,7 @@
# in some cases GPResult seems to return an error - this was first noticed by user when using Dutch based system
# I am not sure if it's possible to fix this error for users, but once that happens checking if GPO is empty fails using the method below
# therefore we will use the old method of assuming something is empty or not empty in such case
Write-Warning "Get-XMLGPO - Reading GPO content [$DisplayName/$DomainName] returned an error. This may be because of non-english language. Assesing EMPTY using old method which can report false positives. Be careful please."
Write-Warning "Get-XMLGPO - Reading GPO content [$DisplayName/$DomainName] returned an error. This may be because of non-english language. Assessing EMPTY using old method which can report false positives. Be careful please."
$OutputUser = @()
$OutputComputer = @()
} else {
@@ -166,7 +168,20 @@
[bool] $UserSettingsAvailable = if ($OutputUser.Count -gt 0) { $true } else { $false }
}
if ($ComputerSettingsAvailable -eq $false -and $UserSettingsAvailable -eq $false) {
# Check if there are any GPF files in the GPO
# those are special files that are used to store settings for some applications (maily Citrix?)
# if there are any, then we can't say that GPO is empty, and they are not visible in the XML
$GPFFile = $false
$FilesCount = 0
Get-ChildItem -LiteralPath $SysvolGpoPath -Recurse -ErrorAction SilentlyContinue -File | ForEach-Object {
if ($_.Extension -eq '.gpf') {
#Write-Warning -Message "Get-XMLGPO - GPO [$DisplayName/$DomainName] has no data in XML, but it contains GPF files. Excluding from empty GPO list."
$GPFFile = $true
}
$FilesCount++
}
if ($ComputerSettingsAvailable -eq $false -and $UserSettingsAvailable -eq $false -and $GPFFile -eq $false) {
$Empty = $true
} else {
$Empty = $false
@@ -223,7 +238,7 @@
} elseif ($ADAdministrativeGroups) {
$OwnerType = 'Unknown'
} else {
$OwnerType = 'Unable to asses (local files?)'
$OwnerType = 'Unable to assess (local files?)'
}
}
# Mark GPO as excluded
@@ -257,6 +272,7 @@
'Inherited' = $false
'Permissions' = 'Owner'
'GPODistinguishedName' = $GPO.Path
'GPOSysvolPath' = $SysvolGpoPath
}
$XMLContent.GPO.SecurityDescriptor.Permissions.TrusteePermissions | ForEach-Object -Process {
if ($_) {
@@ -285,6 +301,7 @@
'OwnerSID' = $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text'
'OwnerType' = $OwnerType
'GPODistinguishedName' = $GPO.Path
'GPOSysvolPath' = $SysvolGpoPath
}
} else {
$GPOOutput = [PsCustomObject] @{
@@ -302,6 +319,7 @@
'Description' = $GPO.Description
'ComputerPolicies' = $XMLContent.GPO.Computer.ExtensionData.Name -join ", "
'UserPolicies' = $XMLContent.GPO.User.ExtensionData.Name -join ", "
'FilesCount' = $FilesCount
'LinksCount' = $LinksTotalCount
'LinksEnabledCount' = $LinksEnabledCount
'LinksDisabledCount' = $LinksDisabledCount
@@ -331,6 +349,7 @@
'WMIFilter' = $GPO.WmiFilter.name
'WMIFilterDescription' = $GPO.WmiFilter.Description
'GPODistinguishedName' = $GPO.Path
'GPOSysvolPath' = $SysvolGpoPath
'SDDL' = if ($Splitter -ne '') { $XMLContent.GPO.SecurityDescriptor.SDDL.'#text' -join $Splitter } else { $XMLContent.GPO.SecurityDescriptor.SDDL.'#text' }
'Owner' = $XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text'
'OwnerSID' = $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text'
@@ -398,4 +417,4 @@
}
}
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
ActionRequired = $null
Data = $null
Execute = {
Invoke-GPOZaurrContent -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
Invoke-GPOZaurrContent -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -GPOName $GPOName -GPOGUID $GPOGUID
}
Processing = {
@@ -5,9 +5,9 @@
Data = $null
Execute = {
if ($Script:Reporting['GPOBlockedInheritance']['Exclusions']) {
Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance -IncludeGroupPoliciesForBlockedObjects -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $Excludeomains -Exclusions $Script:Reporting['GPOBlockedInheritance']['Exclusions']
Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance -IncludeGroupPoliciesForBlockedObjects -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -Exclusions $Script:Reporting['GPOBlockedInheritance']['Exclusions']
} else {
Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance -IncludeGroupPoliciesForBlockedObjects -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $Excludeomains
Get-GPOZaurrInheritance -IncludeBlockedObjects -IncludeExcludedObjects -OnlyBlockedInheritance -IncludeGroupPoliciesForBlockedObjects -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
}
Processing = {
+79
View File
@@ -0,0 +1,79 @@
$GPOZaurrGPORedirects = [ordered] @{
Name = 'Group Policies With Redirected SYSVOL'
Enabled = $false
ActionRequired = $null
Data = $null
Execute = {
Get-GPOZaurrRedirect -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains
}
Processing = {
foreach ($GPO in $Script:Reporting['GPORedirect']['Data']) {
$Script:Reporting['GPORedirect']['Variables']['GPOTotal']++
if ($GPO.IsCorrect -eq $true) {
$Script:Reporting['GPORedirect']['Variables']['GPOIsCorrect']++
} else {
$Script:Reporting['GPORedirect']['Variables']['GPOIsNotCorrect']++
}
}
if ($Script:Reporting['GPORedirect']['Variables']['GPOIsNotCorrect'] -gt 0) {
$Script:Reporting['GPORedirect']['ActionRequired'] = $true
} else {
$Script:Reporting['GPORedirect']['ActionRequired'] = $false
}
}
Variables = @{
GPOTotal = 0
GPOIsCorrect = 0
GPOIsNotCorrect = 0
}
Overview = {
}
Summary = {
New-HTMLText -TextBlock {
"Group Policies are stored in Active Directory and SYSVOL. SYSVOL is a folder shared by the domain controllers to hold its logon scripts, "
"group policy data, and other domain-wide data which needs to be available anywhere there is a domain controller. "
"SYSVOL provides a default location for files that must be shared for common access throughout a domain. "
"However it is possible to redirect SYSVOL to a different location by modifying "
"gPCFileSysPath "
"attribute of a GPO. "
"This is not recommended and should be avoided, but it can also be a sign of compromise."
"This report shows which GPOs are redirected and which are not. "
} -FontSize 10pt -LineBreak -FontWeight normal, normal, normal, normal, bold, normal, normal, normal -Color None, None, None, None, RedBerry, None, None, None
New-HTMLList -Type Unordered {
New-HTMLListItem -Text 'Group Policies in total: ', $Script:Reporting['GPORedirect']['Variables']['GPOTotal'] -FontWeight normal, bold
New-HTMLListItem -Text 'Group Policies without redirects: ', $Script:Reporting['GPORedirect']['Variables']['GPOIsCorrect'] -FontWeight normal, bold -Color None, MintGreen
New-HTMLListItem -Text 'Group Policies with redirects: ', $Script:Reporting['GPORedirect']['Variables']['GPOIsNotCorrect'] -FontWeight normal, bold -Color None, RedBerry
} -FontSize 10pt
New-HTMLText -TextBlock {
"If you notice any GPO with redirect, you should investigate it. "
} -FontSize 10pt -LineBreak
}
Solution = {
New-HTMLSection -Invisible {
New-HTMLPanel {
& $Script:GPOConfiguration['GPORedirect']['Summary']
}
New-HTMLPanel {
New-HTMLChart {
New-ChartBarOptions -Type barStacked
New-ChartLegend -Name 'No redirects', 'With redirects' -Color MintGreen, MediumOrchid
New-ChartBar -Name 'No redirection' -Value $Script:Reporting['GPORedirect']['Variables']['GPOIsCorrect'], $Script:Reporting['GPORedirect']['Variables']['GPOIsNotCorrect']
} -Title 'Group Policies with redirects' -TitleAlignment center
}
}
New-HTMLSection -Name 'Group Policies showing redirects (if any)' {
New-HTMLTable -DataTable $Script:Reporting['GPORedirect']['Data'] -Filtering {
New-HTMLTableCondition -Name 'IsCorrect' -Value $false -BackgroundColor Salmon -ComparisonType bool -FailBackgroundColor MintGreen -HighlightHeaders 'IsCorrect', 'Path', 'ExpectedPath'
}
}
if ($Script:Reporting['GPORedirect']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
New-HTMLTable -DataTable $Script:Reporting['GPORedirect']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
}
}
}
}
}
+115
View File
@@ -0,0 +1,115 @@
$GPOZaurrMissingFiles = [ordered] @{
Name = 'Group Policies with missing files'
Enabled = $true
Action = $null
Data = $null
Execute = {
Get-GPOZaurrMissingFiles -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -GPOName $GPOName -GPOGUID $GPOGUID | Sort-Object -Property ErrorCount -Descending
}
Processing = {
foreach ($GPO in $Script:Reporting['GPOBrokenPartially']['Data']) {
if ($GPO.ErrorCount -gt 0) {
$Script:Reporting['GPOBrokenPartially']['Variables']['RequireFixing']++
}
}
if ($Script:Reporting['GPOBrokenPartially']['Variables']['RequireFixing'] -gt 0) {
$Script:Reporting['GPOBrokenPartially']['ActionRequired'] = $true
} else {
$Script:Reporting['GPOBrokenPartially']['ActionRequired'] = $false
}
}
Variables = @{
RequireFixing = 0
}
Overview = {
}
Resources = @(
)
Summary = {
New-HTMLText -FontSize 10pt -TextBlock {
"Group Policies can become broken for various reasons. One of the common reasons is when GPOs are created and then deleted without being properly removed from Active Directory. "
"In other cases it can be due to replication issues, or simply due to corruption. "
"This can lead to GPOs not being applied as expected, or not being applied at all. "
"If random files are missing from GPOs it's important to fix them to ensure that GPOs are applied as expected. "
"This report provides you with list of GPOs that have missing files. "
"Usually once files are missing it's best to restore them from backup (if available) or remove given section completly. "
"It's not possible to restore missing files from Active Directory directly or manually. "
} -LineBreak
New-HTMLText -Text 'As it stands currently there are ', $Script:Reporting['GPOBrokenPartially']['Variables']['RequireFixing'], ' error requring fixing. ' -FontSize 10pt -FontWeight normal, bold, normal
}
Solution = {
New-HTMLSection -Invisible {
New-HTMLPanel {
& $Script:GPOConfiguration['GPOBrokenPartially']['Summary']
}
New-HTMLPanel {
New-HTMLChart {
New-ChartLegend -Names 'Bad' -Color Salmon
New-ChartBar -Name 'Missing Files' -Value $Script:Reporting['GPOBrokenPartially']['Variables']['RequireFixing']
} -Title 'Group Policies with Missing Files' -TitleAlignment center
}
}
New-HTMLSection -Name 'Group Policy Missing Files' {
New-HTMLTable -DataTable $Script:Reporting['GPOBrokenPartially']['Data'] -Filtering {
New-HTMLTableCondition -Name 'ErrorCount' -Value 0 -BackgroundColor LightGreen -ComparisonType number -FailBackgroundColor Salmon -HighlightHeaders 'ErrorCount', 'ErrorCategory', 'ErrorDetails'
} -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\GPOZaurrMissingFilesBefore.html -Verbose -Type GPOMissingFiles
}
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-GPOZaurrMissingFiles -BrokenOnly
$GPOOutput | Format-Table # do your actions as desired
}
New-HTMLText -Text "It provides same data as you see in table above just doesn't prettify it for you."
}
New-HTMLWizardStep -Name 'Remove Broken objects' {
New-HTMLText -Text "There is no automated way to fix missing files. You need to manually fix them. "
New-HTMLText -Text "You can do so by restoring files from backup or removing section completly. "
}
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\GPOZaurrMissingFilesAfter.html -Verbose -Type GPOMissingFiles
}
New-HTMLText -Text "If everything is healthy in the report you're done! Enjoy rest of the day!" -Color BlueDiamond
}
} -RemoveDoneStepOnNavigateBack -Theme arrows -ToolbarButtonPosition center -EnableAllAnchors
}
}
}
}
if ($Script:Reporting['GPOBrokenPartially']['WarningsAndErrors']) {
New-HTMLSection -Name 'Warnings & Errors to Review' {
New-HTMLTable -DataTable $Script:Reporting['GPOZaurrMissingFiles']['WarningsAndErrors'] -Filtering {
New-HTMLTableCondition -Name 'Type' -Value 'Warning' -BackgroundColor SandyBrown -ComparisonType string -Row
New-HTMLTableCondition -Name 'Type' -Value 'Error' -BackgroundColor Salmon -ComparisonType string -Row
}
}
}
}
}
@@ -34,7 +34,7 @@
#$Script:Reporting['GPOOrganizationalUnit']['Variables']['WillFixPerDomain'][$OU.DomainName]++
} elseif ($OU.Status -contains 'Excluded' -or $OU.Status -contains 'Excluded, Default OU') {
$Script:Reporting['GPOOrganizationalUnit']['Variables']['Excluded']++
$Script:Reporting['GPOOrganizationalUnit']['Variables']['ExcludedOU'].Add($OU.Organizationalunit)
$null = $Script:Reporting['GPOOrganizationalUnit']['Variables']['ExcludedOU'].Add($OU.Organizationalunit)
} else {
$Script:Reporting['GPOOrganizationalUnit']['Variables']['Legitimate']++
}
@@ -52,6 +52,7 @@
DeleteOU = 0
Legitimate = 0
Excluded = 0
# Since we're using Copy-Dictionary this will get translated to Array List
ExcludedOU = [System.Collections.Generic.List[string]]::new()
WillFix = 0
WillFixPerDomain = $null
@@ -209,13 +210,13 @@
} -LineBreak
New-HTMLText -Text 'Once happy with results please follow with command (this will start removal process): ' -LineBreak -FontWeight bold
New-HTMLCodeBlock -Code {
Remove-GPOZaurrLinkEmptyOU -WhatIf -LimitProcessing 2 -Verbose
Remove-GPOZaurrLinkEmptyOU -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-GPOZaurrLinkEmptyOU -WhatIf -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
Remove-GPOZaurrLinkEmptyOU -LimitProcessing 2 -Verbose -IncludeDomains 'YourDomainYouHavePermissionsFor'
}
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. "
+2
View File
@@ -1,6 +1,7 @@
$Script:GPOConfiguration = [ordered] @{
GPOBroken = $GPOZaurrOrphans
GPOBrokenLink = $GPOZaurrBrokenLink
GPOBrokenPartially = $GPOZaurrMissingFiles
GPOOwners = $GPOZaurrOwners
GPOConsistency = $GPOZaurrConsistency
GPODuplicates = $GPOZaurrDuplicates
@@ -13,6 +14,7 @@
GPOPermissionsRead = $GPOZaurrPermissionsRead
GPOPermissionsRoot = $GPOZaurrPermissionsRoot
GPOPermissionsUnknown = $GPOZaurrPermissionsUnknown
GPORedirect = $GPOZaurrGPORedirects
GPOFiles = $GPOZaurrFiles
GPOBlockedInheritance = $GPOZaurrBlockedInheritance
GPOAnalysis = $GPOZaurrAnalysis
+1 -1
View File
@@ -33,7 +33,7 @@
$GPOs = Get-GPO -All -Domain $Domain
foreach ($GPO in $GPOS) {
$Count++
Write-Verbose -Message "Export-GPOZaurr - Exporting ($Count / $($GPOs.Count)) - $($GPO.DisplayName) to $ReportTypeF"
Write-Verbose -Message "Export-GPOZaurr - Exporting ($Count / $($GPOs.Count)) - $($GPO.DisplayName) to $ReportType"
$Name = "$($GPO.DomainName)_$($GPO.Id)_$($GPO.DisplayName).xml".Replace(" ", "_").Replace("|", "_")
$FullName = [io.path]::Combine($GPOOutput, $Name)
Get-GPOReport -Guid $GPO.Id -Domain $GPO.DomainName -ReportType $ReportType -Path $FullName
+21 -20
View File
@@ -63,7 +63,7 @@
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ((WhenChanged -ge $DateFrom -and WhenChanged -le $DateTo) -or (WhenCreated -ge $DateFrom -and WhenCreated -le $DateTo))')
} elseif ($DateProperty -eq 'WhenChanged' -or $DateProperty -eq 'WhenCreated') {
$Property = $DateProperty[0]
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ($Property -ge $DateFrom -and $Property -le $DateTo)')
$Splat['Filter'] = -join ($Splat['Filter'], " -and ($Property -ge $DateFrom -and $Property -le $DateTo)")
} else {
Write-Warning -Message "Get-GPOZaurrAD - DateProperty parameter is empty. Provide name and try again."
continue
@@ -75,7 +75,7 @@
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ((WhenChanged -ge $DateFrom -and WhenChanged -le $DateTo) -or (WhenCreated -ge $DateFrom -and WhenCreated -le $DateTo))')
} elseif ($DateProperty -eq 'WhenChanged' -or $DateProperty -eq 'WhenCreated') {
$Property = $DateProperty[0]
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ($Property -ge $DateFrom -and $Property -le $DateTo)')
$Splat['Filter'] = -join ($Splat['Filter'], " -and ($Property -ge $DateFrom -and $Property -le $DateTo)")
} else {
Write-Warning -Message "Get-GPOZaurrAD - DateProperty parameter is empty. Provide name and try again."
continue
@@ -85,26 +85,27 @@
}
Write-Verbose -Message "Get-GPOZaurrAD - Searching domain $Domain with filter $($Splat['Filter'])"
Get-ADObject @Splat -Properties DisplayName, Name, Created, Modified, ntSecurityDescriptor, gPCFileSysPath, gPCFunctionalityVersion, gPCWQLFilter, gPCMachineExtensionNames, Description, CanonicalName, DistinguishedName | ForEach-Object -Process {
$DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_.DistinguishedName -ToDomainCN
$GUID = $_.Name -replace '{' -replace '}'
$Objects = Get-ADObject @Splat -Properties DisplayName, Name, Created, Modified, ntSecurityDescriptor, gPCFileSysPath, gPCFunctionalityVersion, gPCWQLFilter, gPCMachineExtensionNames, Description, CanonicalName, DistinguishedName
foreach ($Object in $Objects) {
$DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $Object.DistinguishedName -ToDomainCN
$GUID = $Object.Name -replace '{' -replace '}'
if (($GUID).Length -ne 36) {
Write-Warning "Get-GPOZaurrAD - GPO GUID ($($($GUID.Replace("`n",' ')))) is incorrect. Skipping $($_.DisplayName) / Domain: $($DomainCN)"
Write-Warning "Get-GPOZaurrAD - GPO GUID ($($($GUID.Replace("`n",' ')))) is incorrect. Skipping $($Object.DisplayName) / Domain: $($DomainCN)"
} else {
$Output = [ordered]@{ }
$Output['DisplayName'] = $_.DisplayName
$Output['DomainName'] = $DomainCN
$Output['Description'] = $_.Description
$Output['GUID'] = $GUID
$Output['Path'] = $_.gPCFileSysPath
#$Output['FunctionalityVersion'] = $_.gPCFunctionalityVersion
$Output['Created'] = $_.Created
$Output['Modified'] = $_.Modified
$Output['Owner'] = $_.ntSecurityDescriptor.Owner
$Output['GPOCanonicalName'] = $_.CanonicalName
$Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_.DistinguishedName -ToDC
$Output['GPODistinguishedName'] = $_.DistinguishedName
[PSCustomObject] $Output
[PSCustomObject]@{
'DisplayName' = $Object.DisplayName
'DomainName' = $DomainCN
'Description' = $Object.Description
'GUID' = $GUID
'Path' = $Object.gPCFileSysPath
#$Output['FunctionalityVersion'] = $Object.gPCFunctionalityVersion
'Created' = $Object.Created
'Modified' = $Object.Modified
'Owner' = $Object.ntSecurityDescriptor.Owner
'GPOCanonicalName' = $Object.CanonicalName
'GPODomainDistinguishedName' = ConvertFrom-DistinguishedName -DistinguishedName $Object.DistinguishedName -ToDC
'GPODistinguishedName' = $Object.DistinguishedName
}
}
}
}
+4 -1
View File
@@ -15,6 +15,9 @@
.PARAMETER IncludeExcludedObjects
Show excluded objets. Default disabled
.PARAMETER IncludeGroupPoliciesForBlockedObjects
Include Group Policies for Blocked Objects. Default disabled
.PARAMETER Exclusions
Provide exclusions for OU's approved by IT. You can provide OU by canonical name or distinguishedName
@@ -69,7 +72,7 @@
}
if ($InheritanceInformation.BlockedInheritance -and $IncludeGroupPoliciesForBlockedObjects.IsPresent) {
try {
$GPInheritance = Get-GPInheritance -Target $OU.distinguishedName -ErrorAction Stop
$GPInheritance = Get-GPInheritance -Target $OU.distinguishedName -ErrorAction Stop -Domain $InheritanceInformation.DomainName
} catch {
Write-Warning -Message "Get-GPOZaurrInheritance - Can't get GPInheritance for $($OU.distinguishedName). Error: $($_.Exception.Message)"
continue
+52
View File
@@ -0,0 +1,52 @@
function Get-GPOZaurrMissingFiles {
[cmdletBinding()]
param(
[Parameter()][alias('ForestName')][string] $Forest,
[Parameter()][string[]] $ExcludeDomains,
[Parameter()][alias('Domain', 'Domains')][string[]] $IncludeDomains,
[Parameter()][System.Collections.IDictionary] $ExtendedForestInformation,
[Parameter()][Alias('Name')][string[]] $GPOName,
[Parameter()][string[]] $GPOGUID,
[switch] $BrokenOnly
)
Write-Verbose "Get-GPOZaurrMissingFiles - Query AD for GPOs"
if ($GPOName -or $GPOGUID) {
[Array] $GPOs = @(
foreach ($Name in $GPOName) {
Get-GPOZaurrAD -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -GPOName $Name
}
foreach ($GUID in $GPOGUID) {
Get-GPOZaurrAD -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -GPOGuid $GUID
}
)
} else {
[Array] $GPOs = Get-GPOZaurrAD -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
}
$Count = 0
foreach ($GPO in $GPOS) {
$Count++
Write-Verbose -Message "Get-GPOZaurrMissingFiles - Processing ($Count / $($GPOs.Count)) - $($GPO.DisplayName)"
#$Name = "$($GPO.DomainName)_$($GPO.Id)_$($GPO.DisplayName).xml".Replace(" ", "_").Replace("|", "_")
[xml] $GPOOutput = Get-GPOReport -Guid $GPO.GUID -Domain $GPO.DomainName -ReportType Xml
[Array] $ErrorsFound = foreach ($Type in @('User', 'Computer')) {
foreach ($Extension in $GPOOutput.GPO.$Type.ExtensionData) {
if ($Extension.Error) {
Write-Warning -Message "Get-GPOZaurrMissingFiles - $($GPO.DisplayName) - $($Extension.Name) - $($Extension.Error.Details)"
[ordered] @{ Category = $Extension.Name; Error = $Extension.Error.Details }
}
}
}
if ($BrokenOnly -and $ErrorsFound.Count -eq 0) {
continue
}
[PSCustomObject] @{
GPOName = $GPO.DisplayName
GPOGuid = $GPO.GUID
DomainName = $GPO.DomainName
ErrorCount = $ErrorsFound.Count
ErrorCategory = $ErrorsFound.Category
ErrorDetails = $ErrorsFound.Error
}
}
}
+1 -1
View File
@@ -96,7 +96,7 @@
$Object['Owner'] = $_.Owner # : EVOTEC\Enterprise Admins
$Object['Path'] = $_.Path
$Object['SysVolPath'] = $SysvolPath
$Object['Id '] = $_.Id # : 8a7bc515-d7fd-4d1f-90b8-e47c15f89295
$Object['Id'] = $_.Id # : 8a7bc515-d7fd-4d1f-90b8-e47c15f89295
$Object['GpoStatus'] = $_.GpoStatus # : AllSettingsEnabled
$Object['Description'] = $_.Description # :
$Object['CreationTime'] = $_.CreationTime # : 04.03.2020 17:19:42
+164
View File
@@ -0,0 +1,164 @@
function Get-GPOZaurrRedirect {
<#
.SYNOPSIS
Command to detect if GPOs have correct path in SYSVOL, or someone changed it manually.
.DESCRIPTION
Command to detect if GPOs have correct path in SYSVOL, or someone changed it manually.
.PARAMETER GPOName
Provide GPO name to search for. By default command returns all GPOs
.PARAMETER GPOGuid
Provide GPO GUID to search for. By default command returns all GPOs
.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 DateFrom
Provide a date from which to start the search, by default the last X days are used
.PARAMETER DateTo
Provide a date to which to end the search, by default the last X days are used
.PARAMETER DateRange
Provide a date range to search for, by default the last X days are used
.PARAMETER DateProperty
Choose a date property. It can be WhenCreated or WhenChanged or both. By default whenCreated is used for comparison purposes
.PARAMETER ExtendedForestInformation
Ability to provide Forest Information from another command to speed up processing
.EXAMPLE
Get-GPOZaurrRedirect | Format-Table
.NOTES
General notes
#>
[cmdletbinding(DefaultParameterSetName = 'Default')]
param(
[Parameter(ParameterSetName = 'GPOName')]
[string] $GPOName,
[Parameter(ParameterSetName = 'GPOGUID')]
[alias('GUID', 'GPOID')][string] $GPOGuid,
[alias('ForestName')][string] $Forest,
[string[]] $ExcludeDomains,
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[DateTime] $DateFrom,
[DateTime] $DateTo,
[ValidateSet('PastHour', 'CurrentHour', 'PastDay', 'CurrentDay', 'PastMonth', 'CurrentMonth', 'PastQuarter', 'CurrentQuarter', 'Last14Days', 'Last21Days', 'Last30Days', 'Last7Days', 'Last3Days', 'Last1Days')][string] $DateRange,
[ValidateSet('WhenCreated', 'WhenChanged')][string[]] $DateProperty = 'WhenCreated',
[System.Collections.IDictionary] $ExtendedForestInformation
)
Begin {
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
}
Process {
foreach ($Domain in $ForestInformation.Domains) {
if ($PSCmdlet.ParameterSetName -eq 'GPOGUID') {
if ($GPOGuid) {
if ($GPOGUID -notlike '*{*') {
$GUID = -join ("{", $GPOGUID, '}')
} else {
$GUID = $GPOGUID
}
$Splat = @{
Filter = "(objectClass -eq 'groupPolicyContainer') -and (Name -eq '$GUID')"
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
}
} else {
Write-Warning "Get-GPOZaurrRedirect - GPOGUID parameter is empty. Provide name and try again."
continue
}
} elseif ($PSCmdlet.ParameterSetName -eq 'GPOName') {
if ($GPOName) {
$Splat = @{
Filter = "(objectClass -eq 'groupPolicyContainer') -and (DisplayName -eq '$GPOName')"
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
}
} else {
Write-Warning "Get-GPOZaurrRedirect - GPOName parameter is empty. Provide name and try again."
continue
}
} else {
$Splat = @{
Filter = "(objectClass -eq 'groupPolicyContainer')"
Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0]
}
}
# allows to only get GPOs from a specific date range
if ($PSBoundParameters.ContainsKey('DateRange')) {
$Dates = Get-ChoosenDates -DateRange $DateRange
$DateFrom = $($Dates.DateFrom)
$DateTo = $($Dates.DateTo)
if ($DateProperty -contains 'WhenChanged' -and $DateProperty -contains 'WhenCreated') {
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ((WhenChanged -ge $DateFrom -and WhenChanged -le $DateTo) -or (WhenCreated -ge $DateFrom -and WhenCreated -le $DateTo))')
} elseif ($DateProperty -eq 'WhenChanged' -or $DateProperty -eq 'WhenCreated') {
$Property = $DateProperty[0]
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ($Property -ge $DateFrom -and $Property -le $DateTo)')
} else {
Write-Warning -Message "Get-GPOZaurrRedirect - DateProperty parameter is empty. Provide name and try again."
continue
}
} elseif ($PSBoundParameters.ContainsKey('DateFrom') -and $PSBoundParameters.ContainsKey('DateTo')) {
# already set $DateFrom,DateTo
#$Splat['Filter'] = -join ($Splat['Filter'], '-and ($DateProperty -ge $DateFrom -and $DateProperty -le $DateTo)')
if ($DateProperty -contains 'WhenChanged' -and $DateProperty -contains 'WhenCreated') {
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ((WhenChanged -ge $DateFrom -and WhenChanged -le $DateTo) -or (WhenCreated -ge $DateFrom -and WhenCreated -le $DateTo))')
} elseif ($DateProperty -eq 'WhenChanged' -or $DateProperty -eq 'WhenCreated') {
$Property = $DateProperty[0]
$Splat['Filter'] = -join ($Splat['Filter'], ' -and ($Property -ge $DateFrom -and $Property -le $DateTo)')
} else {
Write-Warning -Message "Get-GPOZaurrRedirect - DateProperty parameter is empty. Provide name and try again."
continue
}
} else {
# not needed
}
Write-Verbose -Message "Get-GPOZaurrRedirect - Searching domain $Domain with filter $($Splat['Filter'])"
$Objects = Get-ADObject @Splat -Properties DisplayName, Name, Created, Modified, ntSecurityDescriptor, gPCFileSysPath, gPCFunctionalityVersion, gPCWQLFilter, gPCMachineExtensionNames, Description, CanonicalName, DistinguishedName
foreach ($Object in $Objects) {
$DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $Object.DistinguishedName -ToDomainCN
$GUID = $Object.Name -replace '{' -replace '}'
if (($GUID).Length -ne 36) {
Write-Warning "Get-GPOZaurrRedirect - GPO GUID ($($($GUID.Replace("`n",' ')))) is incorrect. Skipping $($Object.DisplayName) / Domain: $($DomainCN)"
} else {
$Path = $Object.gPCFileSysPath
$ExpectedPath = "\\$($DomainCN)\SYSVOL\$($DomainCN)\Policies\{$($GUID)}"
$Compare = if ($Path -eq $ExpectedPath) { $true } else { $false }
[PSCustomObject]@{
'DisplayName' = $Object.DisplayName
'DomainName' = $DomainCN
'Description' = $Object.Description
'IsCorrect' = $Compare
'GUID' = $GUID
'Path' = $Path
'ExpectedPath' = $ExpectedPath
#$Output['FunctionalityVersion'] = $Object.gPCFunctionalityVersion
'Created' = $Object.Created
'Modified' = $Object.Modified
'Owner' = $Object.ntSecurityDescriptor.Owner
'GPOCanonicalName' = $Object.CanonicalName
'GPODomainDistinguishedName' = ConvertFrom-DistinguishedName -DistinguishedName $Object.DistinguishedName -ToDC
'GPODistinguishedName' = $Object.DistinguishedName
}
}
}
}
}
End {
}
}
+1 -1
View File
@@ -14,7 +14,7 @@
.PARAMETER IncludeDomains
Include only specific domains, by default whole forest is scanned
ą
.PARAMETER DateFrom
Provide a date from which to start the search, by default the last X days are used
+4 -1
View File
@@ -75,7 +75,10 @@
[string[]] $ExcludeDomains,
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
[switch] $Online,
[switch] $SplitReports
[switch] $SplitReports,
[Alias('Name')][string[]] $GPOName,
[Alias('GUID')][string[]] $GPOGUID
)
Reset-GPOZaurrStatus # This makes sure types are at it's proper status
+21 -3
View File
@@ -53,7 +53,13 @@
[Parameter(ParameterSetName = 'Local')]
[switch] $SkipCleanup,
[switch] $Extended
[switch] $Extended,
[Parameter(ParameterSetName = 'Default')]
[Alias('Name')][string[]] $GPOName,
[Parameter(ParameterSetName = 'Default')]
[string[]] $GPOGUID
)
if ($Type.Count -eq 0) {
$Type = $Script:GPODitionary.Keys
@@ -82,6 +88,16 @@
Write-Warning "Invoke-GPOZaurrContent - $GPOPath doesn't exists."
return
}
} elseif ($GPOName -or $GPOGUID) {
Write-Verbose "Invoke-GPOZaurrContent - Query AD for GPOs"
[Array] $GPOs = @(
foreach ($Name in $GPOName) {
Get-GPOZaurrAD -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -GPOName $Name
}
foreach ($GUID in $GPOGUID) {
Get-GPOZaurrAD -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -GPOGUID $GUID
}
)
} else {
Write-Verbose "Invoke-GPOZaurrContent - Query AD for GPOs"
[Array] $GPOs = Get-GPOZaurrAD -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
@@ -94,6 +110,8 @@
$Output['Reports'] = [ordered] @{}
$Output['CategoriesFull'] = [ordered] @{}
$ForestInformation = Get-WinADForestDetails -PreferWritable -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
Write-Verbose "Invoke-GPOZaurrContent - Loading GPO Report to Categories"
$CountGPO = 0
[Array] $GPOCategories = foreach ($GPO in $GPOs) {
@@ -102,7 +120,8 @@
if ($GPOPath) {
$GPOOutput = $GPO.GPOOutput
} else {
[xml] $GPOOutput = Get-GPOReport -Guid $GPO.GUID -Domain $GPO.DomainName -ReportType Xml
$QueryServer = $ForestInformation['QueryServers'][$GPO.DomainName].HostName[0]
[xml] $GPOOutput = Get-GPOReport -Guid $GPO.GUID -Domain $GPO.DomainName -ReportType Xml -Server $QueryServer
}
Get-GPOCategories -GPO $GPO -GPOOutput $GPOOutput.GPO -Splitter $Splitter -FullObjects:$FullObjects -CachedCategories $Output['CategoriesFull']
}
@@ -223,7 +242,6 @@
}
$Output['PoliciesTotal'] = $Output.Reports.Policies.PolicyCategory | Group-Object | Select-Object Name, Count | Sort-Object -Property Name #-Descending
#$Output['PoliciesTotal'] = $Output.Reports.Policies.PolicyCategory | Group-Object | Select-Object Name, Count | Sort-Object -Property Count -Descending
if (-not $SkipCleanup) {
Write-Verbose "Invoke-GPOZaurrContent - Cleaning up output"
+8 -6
View File
@@ -22,11 +22,11 @@
$BackupFinalPath = $BackupPath
}
Write-Verbose "Remove-GPOZaurr - Backing up to $BackupFinalPath"
$null = New-Item -ItemType Directory -Path $BackupFinalPath -Force
$null = New-Item -ItemType Directory -Path $BackupFinalPath -Force -WhatIf:$false
} else {
$BackupRequired = $false
}
$Count = 0
$CountProcessedGPO = 0
}
Process {
$getGPOZaurrSplat = @{
@@ -39,6 +39,11 @@
}
Get-GPOZaurr @getGPOZaurrSplat | ForEach-Object {
if ($LimitProcessing -ne 0 -and $CountProcessedGPO -ge $LimitProcessing) {
Write-Warning -Message "Remove-GPOZaurr - LimitProcessing ($CountProcessedGPO / $LimitProcessing) reached. Stopping processing"
break
}
$DeleteRequired = $false
if ($Type -contains 'Empty') {
@@ -89,10 +94,7 @@
Write-Warning "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)"
}
}
$Count++
if ($LimitProcessing -eq $Count) {
break
}
$CountProcessedGPO++
}
}
}