mirror of
https://github.com/EvotecIT/GPOZaurr.git
synced 2026-07-26 11:49:17 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b63e333fd0 | |||
| 9b0ab0c1c2 | |||
| ee3b25ee88 | |||
| 25c13b54aa | |||
| 2b9faa4e61 | |||
| 42f3053896 | |||
| edcba71e7f | |||
| c8ee2cca56 | |||
| 3b4617af83 | |||
| 6830b1e219 | |||
| 28c55deaa7 | |||
| c757c8281b | |||
| e3e5582696 | |||
| 8e2f4f1552 | |||
| 863c9fabc9 | |||
| 972b51b472 | |||
| 060fb95064 | |||
| fdfc700c6f | |||
| 81eaac3fd1 | |||
| cf9164766e | |||
| 4de2e2a57e | |||
| 663e6058e6 | |||
| f681a5586e | |||
| 4c022bfc16 | |||
| c03f158b77 | |||
| 4824633787 | |||
| 8dc7e5b26d | |||
| 68ed20f3e8 | |||
| df2bacdba7 | |||
| f67ade6341 | |||
| 5855ca2a7c |
@@ -0,0 +1,8 @@
|
||||
Ignore/*
|
||||
.vs/*
|
||||
.vscode/*
|
||||
Releases/*
|
||||
ReleasesUnpacked/*
|
||||
*.log
|
||||
*.html
|
||||
Artefacts/*
|
||||
+212
-276
@@ -1,290 +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.X.0'
|
||||
# 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', 'PSPublishModule'
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
Signing = @{
|
||||
CertificateThumbprint = '36A8A2D0E227D81A2D3B60DCE0CFCF23BEFC343B'
|
||||
}
|
||||
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 = $false
|
||||
Prerelease = ''
|
||||
RequireForce = $false
|
||||
GitHub = $false
|
||||
}
|
||||
}
|
||||
}
|
||||
# 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
|
||||
@@ -1,5 +1,26 @@
|
||||
# GPOZaurr Release History
|
||||
|
||||
## 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
|
||||
|
||||
|
||||
@@ -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'
|
||||
@@ -0,0 +1,4 @@
|
||||
Import-Module .\GPoZaurr.psd1 -Force
|
||||
|
||||
$Data = Invoke-GPOZaurr -Online -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPORedirect -PassThru
|
||||
$Data.GPORedirect
|
||||
@@ -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
|
||||
+14
-10
@@ -4,31 +4,35 @@
|
||||
CmdletsToExport = @()
|
||||
CompanyName = 'Evotec'
|
||||
CompatiblePSEditions = @('Desktop')
|
||||
Copyright = '(c) 2011 - 2023 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.159'
|
||||
ModuleVersion = '1.1.1'
|
||||
PowerShellVersion = '5.1'
|
||||
PrivateData = @{
|
||||
PSData = @{
|
||||
ExternalModuleDependencies = @('CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Security')
|
||||
ProjectUri = 'https://github.com/EvotecIT/GPOZaurr'
|
||||
Tags = @('Windows', 'ActiveDirectory', 'GPO', 'GroupPolicy')
|
||||
ExternalModuleDependencies = @('CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Security')
|
||||
}
|
||||
}
|
||||
RequiredModules = @(@{
|
||||
ModuleName = 'PSSharedGoods'
|
||||
ModuleVersion = '0.0.264'
|
||||
Guid = '0b0ba5c5-ec85-4c2b-a718-874e55a8bc3f'
|
||||
ModuleName = 'PSWriteColor'
|
||||
ModuleVersion = '1.0.1'
|
||||
}, @{
|
||||
Guid = 'ee272aa8-baaa-4edf-9f45-b6d6f7d844fe'
|
||||
ModuleName = 'PSSharedGoods'
|
||||
ModuleVersion = '0.0.276'
|
||||
}, @{
|
||||
ModuleName = 'ADEssentials'
|
||||
ModuleVersion = '0.0.148'
|
||||
Guid = '9fc9fd61-7f11-4f4b-a527-084086f1905f'
|
||||
ModuleName = 'ADEssentials'
|
||||
ModuleVersion = '0.0.186'
|
||||
}, @{
|
||||
ModuleName = 'PSWriteHTML'
|
||||
ModuleVersion = '0.0.188'
|
||||
Guid = 'a7bdf640-f5cb-4acf-9de0-365b322d245c'
|
||||
ModuleName = 'PSWriteHTML'
|
||||
ModuleVersion = '1.17.0'
|
||||
}, 'CimCmdlets', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Security')
|
||||
RootModule = 'GPOZaurr.psm1'
|
||||
}
|
||||
+20
-1
@@ -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'
|
||||
|
||||
@@ -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
|
||||
@@ -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'
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
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"
|
||||
|
||||
Reference in New Issue
Block a user